1use crate::account::{AccessKey, AccessKeyPermission, Account, FunctionCallPermission};
7use crate::action::delegate::{DelegateAction, SignedDelegateAction};
8use crate::action::{
9 DeployGlobalContractAction, DeterministicStateInitAction, GlobalContractDeployMode,
10 GlobalContractIdentifier, UseGlobalContractAction,
11};
12use crate::bandwidth_scheduler::BandwidthRequests;
13use crate::block::{Block, BlockHeader, Tip};
14use crate::block_header::BlockHeaderInnerLite;
15use crate::challenge::SlashedValidator;
16use crate::congestion_info::{CongestionInfo, CongestionInfoV1};
17use crate::errors::TxExecutionError;
18use crate::hash::{CryptoHash, hash};
19use crate::merkle::{MerklePath, combine_hash};
20use crate::network::PeerId;
21use crate::receipt::{
22 ActionReceipt, ActionReceiptV2, DataReceipt, DataReceiver, GlobalContractDistributionReceipt,
23 Receipt, ReceiptEnum, ReceiptV1, VersionedActionReceipt, VersionedReceiptEnum,
24};
25use crate::serialize::dec_format;
26use crate::sharding::shard_chunk_header_inner::ShardChunkHeaderInnerV4;
27use crate::sharding::{
28 ChunkHash, ShardChunk, ShardChunkHeader, ShardChunkHeaderInner, ShardChunkHeaderInnerV2,
29 ShardChunkHeaderInnerV3, ShardChunkHeaderV3,
30};
31use crate::stateless_validation::chunk_endorsements_bitmap::ChunkEndorsementsBitmap;
32use crate::transaction::{
33 Action, AddKeyAction, CreateAccountAction, DeleteAccountAction, DeleteKeyAction,
34 DeployContractAction, ExecutionMetadata, ExecutionOutcome, ExecutionOutcomeWithIdAndProof,
35 ExecutionStatus, FunctionCallAction, PartialExecutionOutcome, PartialExecutionStatus,
36 SignedTransaction, StakeAction, TransferAction,
37};
38use crate::types::{
39 AccountId, AccountWithPublicKey, Balance, BlockHeight, EpochHeight, EpochId, FunctionArgs, Gas,
40 Nonce, NumBlocks, ShardId, StateChangeCause, StateChangeKind, StateChangeValue,
41 StateChangeWithCause, StateChangesRequest, StateRoot, StorageUsage, StoreKey, StoreValue,
42 ValidatorKickoutReason,
43};
44use crate::version::{ProtocolVersion, Version};
45use borsh::{BorshDeserialize, BorshSerialize};
46use near_crypto::{PublicKey, Signature};
47use near_fmt::{AbbrBytes, Slice};
48use near_parameters::config::CongestionControlConfig;
49use near_parameters::view::CongestionControlConfigView;
50use near_parameters::{ActionCosts, ExtCosts};
51use near_primitives_core::account::{AccountContract, GasKey};
52use near_primitives_core::deterministic_account_id::{
53 DeterministicAccountStateInit, DeterministicAccountStateInitV1,
54};
55use near_primitives_core::types::NonceIndex;
56use near_schema_checker_lib::ProtocolSchema;
57use near_time::Utc;
58use serde_with::base64::Base64;
59use serde_with::serde_as;
60use std::collections::{BTreeMap, HashMap};
61use std::fmt;
62use std::ops::Range;
63use std::sync::Arc;
64use strum::IntoEnumIterator;
65use validator_stake_view::ValidatorStakeView;
66
67#[derive(serde::Serialize, serde::Deserialize, Debug, Eq, PartialEq, Clone)]
69#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
70pub struct AccountView {
71 pub amount: Balance,
72 pub locked: Balance,
73 pub code_hash: CryptoHash,
74 pub storage_usage: StorageUsage,
75 #[serde(default)]
77 pub storage_paid_at: BlockHeight,
78 #[serde(default, skip_serializing_if = "Option::is_none")]
79 pub global_contract_hash: Option<CryptoHash>,
80 #[serde(default, skip_serializing_if = "Option::is_none")]
81 pub global_contract_account_id: Option<AccountId>,
82}
83
84#[serde_as]
86#[derive(serde::Serialize, serde::Deserialize, PartialEq, Eq, Debug, Clone)]
87#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
88pub struct ContractCodeView {
89 #[serde(rename = "code_base64")]
90 #[serde_as(as = "Base64")]
91 #[cfg_attr(feature = "schemars", schemars(with = "String"))]
92 pub code: Vec<u8>,
93 pub hash: CryptoHash,
94}
95
96impl From<&Account> for AccountView {
97 fn from(account: &Account) -> Self {
98 let (global_contract_hash, global_contract_account_id) =
99 match account.contract().into_owned() {
100 AccountContract::Global(contract) => (Some(contract), None),
101 AccountContract::GlobalByAccount(account_id) => (None, Some(account_id)),
102 AccountContract::Local(_) | AccountContract::None => (None, None),
103 };
104 AccountView {
105 amount: account.amount(),
106 locked: account.locked(),
107 code_hash: account.local_contract_hash().unwrap_or_default(),
108 storage_usage: account.storage_usage(),
109 storage_paid_at: 0,
110 global_contract_hash,
111 global_contract_account_id,
112 }
113 }
114}
115
116impl From<Account> for AccountView {
117 fn from(account: Account) -> Self {
118 (&account).into()
119 }
120}
121
122impl From<&AccountView> for Account {
123 fn from(view: &AccountView) -> Self {
124 let contract = match &view.global_contract_account_id {
125 Some(account_id) => AccountContract::GlobalByAccount(account_id.clone()),
126 None => match view.global_contract_hash {
127 Some(hash) => AccountContract::Global(hash),
128 None => AccountContract::from_local_code_hash(view.code_hash),
129 },
130 };
131 Account::new(view.amount, view.locked, contract, view.storage_usage)
132 }
133}
134
135impl From<AccountView> for Account {
136 fn from(view: AccountView) -> Self {
137 (&view).into()
138 }
139}
140
141#[derive(
143 BorshSerialize,
144 BorshDeserialize,
145 Debug,
146 Eq,
147 PartialEq,
148 Clone,
149 serde::Serialize,
150 serde::Deserialize,
151)]
152#[borsh(use_discriminant = true)]
153#[repr(u8)]
154#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
155pub enum AccessKeyPermissionView {
156 FunctionCall { allowance: Option<Balance>, receiver_id: String, method_names: Vec<String> } = 0,
157 FullAccess = 1,
158}
159
160impl From<AccessKeyPermission> for AccessKeyPermissionView {
161 fn from(permission: AccessKeyPermission) -> Self {
162 match permission {
163 AccessKeyPermission::FunctionCall(func_call) => AccessKeyPermissionView::FunctionCall {
164 allowance: func_call.allowance,
165 receiver_id: func_call.receiver_id,
166 method_names: func_call.method_names,
167 },
168 AccessKeyPermission::FullAccess => AccessKeyPermissionView::FullAccess,
169 }
170 }
171}
172
173impl From<AccessKeyPermissionView> for AccessKeyPermission {
174 fn from(view: AccessKeyPermissionView) -> Self {
175 match view {
176 AccessKeyPermissionView::FunctionCall { allowance, receiver_id, method_names } => {
177 AccessKeyPermission::FunctionCall(FunctionCallPermission {
178 allowance,
179 receiver_id,
180 method_names,
181 })
182 }
183 AccessKeyPermissionView::FullAccess => AccessKeyPermission::FullAccess,
184 }
185 }
186}
187
188#[derive(
190 BorshSerialize,
191 BorshDeserialize,
192 Debug,
193 Eq,
194 PartialEq,
195 Clone,
196 serde::Serialize,
197 serde::Deserialize,
198)]
199#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
200pub struct AccessKeyView {
201 pub nonce: Nonce,
202 pub permission: AccessKeyPermissionView,
203}
204
205impl From<AccessKey> for AccessKeyView {
206 fn from(access_key: AccessKey) -> Self {
207 Self { nonce: access_key.nonce, permission: access_key.permission.into() }
208 }
209}
210
211impl From<AccessKeyView> for AccessKey {
212 fn from(view: AccessKeyView) -> Self {
213 Self { nonce: view.nonce, permission: view.permission.into() }
214 }
215}
216
217#[derive(
218 BorshSerialize,
219 BorshDeserialize,
220 Debug,
221 Eq,
222 PartialEq,
223 Clone,
224 serde::Serialize,
225 serde::Deserialize,
226)]
227#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
228pub struct GasKeyView {
229 pub num_nonces: NonceIndex,
230 pub balance: Balance,
231 pub permission: AccessKeyPermissionView,
232}
233
234impl From<GasKey> for GasKeyView {
235 fn from(gas_key: GasKey) -> Self {
236 Self {
237 num_nonces: gas_key.num_nonces,
238 balance: gas_key.balance,
239 permission: gas_key.permission.into(),
240 }
241 }
242}
243
244impl From<GasKeyView> for GasKey {
245 fn from(view: GasKeyView) -> Self {
246 Self {
247 num_nonces: view.num_nonces,
248 balance: view.balance,
249 permission: view.permission.into(),
250 }
251 }
252}
253
254#[derive(serde::Serialize, serde::Deserialize, Debug, PartialEq, Eq, Clone)]
256#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
257pub struct StateItem {
258 pub key: StoreKey,
259 pub value: StoreValue,
260}
261
262#[serde_as]
264#[derive(serde::Serialize, serde::Deserialize, Debug, PartialEq, Eq, Clone)]
265#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
266pub struct ViewStateResult {
267 pub values: Vec<StateItem>,
268 #[serde_as(as = "Vec<Base64>")]
269 #[serde(default, skip_serializing_if = "Vec::is_empty")]
270 #[cfg_attr(feature = "schemars", schemars(with = "Vec<String>"))]
271 pub proof: Vec<Arc<[u8]>>,
272}
273
274#[derive(serde::Serialize, serde::Deserialize, Debug, PartialEq, Eq, Clone, Default)]
276#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
277pub struct CallResult {
278 pub result: Vec<u8>,
279 pub logs: Vec<String>,
280}
281
282#[derive(serde::Serialize, serde::Deserialize, Debug, PartialEq, Eq, Clone)]
283pub struct QueryError {
284 pub error: String,
285 pub logs: Vec<String>,
286}
287
288#[derive(serde::Serialize, serde::Deserialize, Debug, PartialEq, Eq, Clone)]
290#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
291pub struct AccessKeyInfoView {
292 pub public_key: PublicKey,
293 pub access_key: AccessKeyView,
294}
295
296#[derive(serde::Serialize, serde::Deserialize, Debug, PartialEq, Eq, Clone)]
298#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
299pub struct AccessKeyList {
300 pub keys: Vec<AccessKeyInfoView>,
301}
302
303impl FromIterator<AccessKeyInfoView> for AccessKeyList {
304 fn from_iter<I: IntoIterator<Item = AccessKeyInfoView>>(iter: I) -> Self {
305 Self { keys: iter.into_iter().collect() }
306 }
307}
308
309#[cfg_attr(feature = "deepsize_feature", derive(deepsize::DeepSizeOf))]
311#[derive(serde::Serialize, serde::Deserialize, Debug, PartialEq, Eq, Clone)]
312#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
313pub struct KnownPeerStateView {
314 pub peer_id: PeerId,
315 pub status: String,
316 pub addr: String,
317 pub first_seen: i64,
318 pub last_seen: i64,
319 pub last_attempt: Option<(i64, String)>,
320}
321
322#[cfg_attr(feature = "deepsize_feature", derive(deepsize::DeepSizeOf))]
323#[derive(serde::Serialize, serde::Deserialize, Debug, PartialEq, Eq, Clone)]
324#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
325pub struct ConnectionInfoView {
326 pub peer_id: PeerId,
327 pub addr: String,
328 pub time_established: i64,
329 pub time_connected_until: i64,
330}
331
332#[cfg_attr(feature = "deepsize_feature", derive(deepsize::DeepSizeOf))]
333#[derive(serde::Serialize, serde::Deserialize, Debug, PartialEq, Eq, Clone)]
334#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
335pub struct SnapshotHostInfoView {
336 pub peer_id: PeerId,
337 pub sync_hash: CryptoHash,
338 pub epoch_height: u64,
339 pub shards: Vec<u64>,
340}
341
342#[cfg_attr(feature = "deepsize_feature", derive(deepsize::DeepSizeOf))]
343#[derive(Debug, PartialEq, Eq, Clone)]
344pub enum QueryResponseKind {
345 ViewAccount(AccountView),
346 ViewCode(ContractCodeView),
347 ViewState(ViewStateResult),
348 CallResult(CallResult),
349 AccessKey(AccessKeyView),
350 AccessKeyList(AccessKeyList),
351}
352
353#[derive(serde::Serialize, serde::Deserialize, Debug, PartialEq, Eq, Clone)]
354#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
355#[serde(tag = "request_type", rename_all = "snake_case")]
356pub enum QueryRequest {
357 ViewAccount {
358 account_id: AccountId,
359 },
360 ViewCode {
361 account_id: AccountId,
362 },
363 ViewState {
364 account_id: AccountId,
365 #[serde(rename = "prefix_base64")]
366 prefix: StoreKey,
367 #[serde(default, skip_serializing_if = "is_false")]
368 include_proof: bool,
369 },
370 ViewAccessKey {
371 account_id: AccountId,
372 public_key: PublicKey,
373 },
374 ViewAccessKeyList {
375 account_id: AccountId,
376 },
377 CallFunction {
378 account_id: AccountId,
379 method_name: String,
380 #[serde(rename = "args_base64")]
381 args: FunctionArgs,
382 },
383 ViewGlobalContractCode {
384 code_hash: CryptoHash,
385 },
386 ViewGlobalContractCodeByAccountId {
387 account_id: AccountId,
388 },
389}
390
391fn is_false(v: &bool) -> bool {
392 !*v
393}
394
395#[derive(Debug, PartialEq, Eq, Clone)]
396pub struct QueryResponse {
397 pub kind: QueryResponseKind,
398 pub block_height: BlockHeight,
399 pub block_hash: CryptoHash,
400}
401
402#[derive(serde::Serialize, serde::Deserialize, Debug)]
403#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
404pub struct StatusSyncInfo {
405 pub latest_block_hash: CryptoHash,
406 pub latest_block_height: BlockHeight,
407 pub latest_state_root: CryptoHash,
408 #[serde(with = "near_time::serde_utc_as_iso")]
409 #[cfg_attr(feature = "schemars", schemars(with = "String"))]
410 pub latest_block_time: Utc,
411 pub syncing: bool,
412 pub earliest_block_hash: Option<CryptoHash>,
413 pub earliest_block_height: Option<BlockHeight>,
414 #[serde(with = "near_time::serde_opt_utc_as_iso")]
415 #[cfg_attr(feature = "schemars", schemars(with = "Option<String>"))]
416 pub earliest_block_time: Option<Utc>,
417 pub epoch_id: Option<EpochId>,
418 pub epoch_start_height: Option<BlockHeight>,
419}
420
421#[derive(serde::Serialize, serde::Deserialize, Debug, PartialEq, Eq, Clone)]
423#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
424pub struct ValidatorInfo {
425 pub account_id: AccountId,
426}
427
428#[derive(serde::Serialize, serde::Deserialize, Debug, PartialEq, Eq)]
429#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
430pub struct PeerInfoView {
431 pub addr: String,
432 pub account_id: Option<AccountId>,
433 pub height: Option<BlockHeight>,
434 pub block_hash: Option<CryptoHash>,
435 pub is_highest_block_invalid: bool,
436 pub tracked_shards: Vec<ShardId>,
437 pub archival: bool,
438 pub peer_id: PublicKey,
439 pub received_bytes_per_sec: u64,
440 pub sent_bytes_per_sec: u64,
441 pub last_time_peer_requested_millis: u64,
442 pub last_time_received_message_millis: u64,
443 pub connection_established_time_millis: u64,
444 pub is_outbound_peer: bool,
445 pub nonce: u64,
447}
448
449#[derive(serde::Serialize, serde::Deserialize, Debug, PartialEq, Eq)]
452#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
453pub struct KnownProducerView {
454 pub account_id: AccountId,
455 pub peer_id: PublicKey,
456 pub next_hops: Option<Vec<PublicKey>>,
457}
458
459#[derive(serde::Serialize, serde::Deserialize, Debug, PartialEq, Eq)]
460#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
461pub struct Tier1ProxyView {
462 pub addr: std::net::SocketAddr,
463 pub peer_id: PublicKey,
464}
465
466#[derive(serde::Serialize, serde::Deserialize, Debug, PartialEq, Eq)]
478#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
479pub struct AccountDataView {
480 pub peer_id: PublicKey,
482 pub proxies: Vec<Tier1ProxyView>,
487 pub account_key: PublicKey,
489 #[serde(with = "near_time::serde_utc_as_iso")]
491 #[cfg_attr(feature = "schemars", schemars(with = "String"))]
492 pub timestamp: Utc,
493}
494
495#[derive(serde::Serialize, serde::Deserialize, Debug, PartialEq, Eq)]
496#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
497pub struct NetworkInfoView {
498 pub peer_max_count: u32,
499 pub num_connected_peers: usize,
500 pub connected_peers: Vec<PeerInfoView>,
501 pub known_producers: Vec<KnownProducerView>,
502 pub tier1_accounts_keys: Vec<PublicKey>,
503 pub tier1_accounts_data: Vec<AccountDataView>,
504 pub tier1_connections: Vec<PeerInfoView>,
505}
506
507#[derive(serde::Serialize, serde::Deserialize, Debug, PartialEq, Eq)]
508#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
509pub enum SyncStatusView {
510 AwaitingPeers,
512 NoSync,
514 EpochSync {
516 source_peer_height: BlockHeight,
517 source_peer_id: String,
518 attempt_time: String,
519 },
520 EpochSyncDone,
521 HeaderSync {
523 start_height: BlockHeight,
524 current_height: BlockHeight,
525 highest_height: BlockHeight,
526 },
527 StateSync(StateSyncStatusView),
529 StateSyncDone,
531 BlockSync {
533 start_height: BlockHeight,
534 current_height: BlockHeight,
535 highest_height: BlockHeight,
536 },
537}
538
539#[derive(serde::Serialize, serde::Deserialize, Debug, PartialEq, Eq)]
540#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
541pub struct StateSyncStatusView {
542 pub sync_hash: CryptoHash,
543 pub shard_sync_status: HashMap<ShardId, String>,
544 pub download_tasks: Vec<String>,
545 pub computation_tasks: Vec<String>,
546}
547
548#[derive(serde::Serialize, serde::Deserialize, Debug, PartialEq, Eq)]
549#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
550pub struct PeerStoreView {
551 pub peer_states: Vec<KnownPeerStateView>,
552}
553
554#[derive(serde::Serialize, serde::Deserialize, Debug, PartialEq, Eq)]
555#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
556pub struct RecentOutboundConnectionsView {
557 pub recent_outbound_connections: Vec<ConnectionInfoView>,
558}
559
560#[derive(serde::Serialize, serde::Deserialize, Debug, PartialEq, Eq)]
561#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
562pub struct SnapshotHostsView {
563 pub hosts: Vec<SnapshotHostInfoView>,
564}
565
566#[derive(serde::Serialize, serde::Deserialize, Debug, PartialEq, Eq)]
567#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
568pub struct EdgeView {
569 pub peer0: PeerId,
570 pub peer1: PeerId,
571 pub nonce: u64,
572}
573
574#[derive(serde::Serialize, serde::Deserialize, Debug, PartialEq, Eq)]
575#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
576pub struct NetworkGraphView {
577 pub edges: Vec<EdgeView>,
578 pub next_hops: HashMap<PeerId, Vec<PeerId>>,
579}
580
581#[derive(serde::Serialize, serde::Deserialize, Debug, PartialEq, Eq)]
582#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
583pub struct LabeledEdgeView {
584 pub peer0: u32,
585 pub peer1: u32,
586 pub nonce: u64,
587}
588
589#[derive(serde::Serialize, serde::Deserialize, Debug, PartialEq, Eq, Default)]
590#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
591pub struct EdgeCacheView {
592 pub peer_labels: HashMap<PeerId, u32>,
593 pub spanning_trees: HashMap<u32, Vec<LabeledEdgeView>>,
594}
595
596#[derive(serde::Serialize, serde::Deserialize, Debug, PartialEq, Eq)]
597#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
598pub struct PeerDistancesView {
599 pub distance: Vec<Option<u32>>,
600 pub min_nonce: u64,
601}
602
603#[derive(serde::Serialize, serde::Deserialize, Debug, PartialEq, Eq, Default)]
604#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
605pub struct NetworkRoutesView {
606 pub edge_cache: EdgeCacheView,
607 pub local_edges: HashMap<PeerId, EdgeView>,
608 pub peer_distances: HashMap<PeerId, PeerDistancesView>,
609 pub my_distances: HashMap<PeerId, u32>,
610}
611
612#[derive(serde::Serialize, serde::Deserialize, Debug, PartialEq, Eq)]
613#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
614pub struct ShardSyncDownloadView {
615 pub downloads: Vec<DownloadStatusView>,
616 pub status: String,
617}
618
619#[derive(serde::Serialize, serde::Deserialize, Debug, PartialEq, Eq)]
620#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
621pub struct DownloadStatusView {
622 pub error: bool,
623 pub done: bool,
624}
625
626#[derive(serde::Serialize, serde::Deserialize, Debug, PartialEq, Eq)]
628#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
629pub struct CatchupStatusView {
630 pub sync_block_hash: CryptoHash,
632 pub sync_block_height: BlockHeight,
633 pub shard_sync_status: HashMap<ShardId, String>,
635 pub blocks_to_catchup: Vec<BlockStatusView>,
637}
638
639#[derive(serde::Serialize, serde::Deserialize, Debug, PartialEq, Eq)]
640#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
641pub struct RequestedStatePartsView {
642 pub block_hash: CryptoHash,
644 pub shard_requested_parts: HashMap<ShardId, Vec<PartElapsedTimeView>>,
646}
647
648#[derive(serde::Serialize, serde::Deserialize, Debug, PartialEq, Eq)]
650#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
651pub struct BlockStatusView {
652 pub height: BlockHeight,
653 pub hash: CryptoHash,
654}
655
656impl BlockStatusView {
657 pub fn new(height: &BlockHeight, hash: &CryptoHash) -> BlockStatusView {
658 Self { height: *height, hash: *hash }
659 }
660}
661
662impl From<Tip> for BlockStatusView {
663 fn from(tip: Tip) -> Self {
664 Self { height: tip.height, hash: tip.last_block_hash }
665 }
666}
667
668impl From<&Tip> for BlockStatusView {
669 fn from(tip: &Tip) -> Self {
670 Self { height: tip.height, hash: tip.last_block_hash }
671 }
672}
673
674#[derive(serde::Serialize, serde::Deserialize, Debug, PartialEq, Eq, Clone)]
675#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
676pub struct PartElapsedTimeView {
677 pub part_id: u64,
678 pub elapsed_ms: u128,
679}
680
681impl PartElapsedTimeView {
682 pub fn new(part_id: &u64, elapsed_ms: u128) -> PartElapsedTimeView {
683 Self { part_id: *part_id, elapsed_ms }
684 }
685}
686
687#[derive(serde::Serialize, serde::Deserialize, Debug)]
688#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
689pub struct BlockByChunksView {
690 pub height: BlockHeight,
691 pub hash: CryptoHash,
692 pub block_status: String,
693 pub chunk_status: String,
694}
695
696#[derive(serde::Serialize, serde::Deserialize, Debug)]
697#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
698pub struct ChainProcessingInfo {
699 pub num_blocks_in_processing: usize,
700 pub num_orphans: usize,
701 pub num_blocks_missing_chunks: usize,
702 pub blocks_info: Vec<BlockProcessingInfo>,
704 pub floating_chunks_info: Vec<ChunkProcessingInfo>,
706}
707
708#[derive(serde::Serialize, serde::Deserialize, Debug)]
709#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
710pub struct BlockProcessingInfo {
711 pub height: BlockHeight,
712 pub hash: CryptoHash,
713 #[serde(with = "near_time::serde_utc_as_iso")]
714 #[cfg_attr(feature = "schemars", schemars(with = "String"))]
715 pub received_timestamp: Utc,
716 pub in_progress_ms: u128,
718 pub orphaned_ms: Option<u128>,
722 pub missing_chunks_ms: Option<u128>,
726 pub block_status: BlockProcessingStatus,
727 pub chunks_info: Vec<Option<ChunkProcessingInfo>>,
730}
731
732#[derive(
733 BorshSerialize,
734 BorshDeserialize,
735 Clone,
736 Debug,
737 PartialEq,
738 Eq,
739 serde::Serialize,
740 serde::Deserialize,
741)]
742#[borsh(use_discriminant = true)]
743#[repr(u8)]
744#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
745pub enum BlockProcessingStatus {
746 Orphan = 0,
747 WaitingForChunks = 1,
748 InProcessing = 2,
749 Accepted = 3,
750 Error(String) = 4,
751 Dropped(DroppedReason) = 5,
752 Unknown = 6,
753}
754
755#[derive(
756 BorshSerialize,
757 BorshDeserialize,
758 Clone,
759 Debug,
760 PartialEq,
761 Eq,
762 serde::Serialize,
763 serde::Deserialize,
764)]
765#[borsh(use_discriminant = true)]
766#[repr(u8)]
767#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
768pub enum DroppedReason {
769 HeightProcessed = 0,
771 TooManyProcessingBlocks = 1,
773}
774
775#[derive(serde::Serialize, serde::Deserialize, Debug)]
776#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
777pub struct ChunkProcessingInfo {
778 pub height_created: BlockHeight,
779 pub shard_id: ShardId,
780 pub chunk_hash: ChunkHash,
781 pub prev_block_hash: CryptoHash,
782 pub created_by: Option<AccountId>,
785 pub status: ChunkProcessingStatus,
786 #[serde(with = "near_time::serde_opt_utc_as_iso")]
788 #[cfg_attr(feature = "schemars", schemars(with = "Option<String>"))]
789 pub requested_timestamp: Option<Utc>,
790 #[serde(with = "near_time::serde_opt_utc_as_iso")]
792 #[cfg_attr(feature = "schemars", schemars(with = "Option<String>"))]
793 pub completed_timestamp: Option<Utc>,
794 pub request_duration: Option<u64>,
796 pub chunk_parts_collection: Vec<PartCollectionInfo>,
797}
798
799#[derive(serde::Serialize, serde::Deserialize, Debug)]
800#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
801pub struct PartCollectionInfo {
802 pub part_owner: AccountId,
803 #[serde(with = "near_time::serde_opt_utc_as_iso")]
805 #[cfg_attr(feature = "schemars", schemars(with = "Option<String>"))]
806 pub received_time: Option<Utc>,
807 #[serde(with = "near_time::serde_opt_utc_as_iso")]
809 #[cfg_attr(feature = "schemars", schemars(with = "Option<String>"))]
810 pub forwarded_received_time: Option<Utc>,
811 #[serde(with = "near_time::serde_opt_utc_as_iso")]
813 #[cfg_attr(feature = "schemars", schemars(with = "Option<String>"))]
814 pub chunk_received_time: Option<Utc>,
815}
816
817#[derive(serde::Serialize, serde::Deserialize, Debug)]
818#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
819pub enum ChunkProcessingStatus {
820 NeedToRequest,
821 Requested,
822 Completed,
823}
824
825#[derive(serde::Serialize, serde::Deserialize, Debug)]
826#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
827pub struct DetailedDebugStatus {
828 pub network_info: NetworkInfoView,
829 pub sync_status: String,
830 pub catchup_status: Vec<CatchupStatusView>,
831 pub current_head_status: BlockStatusView,
832 pub current_header_head_status: BlockStatusView,
833 pub block_production_delay_millis: u64,
834}
835
836#[derive(serde::Serialize, serde::Deserialize, Debug)]
838#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
839pub struct StatusResponse {
840 pub version: Version,
842 pub chain_id: String,
844 pub protocol_version: u32,
846 pub latest_protocol_version: u32,
848 #[serde(skip_serializing_if = "Option::is_none")]
850 pub rpc_addr: Option<String>,
851 pub validators: Vec<ValidatorInfo>,
853 pub sync_info: StatusSyncInfo,
855 pub validator_account_id: Option<AccountId>,
857 pub validator_public_key: Option<PublicKey>,
859 pub node_public_key: PublicKey,
861 pub node_key: Option<PublicKey>,
863 pub uptime_sec: i64,
865 pub genesis_hash: CryptoHash,
867 #[serde(skip_serializing_if = "Option::is_none")]
869 pub detailed_debug_status: Option<DetailedDebugStatus>,
870}
871
872#[derive(serde::Serialize, serde::Deserialize, Debug, Clone, Default)]
874#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
875pub struct BlockHeaderView {
876 pub height: BlockHeight,
877 pub prev_height: Option<BlockHeight>,
878 pub epoch_id: CryptoHash,
879 pub next_epoch_id: CryptoHash,
880 pub hash: CryptoHash,
881 pub prev_hash: CryptoHash,
883 pub prev_state_root: CryptoHash,
884 pub block_body_hash: Option<CryptoHash>,
885 pub chunk_receipts_root: CryptoHash,
886 pub chunk_headers_root: CryptoHash,
887 pub chunk_tx_root: CryptoHash,
888 pub outcome_root: CryptoHash,
889 pub chunks_included: u64,
890 pub challenges_root: CryptoHash,
891 pub timestamp: u64,
893 #[serde(with = "dec_format")]
894 #[cfg_attr(feature = "schemars", schemars(with = "String"))]
895 pub timestamp_nanosec: u64,
896 pub random_value: CryptoHash,
897 pub validator_proposals: Vec<ValidatorStakeView>,
898 pub chunk_mask: Vec<bool>,
899 pub gas_price: Balance,
900 pub block_ordinal: Option<NumBlocks>,
901 #[serde(default)]
903 pub rent_paid: Balance,
904 #[serde(default)]
906 pub validator_reward: Balance,
907 pub total_supply: Balance,
908 pub challenges_result: Vec<SlashedValidator>,
910 pub last_final_block: CryptoHash,
911 pub last_ds_final_block: CryptoHash,
912 pub next_bp_hash: CryptoHash,
913 pub block_merkle_root: CryptoHash,
914 pub epoch_sync_data_hash: Option<CryptoHash>,
915 pub approvals: Vec<Option<Box<Signature>>>,
916 pub signature: Signature,
918 pub latest_protocol_version: ProtocolVersion,
919 pub chunk_endorsements: Option<Vec<Vec<u8>>>,
920}
921
922impl From<&BlockHeader> for BlockHeaderView {
923 fn from(header: &BlockHeader) -> Self {
924 Self {
925 height: header.height(),
926 prev_height: header.prev_height(),
927 epoch_id: header.epoch_id().0,
928 next_epoch_id: header.next_epoch_id().0,
929 hash: *header.hash(),
930 prev_hash: *header.prev_hash(),
931 prev_state_root: *header.prev_state_root(),
932 block_body_hash: header.block_body_hash(),
933 chunk_receipts_root: *header.prev_chunk_outgoing_receipts_root(),
934 chunk_headers_root: *header.chunk_headers_root(),
935 chunk_tx_root: *header.chunk_tx_root(),
936 chunks_included: header.chunks_included(),
937 challenges_root: CryptoHash::default(),
938 outcome_root: *header.outcome_root(),
939 timestamp: header.raw_timestamp(),
940 timestamp_nanosec: header.raw_timestamp(),
941 random_value: *header.random_value(),
942 validator_proposals: header.prev_validator_proposals().map(Into::into).collect(),
943 chunk_mask: header.chunk_mask().to_vec(),
944 block_ordinal: if header.block_ordinal() != 0 {
945 Some(header.block_ordinal())
946 } else {
947 None
948 },
949 gas_price: header.next_gas_price(),
950 rent_paid: Balance::ZERO,
951 validator_reward: Balance::ZERO,
952 total_supply: header.total_supply(),
953 challenges_result: vec![],
954 last_final_block: *header.last_final_block(),
955 last_ds_final_block: *header.last_ds_final_block(),
956 next_bp_hash: *header.next_bp_hash(),
957 block_merkle_root: *header.block_merkle_root(),
958 epoch_sync_data_hash: header.epoch_sync_data_hash(),
959 approvals: header.approvals().to_vec(),
960 signature: header.signature().clone(),
961 latest_protocol_version: header.latest_protocol_version(),
962 chunk_endorsements: header.chunk_endorsements().map(|bitmap| bitmap.bytes()),
963 }
964 }
965}
966
967impl From<BlockHeaderView> for BlockHeader {
968 fn from(view: BlockHeaderView) -> Self {
969 BlockHeader::from_view(
970 &view.hash,
971 view.latest_protocol_version,
972 view.height,
973 view.prev_hash,
974 view.block_body_hash.unwrap_or_default(),
975 view.prev_state_root,
976 view.chunk_receipts_root,
977 view.chunk_headers_root,
978 view.chunk_tx_root,
979 view.outcome_root,
980 view.timestamp,
981 view.random_value,
982 view.validator_proposals.into_iter().map(|v| v.into_validator_stake()).collect(),
983 view.chunk_mask,
984 view.block_ordinal.unwrap_or(0),
985 EpochId(view.epoch_id),
986 EpochId(view.next_epoch_id),
987 view.gas_price,
988 view.total_supply,
989 view.signature,
990 view.last_final_block,
991 view.last_ds_final_block,
992 view.epoch_sync_data_hash,
993 view.approvals,
994 view.next_bp_hash,
995 view.block_merkle_root,
996 view.prev_height.unwrap_or_default(),
997 view.chunk_endorsements.map(|bytes| ChunkEndorsementsBitmap::from_bytes(bytes)),
998 )
999 }
1000}
1001
1002#[derive(
1004 PartialEq,
1005 Eq,
1006 Debug,
1007 Clone,
1008 BorshDeserialize,
1009 BorshSerialize,
1010 serde::Serialize,
1011 serde::Deserialize,
1012)]
1013#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
1014pub struct BlockHeaderInnerLiteView {
1015 pub height: BlockHeight,
1016 pub epoch_id: CryptoHash,
1018 pub next_epoch_id: CryptoHash,
1020 pub prev_state_root: CryptoHash,
1021 pub outcome_root: CryptoHash,
1022 pub timestamp: u64,
1024 #[serde(with = "dec_format")]
1025 #[cfg_attr(feature = "schemars", schemars(with = "String"))]
1026 pub timestamp_nanosec: u64,
1027 pub next_bp_hash: CryptoHash,
1029 pub block_merkle_root: CryptoHash,
1031}
1032
1033impl From<BlockHeader> for BlockHeaderInnerLiteView {
1034 fn from(header: BlockHeader) -> Self {
1035 let inner_lite = header.inner_lite();
1036 BlockHeaderInnerLiteView {
1037 height: inner_lite.height,
1038 epoch_id: inner_lite.epoch_id.0,
1039 next_epoch_id: inner_lite.next_epoch_id.0,
1040 prev_state_root: inner_lite.prev_state_root,
1041 outcome_root: inner_lite.prev_outcome_root,
1042 timestamp: inner_lite.timestamp,
1043 timestamp_nanosec: inner_lite.timestamp,
1044 next_bp_hash: inner_lite.next_bp_hash,
1045 block_merkle_root: inner_lite.block_merkle_root,
1046 }
1047 }
1048}
1049
1050impl From<BlockHeaderInnerLiteView> for BlockHeaderInnerLite {
1051 fn from(view: BlockHeaderInnerLiteView) -> Self {
1052 BlockHeaderInnerLite {
1053 height: view.height,
1054 epoch_id: EpochId(view.epoch_id),
1055 next_epoch_id: EpochId(view.next_epoch_id),
1056 prev_state_root: view.prev_state_root,
1057 prev_outcome_root: view.outcome_root,
1058 timestamp: view.timestamp_nanosec,
1059 next_bp_hash: view.next_bp_hash,
1060 block_merkle_root: view.block_merkle_root,
1061 }
1062 }
1063}
1064
1065#[derive(serde::Serialize, serde::Deserialize, Debug, Clone)]
1067#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
1068pub struct ChunkHeaderView {
1069 pub chunk_hash: CryptoHash,
1070 pub prev_block_hash: CryptoHash,
1071 pub outcome_root: CryptoHash,
1072 pub prev_state_root: StateRoot,
1073 pub encoded_merkle_root: CryptoHash,
1074 pub encoded_length: u64,
1075 pub height_created: BlockHeight,
1076 pub height_included: BlockHeight,
1077 pub shard_id: ShardId,
1078 pub gas_used: Gas,
1079 pub gas_limit: Gas,
1080 #[serde(default)]
1082 pub rent_paid: Balance,
1083 #[serde(default)]
1085 pub validator_reward: Balance,
1086 pub balance_burnt: Balance,
1087 pub outgoing_receipts_root: CryptoHash,
1088 pub tx_root: CryptoHash,
1089 pub validator_proposals: Vec<ValidatorStakeView>,
1090 pub congestion_info: Option<CongestionInfoView>,
1091 pub bandwidth_requests: Option<BandwidthRequests>,
1092 pub signature: Signature,
1093}
1094
1095impl ChunkHeaderView {
1096 pub fn is_new_chunk(&self, block_height: BlockHeight) -> bool {
1097 self.height_included == block_height
1098 }
1099}
1100
1101impl From<ShardChunkHeader> for ChunkHeaderView {
1102 fn from(chunk: ShardChunkHeader) -> Self {
1103 let hash = chunk.chunk_hash().0;
1104 let signature = chunk.signature().clone();
1105 let height_included = chunk.height_included();
1106 let inner = chunk.take_inner();
1107 ChunkHeaderView {
1108 chunk_hash: hash,
1109 prev_block_hash: *inner.prev_block_hash(),
1110 outcome_root: *inner.prev_outcome_root(),
1111 prev_state_root: if cfg!(feature = "protocol_feature_spice") {
1112 CryptoHash::default()
1113 } else {
1114 *inner.prev_state_root()
1115 },
1116 encoded_merkle_root: *inner.encoded_merkle_root(),
1117 encoded_length: inner.encoded_length(),
1118 height_created: inner.height_created(),
1119 height_included,
1120 shard_id: inner.shard_id(),
1121 gas_used: inner.prev_gas_used(),
1122 gas_limit: inner.gas_limit(),
1123 rent_paid: Balance::ZERO,
1124 validator_reward: Balance::ZERO,
1125 balance_burnt: inner.prev_balance_burnt(),
1126 outgoing_receipts_root: *inner.prev_outgoing_receipts_root(),
1127 tx_root: *inner.tx_root(),
1128 validator_proposals: inner.prev_validator_proposals().map(Into::into).collect(),
1129 congestion_info: Some(inner.congestion_info().into()),
1130 bandwidth_requests: inner.bandwidth_requests().cloned(),
1131 signature,
1132 }
1133 }
1134}
1135
1136impl From<ChunkHeaderView> for ShardChunkHeader {
1137 fn from(view: ChunkHeaderView) -> Self {
1138 match (view.bandwidth_requests, view.congestion_info) {
1139 (Some(bandwidth_requests), Some(congestion_info)) => {
1140 let mut header = ShardChunkHeaderV3 {
1141 inner: ShardChunkHeaderInner::V4(ShardChunkHeaderInnerV4 {
1142 prev_block_hash: view.prev_block_hash,
1143 prev_state_root: view.prev_state_root,
1144 prev_outcome_root: view.outcome_root,
1145 encoded_merkle_root: view.encoded_merkle_root,
1146 encoded_length: view.encoded_length,
1147 height_created: view.height_created,
1148 shard_id: view.shard_id,
1149 prev_gas_used: view.gas_used,
1150 gas_limit: view.gas_limit,
1151 prev_balance_burnt: view.balance_burnt,
1152 prev_outgoing_receipts_root: view.outgoing_receipts_root,
1153 tx_root: view.tx_root,
1154 prev_validator_proposals: view
1155 .validator_proposals
1156 .into_iter()
1157 .map(Into::into)
1158 .collect(),
1159 congestion_info: congestion_info.into(),
1160 bandwidth_requests,
1161 }),
1162 height_included: view.height_included,
1163 signature: view.signature,
1164 hash: ChunkHash::default(),
1165 };
1166 header.init();
1167 ShardChunkHeader::V3(header)
1168 }
1169 (None, Some(congestion_info)) => {
1170 let mut header = ShardChunkHeaderV3 {
1171 inner: ShardChunkHeaderInner::V3(ShardChunkHeaderInnerV3 {
1172 prev_block_hash: view.prev_block_hash,
1173 prev_state_root: view.prev_state_root,
1174 prev_outcome_root: view.outcome_root,
1175 encoded_merkle_root: view.encoded_merkle_root,
1176 encoded_length: view.encoded_length,
1177 height_created: view.height_created,
1178 shard_id: view.shard_id,
1179 prev_gas_used: view.gas_used,
1180 gas_limit: view.gas_limit,
1181 prev_balance_burnt: view.balance_burnt,
1182 prev_outgoing_receipts_root: view.outgoing_receipts_root,
1183 tx_root: view.tx_root,
1184 prev_validator_proposals: view
1185 .validator_proposals
1186 .into_iter()
1187 .map(Into::into)
1188 .collect(),
1189 congestion_info: congestion_info.into(),
1190 }),
1191 height_included: view.height_included,
1192 signature: view.signature,
1193 hash: ChunkHash::default(),
1194 };
1195 header.init();
1196 ShardChunkHeader::V3(header)
1197 }
1198 _ => {
1199 let mut header = ShardChunkHeaderV3 {
1200 inner: ShardChunkHeaderInner::V2(ShardChunkHeaderInnerV2 {
1201 prev_block_hash: view.prev_block_hash,
1202 prev_state_root: view.prev_state_root,
1203 prev_outcome_root: view.outcome_root,
1204 encoded_merkle_root: view.encoded_merkle_root,
1205 encoded_length: view.encoded_length,
1206 height_created: view.height_created,
1207 shard_id: view.shard_id,
1208 prev_gas_used: view.gas_used,
1209 gas_limit: view.gas_limit,
1210 prev_balance_burnt: view.balance_burnt,
1211 prev_outgoing_receipts_root: view.outgoing_receipts_root,
1212 tx_root: view.tx_root,
1213 prev_validator_proposals: view
1214 .validator_proposals
1215 .into_iter()
1216 .map(Into::into)
1217 .collect(),
1218 }),
1219 height_included: view.height_included,
1220 signature: view.signature,
1221 hash: ChunkHash::default(),
1222 };
1223 header.init();
1224 ShardChunkHeader::V3(header)
1225 }
1226 }
1227 }
1228}
1229
1230#[derive(serde::Serialize, serde::Deserialize, Debug, Clone)]
1231#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
1232pub struct BlockView {
1233 pub author: AccountId,
1235 pub header: BlockHeaderView,
1236 pub chunks: Vec<ChunkHeaderView>,
1237}
1238
1239impl BlockView {
1240 pub fn from_author_block(author: AccountId, block: &Block) -> Self {
1241 BlockView {
1242 author,
1243 header: block.header().into(),
1244 chunks: block.chunks().iter_raw().cloned().map(Into::into).collect(),
1245 }
1246 }
1247}
1248
1249#[derive(serde::Serialize, serde::Deserialize, Debug)]
1250#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
1251pub struct ChunkView {
1252 pub author: AccountId,
1253 pub header: ChunkHeaderView,
1254 pub transactions: Vec<SignedTransactionView>,
1255 pub receipts: Vec<ReceiptView>,
1256}
1257
1258impl ChunkView {
1259 pub fn from_author_chunk(author: AccountId, chunk: ShardChunk) -> Self {
1260 match chunk {
1261 ShardChunk::V1(chunk) => Self {
1262 author,
1263 header: ShardChunkHeader::V1(chunk.header).into(),
1264 transactions: chunk.transactions.into_iter().map(Into::into).collect(),
1265 receipts: chunk.prev_outgoing_receipts.into_iter().map(Into::into).collect(),
1266 },
1267 ShardChunk::V2(chunk) => Self {
1268 author,
1269 header: chunk.header.into(),
1270 transactions: chunk.transactions.into_iter().map(Into::into).collect(),
1271 receipts: chunk.prev_outgoing_receipts.into_iter().map(Into::into).collect(),
1272 },
1273 }
1274 }
1275}
1276
1277#[derive(
1278 BorshSerialize,
1279 BorshDeserialize,
1280 Clone,
1281 Debug,
1282 PartialEq,
1283 Eq,
1284 serde::Serialize,
1285 serde::Deserialize,
1286)]
1287#[serde(untagged, rename_all = "snake_case")]
1288#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
1289#[borsh(use_discriminant = true)]
1290#[repr(u8)]
1291pub enum GlobalContractIdentifierView {
1292 #[serde(rename = "hash")]
1293 CodeHash(CryptoHash) = 0,
1294 AccountId(AccountId) = 1,
1295}
1296
1297impl From<GlobalContractIdentifier> for GlobalContractIdentifierView {
1298 fn from(code: GlobalContractIdentifier) -> Self {
1299 match code {
1300 GlobalContractIdentifier::CodeHash(code_hash) => {
1301 GlobalContractIdentifierView::CodeHash(code_hash)
1302 }
1303 GlobalContractIdentifier::AccountId(account_id) => {
1304 GlobalContractIdentifierView::AccountId(account_id)
1305 }
1306 }
1307 }
1308}
1309
1310impl From<GlobalContractIdentifierView> for GlobalContractIdentifier {
1311 fn from(code: GlobalContractIdentifierView) -> Self {
1312 match code {
1313 GlobalContractIdentifierView::CodeHash(code_hash) => {
1314 GlobalContractIdentifier::CodeHash(code_hash)
1315 }
1316 GlobalContractIdentifierView::AccountId(account_id) => {
1317 GlobalContractIdentifier::AccountId(account_id)
1318 }
1319 }
1320 }
1321}
1322
1323#[serde_as]
1324#[derive(
1325 BorshSerialize,
1326 BorshDeserialize,
1327 Clone,
1328 Debug,
1329 PartialEq,
1330 Eq,
1331 serde::Serialize,
1332 serde::Deserialize,
1333)]
1334#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
1335#[borsh(use_discriminant = true)]
1336#[repr(u8)]
1337pub enum ActionView {
1338 CreateAccount = 0,
1339 DeployContract {
1340 #[serde_as(as = "Base64")]
1341 #[cfg_attr(
1342 feature = "schemars",
1343 schemars(schema_with = "crate::serialize::base64_schema")
1344 )]
1345 code: Vec<u8>,
1346 } = 1,
1347 FunctionCall {
1348 method_name: String,
1349 args: FunctionArgs,
1350 gas: Gas,
1351 deposit: Balance,
1352 } = 2,
1353 Transfer {
1354 deposit: Balance,
1355 } = 3,
1356 Stake {
1357 stake: Balance,
1358 public_key: PublicKey,
1359 } = 4,
1360 AddKey {
1361 public_key: PublicKey,
1362 access_key: AccessKeyView,
1363 } = 5,
1364 DeleteKey {
1365 public_key: PublicKey,
1366 } = 6,
1367 DeleteAccount {
1368 beneficiary_id: AccountId,
1369 } = 7,
1370 Delegate {
1371 delegate_action: DelegateAction,
1372 signature: Signature,
1373 } = 8,
1374 DeployGlobalContract {
1375 #[serde_as(as = "Base64")]
1376 #[cfg_attr(
1377 feature = "schemars",
1378 schemars(schema_with = "crate::serialize::base64_schema")
1379 )]
1380 code: Vec<u8>,
1381 } = 9,
1382 DeployGlobalContractByAccountId {
1383 #[serde_as(as = "Base64")]
1384 #[cfg_attr(
1385 feature = "schemars",
1386 schemars(schema_with = "crate::serialize::base64_schema")
1387 )]
1388 code: Vec<u8>,
1389 } = 10,
1390 UseGlobalContract {
1391 code_hash: CryptoHash,
1392 } = 11,
1393 UseGlobalContractByAccountId {
1394 account_id: AccountId,
1395 } = 12,
1396 DeterministicStateInit {
1397 code: GlobalContractIdentifierView,
1398 #[serde_as(as = "BTreeMap<Base64, Base64>")]
1399 #[cfg_attr(feature = "schemars", schemars(with = "BTreeMap<String, String>"))]
1400 data: BTreeMap<Vec<u8>, Vec<u8>>,
1401 deposit: Balance,
1402 } = 13,
1403}
1404
1405impl From<Action> for ActionView {
1406 fn from(action: Action) -> Self {
1407 match action {
1408 Action::CreateAccount(_) => ActionView::CreateAccount,
1409 Action::DeployContract(action) => {
1410 let code = hash(&action.code).as_ref().to_vec();
1411 ActionView::DeployContract { code }
1412 }
1413 Action::FunctionCall(action) => ActionView::FunctionCall {
1414 method_name: action.method_name,
1415 args: action.args.into(),
1416 gas: action.gas,
1417 deposit: action.deposit,
1418 },
1419 Action::Transfer(action) => ActionView::Transfer { deposit: action.deposit },
1420 Action::Stake(action) => {
1421 ActionView::Stake { stake: action.stake, public_key: action.public_key }
1422 }
1423 Action::AddKey(action) => ActionView::AddKey {
1424 public_key: action.public_key,
1425 access_key: action.access_key.into(),
1426 },
1427 Action::DeleteKey(action) => ActionView::DeleteKey { public_key: action.public_key },
1428 Action::DeleteAccount(action) => {
1429 ActionView::DeleteAccount { beneficiary_id: action.beneficiary_id }
1430 }
1431 Action::Delegate(action) => ActionView::Delegate {
1432 delegate_action: action.delegate_action,
1433 signature: action.signature,
1434 },
1435 Action::DeployGlobalContract(action) => {
1436 let code = hash(&action.code).as_ref().to_vec();
1437 match action.deploy_mode {
1438 GlobalContractDeployMode::CodeHash => ActionView::DeployGlobalContract { code },
1439 GlobalContractDeployMode::AccountId => {
1440 ActionView::DeployGlobalContractByAccountId { code }
1441 }
1442 }
1443 }
1444 Action::UseGlobalContract(action) => match action.contract_identifier {
1445 GlobalContractIdentifier::CodeHash(code_hash) => {
1446 ActionView::UseGlobalContract { code_hash }
1447 }
1448 GlobalContractIdentifier::AccountId(account_id) => {
1449 ActionView::UseGlobalContractByAccountId { account_id }
1450 }
1451 },
1452 Action::DeterministicStateInit(action) => {
1453 let (code, data) = action.state_init.take();
1454 let identifier = GlobalContractIdentifierView::from(code);
1455 ActionView::DeterministicStateInit {
1456 code: identifier,
1457 data,
1458 deposit: action.deposit,
1459 }
1460 }
1461 }
1462 }
1463}
1464
1465impl TryFrom<ActionView> for Action {
1466 type Error = Box<dyn std::error::Error + Send + Sync>;
1467
1468 fn try_from(action_view: ActionView) -> Result<Self, Self::Error> {
1469 Ok(match action_view {
1470 ActionView::CreateAccount => Action::CreateAccount(CreateAccountAction {}),
1471 ActionView::DeployContract { code } => {
1472 Action::DeployContract(DeployContractAction { code })
1473 }
1474 ActionView::FunctionCall { method_name, args, gas, deposit } => {
1475 Action::FunctionCall(Box::new(FunctionCallAction {
1476 method_name,
1477 args: args.into(),
1478 gas,
1479 deposit,
1480 }))
1481 }
1482 ActionView::Transfer { deposit } => Action::Transfer(TransferAction { deposit }),
1483 ActionView::Stake { stake, public_key } => {
1484 Action::Stake(Box::new(StakeAction { stake, public_key }))
1485 }
1486 ActionView::AddKey { public_key, access_key } => {
1487 Action::AddKey(Box::new(AddKeyAction { public_key, access_key: access_key.into() }))
1488 }
1489 ActionView::DeleteKey { public_key } => {
1490 Action::DeleteKey(Box::new(DeleteKeyAction { public_key }))
1491 }
1492 ActionView::DeleteAccount { beneficiary_id } => {
1493 Action::DeleteAccount(DeleteAccountAction { beneficiary_id })
1494 }
1495 ActionView::Delegate { delegate_action, signature } => {
1496 Action::Delegate(Box::new(SignedDelegateAction { delegate_action, signature }))
1497 }
1498 ActionView::DeployGlobalContract { code } => {
1499 Action::DeployGlobalContract(DeployGlobalContractAction {
1500 code: code.into(),
1501 deploy_mode: GlobalContractDeployMode::CodeHash,
1502 })
1503 }
1504 ActionView::DeployGlobalContractByAccountId { code } => {
1505 Action::DeployGlobalContract(DeployGlobalContractAction {
1506 code: code.into(),
1507 deploy_mode: GlobalContractDeployMode::AccountId,
1508 })
1509 }
1510 ActionView::UseGlobalContract { code_hash } => {
1511 Action::UseGlobalContract(Box::new(UseGlobalContractAction {
1512 contract_identifier: GlobalContractIdentifier::CodeHash(code_hash),
1513 }))
1514 }
1515 ActionView::UseGlobalContractByAccountId { account_id } => {
1516 Action::UseGlobalContract(Box::new(UseGlobalContractAction {
1517 contract_identifier: GlobalContractIdentifier::AccountId(account_id),
1518 }))
1519 }
1520 ActionView::DeterministicStateInit { code, data, deposit } => {
1521 let code = GlobalContractIdentifier::from(code);
1522 Action::DeterministicStateInit(Box::new(DeterministicStateInitAction {
1523 state_init: DeterministicAccountStateInit::V1(
1524 DeterministicAccountStateInitV1 { code, data },
1525 ),
1526 deposit,
1527 }))
1528 }
1529 })
1530 }
1531}
1532
1533#[derive(
1534 BorshSerialize,
1535 BorshDeserialize,
1536 Debug,
1537 PartialEq,
1538 Eq,
1539 Clone,
1540 serde::Serialize,
1541 serde::Deserialize,
1542)]
1543#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
1544pub struct SignedTransactionView {
1545 pub signer_id: AccountId,
1546 pub public_key: PublicKey,
1547 pub nonce: Nonce,
1548 pub receiver_id: AccountId,
1549 pub actions: Vec<ActionView>,
1550 #[serde(default)]
1554 pub priority_fee: u64,
1555 pub signature: Signature,
1556 pub hash: CryptoHash,
1557}
1558
1559impl From<SignedTransaction> for SignedTransactionView {
1560 fn from(signed_tx: SignedTransaction) -> Self {
1561 let hash = signed_tx.get_hash();
1562 let transaction = signed_tx.transaction;
1563 let priority_fee = transaction.priority_fee().unwrap_or_default();
1564 SignedTransactionView {
1565 signer_id: transaction.signer_id().clone(),
1566 public_key: transaction.public_key().clone(),
1567 nonce: transaction.nonce(),
1568 receiver_id: transaction.receiver_id().clone(),
1569 actions: transaction.take_actions().into_iter().map(|action| action.into()).collect(),
1570 signature: signed_tx.signature,
1571 hash,
1572 priority_fee,
1573 }
1574 }
1575}
1576
1577#[serde_as]
1578#[derive(
1579 BorshSerialize,
1580 BorshDeserialize,
1581 serde::Serialize,
1582 serde::Deserialize,
1583 PartialEq,
1584 Eq,
1585 Clone,
1586 Default,
1587)]
1588#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
1589#[borsh(use_discriminant = true)]
1590#[repr(u8)]
1591pub enum FinalExecutionStatus {
1592 #[default]
1594 NotStarted = 0,
1595 Started = 1,
1597 Failure(TxExecutionError) = 2,
1599 SuccessValue(
1601 #[serde_as(as = "Base64")]
1602 #[cfg_attr(feature = "schemars", schemars(with = "String"))]
1603 Vec<u8>,
1604 ) = 3,
1605}
1606
1607impl fmt::Debug for FinalExecutionStatus {
1608 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1609 match self {
1610 FinalExecutionStatus::NotStarted => f.write_str("NotStarted"),
1611 FinalExecutionStatus::Started => f.write_str("Started"),
1612 FinalExecutionStatus::Failure(e) => f.write_fmt(format_args!("Failure({:?})", e)),
1613 FinalExecutionStatus::SuccessValue(v) => {
1614 f.write_fmt(format_args!("SuccessValue({})", AbbrBytes(v)))
1615 }
1616 }
1617 }
1618}
1619
1620#[derive(
1621 BorshSerialize,
1622 BorshDeserialize,
1623 Debug,
1624 PartialEq,
1625 Eq,
1626 Clone,
1627 serde::Serialize,
1628 serde::Deserialize,
1629)]
1630#[borsh(use_discriminant = true)]
1631#[repr(u8)]
1632pub enum ServerError {
1633 TxExecutionError(TxExecutionError) = 0,
1634 Timeout = 1,
1635 Closed = 2,
1636}
1637
1638#[serde_as]
1639#[derive(
1640 BorshSerialize, BorshDeserialize, serde::Serialize, serde::Deserialize, PartialEq, Eq, Clone,
1641)]
1642#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
1643#[borsh(use_discriminant = true)]
1644#[repr(u8)]
1645pub enum ExecutionStatusView {
1646 Unknown = 0,
1648 Failure(TxExecutionError) = 1,
1650 SuccessValue(
1652 #[serde_as(as = "Base64")]
1653 #[cfg_attr(feature = "schemars", schemars(with = "String"))]
1654 Vec<u8>,
1655 ) = 2,
1656 SuccessReceiptId(CryptoHash) = 3,
1659}
1660
1661impl fmt::Debug for ExecutionStatusView {
1662 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1663 match self {
1664 ExecutionStatusView::Unknown => f.write_str("Unknown"),
1665 ExecutionStatusView::Failure(e) => f.write_fmt(format_args!("Failure({:?})", e)),
1666 ExecutionStatusView::SuccessValue(v) => {
1667 f.write_fmt(format_args!("SuccessValue({})", AbbrBytes(v)))
1668 }
1669 ExecutionStatusView::SuccessReceiptId(receipt_id) => {
1670 f.write_fmt(format_args!("SuccessReceiptId({})", receipt_id))
1671 }
1672 }
1673 }
1674}
1675
1676impl From<ExecutionStatus> for ExecutionStatusView {
1677 fn from(outcome: ExecutionStatus) -> Self {
1678 match outcome {
1679 ExecutionStatus::Unknown => ExecutionStatusView::Unknown,
1680 ExecutionStatus::Failure(e) => ExecutionStatusView::Failure(e),
1681 ExecutionStatus::SuccessValue(v) => ExecutionStatusView::SuccessValue(v),
1682 ExecutionStatus::SuccessReceiptId(receipt_id) => {
1683 ExecutionStatusView::SuccessReceiptId(receipt_id)
1684 }
1685 }
1686 }
1687}
1688
1689#[derive(
1691 BorshSerialize,
1692 BorshDeserialize,
1693 PartialEq,
1694 Clone,
1695 Eq,
1696 Debug,
1697 serde::Serialize,
1698 serde::Deserialize,
1699)]
1700#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
1701pub struct CostGasUsed {
1702 pub cost_category: String,
1704 pub cost: String,
1705 #[serde(with = "dec_format")]
1706 #[cfg_attr(feature = "schemars", schemars(with = "String"))]
1707 pub gas_used: Gas,
1708}
1709
1710#[derive(
1711 BorshSerialize,
1712 BorshDeserialize,
1713 PartialEq,
1714 Clone,
1715 Eq,
1716 Debug,
1717 serde::Serialize,
1718 serde::Deserialize,
1719)]
1720#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
1721pub struct ExecutionMetadataView {
1722 pub version: u32,
1723 pub gas_profile: Option<Vec<CostGasUsed>>,
1724}
1725
1726impl Default for ExecutionMetadataView {
1727 fn default() -> Self {
1728 ExecutionMetadata::V1.into()
1729 }
1730}
1731
1732impl From<ExecutionMetadata> for ExecutionMetadataView {
1733 fn from(metadata: ExecutionMetadata) -> Self {
1734 let version = match metadata {
1735 ExecutionMetadata::V1 => 1,
1736 ExecutionMetadata::V2(_) => 2,
1737 ExecutionMetadata::V3(_) => 3,
1738 };
1739 let mut gas_profile = match metadata {
1740 ExecutionMetadata::V1 => None,
1741 ExecutionMetadata::V2(profile_data) => {
1742 let mut costs: Vec<CostGasUsed> = profile_data
1748 .legacy_action_costs()
1749 .into_iter()
1750 .filter(|&(_, gas)| gas > Gas::ZERO)
1751 .map(|(name, gas)| CostGasUsed::action(name.to_string(), gas))
1752 .collect();
1753
1754 costs.push(CostGasUsed::wasm_host(
1756 "WASM_INSTRUCTION".to_string(),
1757 profile_data.get_wasm_cost(),
1758 ));
1759
1760 for ext_cost in ExtCosts::iter() {
1762 costs.push(CostGasUsed::wasm_host(
1763 format!("{:?}", ext_cost).to_ascii_uppercase(),
1764 profile_data.get_ext_cost(ext_cost),
1765 ));
1766 }
1767
1768 Some(costs)
1769 }
1770 ExecutionMetadata::V3(profile) => {
1771 let mut costs: Vec<CostGasUsed> = ActionCosts::iter()
1774 .filter_map(|cost| {
1775 let gas_used = profile.get_action_cost(cost);
1776 (gas_used > Gas::ZERO).then(|| {
1777 CostGasUsed::action(
1778 format!("{:?}", cost).to_ascii_uppercase(),
1779 gas_used,
1780 )
1781 })
1782 })
1783 .collect();
1784
1785 let wasm_gas_used = profile.get_wasm_cost();
1787 if wasm_gas_used > Gas::ZERO {
1788 costs.push(CostGasUsed::wasm_host(
1789 "WASM_INSTRUCTION".to_string(),
1790 wasm_gas_used,
1791 ));
1792 }
1793
1794 for ext_cost in ExtCosts::iter() {
1796 let gas_used = profile.get_ext_cost(ext_cost);
1797 if gas_used > Gas::ZERO {
1798 costs.push(CostGasUsed::wasm_host(
1799 format!("{:?}", ext_cost).to_ascii_uppercase(),
1800 gas_used,
1801 ));
1802 }
1803 }
1804
1805 Some(costs)
1806 }
1807 };
1808 if let Some(ref mut costs) = gas_profile {
1809 costs.sort_by(|lhs, rhs| {
1816 lhs.cost_category.cmp(&rhs.cost_category).then_with(|| lhs.cost.cmp(&rhs.cost))
1817 });
1818 }
1819 ExecutionMetadataView { version, gas_profile }
1820 }
1821}
1822
1823impl CostGasUsed {
1824 pub fn action(cost: String, gas_used: Gas) -> Self {
1825 Self { cost_category: "ACTION_COST".to_string(), cost, gas_used }
1826 }
1827
1828 pub fn wasm_host(cost: String, gas_used: Gas) -> Self {
1829 Self { cost_category: "WASM_HOST_COST".to_string(), cost, gas_used }
1830 }
1831}
1832
1833#[derive(
1834 BorshSerialize,
1835 BorshDeserialize,
1836 Debug,
1837 Clone,
1838 PartialEq,
1839 Eq,
1840 serde::Serialize,
1841 serde::Deserialize,
1842)]
1843#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
1844pub struct ExecutionOutcomeView {
1845 pub logs: Vec<String>,
1847 pub receipt_ids: Vec<CryptoHash>,
1849 pub gas_burnt: Gas,
1851 pub tokens_burnt: Balance,
1857 pub executor_id: AccountId,
1860 pub status: ExecutionStatusView,
1862 #[serde(default)]
1864 pub metadata: ExecutionMetadataView,
1865}
1866
1867impl From<ExecutionOutcome> for ExecutionOutcomeView {
1868 fn from(outcome: ExecutionOutcome) -> Self {
1869 Self {
1870 logs: outcome.logs,
1871 receipt_ids: outcome.receipt_ids,
1872 gas_burnt: outcome.gas_burnt,
1873 tokens_burnt: outcome.tokens_burnt,
1874 executor_id: outcome.executor_id,
1875 status: outcome.status.into(),
1876 metadata: outcome.metadata.into(),
1877 }
1878 }
1879}
1880
1881impl From<&ExecutionOutcomeView> for PartialExecutionOutcome {
1882 fn from(outcome: &ExecutionOutcomeView) -> Self {
1883 Self {
1884 receipt_ids: outcome.receipt_ids.clone(),
1885 gas_burnt: outcome.gas_burnt,
1886 tokens_burnt: outcome.tokens_burnt,
1887 executor_id: outcome.executor_id.clone(),
1888 status: outcome.status.clone().into(),
1889 }
1890 }
1891}
1892impl From<ExecutionStatusView> for PartialExecutionStatus {
1893 fn from(status: ExecutionStatusView) -> PartialExecutionStatus {
1894 match status {
1895 ExecutionStatusView::Unknown => PartialExecutionStatus::Unknown,
1896 ExecutionStatusView::Failure(_) => PartialExecutionStatus::Failure,
1897 ExecutionStatusView::SuccessValue(value) => PartialExecutionStatus::SuccessValue(value),
1898 ExecutionStatusView::SuccessReceiptId(id) => {
1899 PartialExecutionStatus::SuccessReceiptId(id)
1900 }
1901 }
1902 }
1903}
1904
1905impl ExecutionOutcomeView {
1906 pub fn to_hashes(&self, id: CryptoHash) -> Vec<CryptoHash> {
1908 let mut result = Vec::with_capacity(self.logs.len().saturating_add(2));
1909 result.push(id);
1910 result.push(CryptoHash::hash_borsh(&PartialExecutionOutcome::from(self)));
1911 result.extend(self.logs.iter().map(|log| hash(log.as_bytes())));
1912 result
1913 }
1914}
1915
1916#[cfg_attr(feature = "deepsize_feature", derive(deepsize::DeepSizeOf))]
1917#[derive(
1918 BorshSerialize,
1919 BorshDeserialize,
1920 Debug,
1921 PartialEq,
1922 Eq,
1923 Clone,
1924 serde::Serialize,
1925 serde::Deserialize,
1926)]
1927#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
1928pub struct ExecutionOutcomeWithIdView {
1929 pub proof: MerklePath,
1930 pub block_hash: CryptoHash,
1931 pub id: CryptoHash,
1932 pub outcome: ExecutionOutcomeView,
1933}
1934
1935impl From<ExecutionOutcomeWithIdAndProof> for ExecutionOutcomeWithIdView {
1936 fn from(outcome_with_id_and_proof: ExecutionOutcomeWithIdAndProof) -> Self {
1937 Self {
1938 proof: outcome_with_id_and_proof.proof,
1939 block_hash: outcome_with_id_and_proof.block_hash,
1940 id: outcome_with_id_and_proof.outcome_with_id.id,
1941 outcome: outcome_with_id_and_proof.outcome_with_id.outcome.into(),
1942 }
1943 }
1944}
1945
1946impl ExecutionOutcomeWithIdView {
1947 pub fn to_hashes(&self) -> Vec<CryptoHash> {
1948 self.outcome.to_hashes(self.id)
1949 }
1950}
1951#[derive(Clone, Debug)]
1952pub struct TxStatusView {
1953 pub execution_outcome: Option<FinalExecutionOutcomeViewEnum>,
1954 pub status: TxExecutionStatus,
1955}
1956
1957#[derive(
1958 BorshSerialize,
1959 BorshDeserialize,
1960 serde::Serialize,
1961 serde::Deserialize,
1962 Clone,
1963 Debug,
1964 Default,
1965 Eq,
1966 PartialEq,
1967)]
1968#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
1969#[serde(rename_all = "SCREAMING_SNAKE_CASE")]
1970#[borsh(use_discriminant = true)]
1971pub enum TxExecutionStatus {
1972 None = 0,
1974 Included = 1,
1976 #[default]
1980 ExecutedOptimistic = 2,
1981 IncludedFinal = 3,
1983 Executed = 4,
1987 Final = 5,
1990}
1991
1992#[derive(serde::Serialize, serde::Deserialize, Debug, Clone)]
1993#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
1994#[serde(untagged)]
1995pub enum FinalExecutionOutcomeViewEnum {
1998 FinalExecutionOutcomeWithReceipt(FinalExecutionOutcomeWithReceiptView),
1999 FinalExecutionOutcome(FinalExecutionOutcomeView),
2000}
2001
2002impl FinalExecutionOutcomeViewEnum {
2003 pub fn into_outcome(self) -> FinalExecutionOutcomeView {
2004 match self {
2005 Self::FinalExecutionOutcome(outcome) => outcome,
2006 Self::FinalExecutionOutcomeWithReceipt(outcome) => outcome.final_outcome,
2007 }
2008 }
2009}
2010
2011impl TxStatusView {
2012 pub fn into_outcome(self) -> Option<FinalExecutionOutcomeView> {
2013 self.execution_outcome.map(|outcome| match outcome {
2014 FinalExecutionOutcomeViewEnum::FinalExecutionOutcome(outcome) => outcome,
2015 FinalExecutionOutcomeViewEnum::FinalExecutionOutcomeWithReceipt(outcome) => {
2016 outcome.final_outcome
2017 }
2018 })
2019 }
2020}
2021
2022#[derive(
2025 BorshSerialize, BorshDeserialize, serde::Serialize, serde::Deserialize, PartialEq, Eq, Clone,
2026)]
2027#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
2028pub struct FinalExecutionOutcomeView {
2029 pub status: FinalExecutionStatus,
2035 pub transaction: SignedTransactionView,
2037 pub transaction_outcome: ExecutionOutcomeWithIdView,
2039 pub receipts_outcome: Vec<ExecutionOutcomeWithIdView>,
2041}
2042
2043impl fmt::Debug for FinalExecutionOutcomeView {
2044 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
2045 f.debug_struct("FinalExecutionOutcome")
2046 .field("status", &self.status)
2047 .field("transaction", &self.transaction)
2048 .field("transaction_outcome", &self.transaction_outcome)
2049 .field("receipts_outcome", &Slice(&self.receipts_outcome))
2050 .finish()
2051 }
2052}
2053
2054#[derive(
2057 BorshSerialize,
2058 BorshDeserialize,
2059 PartialEq,
2060 Eq,
2061 Clone,
2062 Debug,
2063 serde::Serialize,
2064 serde::Deserialize,
2065)]
2066#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
2067pub struct FinalExecutionOutcomeWithReceiptView {
2068 #[serde(flatten)]
2070 pub final_outcome: FinalExecutionOutcomeView,
2071 pub receipts: Vec<ReceiptView>,
2073}
2074
2075pub mod validator_stake_view {
2076 pub use super::ValidatorStakeViewV1;
2077 use crate::types::validator_stake::ValidatorStake;
2078 use borsh::{BorshDeserialize, BorshSerialize};
2079 use near_primitives_core::types::AccountId;
2080 use serde::Deserialize;
2081
2082 #[derive(
2083 BorshSerialize, BorshDeserialize, serde::Serialize, Deserialize, Debug, Clone, Eq, PartialEq,
2084 )]
2085 #[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
2086 #[serde(tag = "validator_stake_struct_version")]
2087 pub enum ValidatorStakeView {
2088 V1(ValidatorStakeViewV1),
2089 }
2090
2091 impl ValidatorStakeView {
2092 pub fn into_validator_stake(self) -> ValidatorStake {
2093 self.into()
2094 }
2095
2096 #[inline]
2097 pub fn take_account_id(self) -> AccountId {
2098 match self {
2099 Self::V1(v1) => v1.account_id,
2100 }
2101 }
2102
2103 #[inline]
2104 pub fn account_id(&self) -> &AccountId {
2105 match self {
2106 Self::V1(v1) => &v1.account_id,
2107 }
2108 }
2109 }
2110
2111 impl From<ValidatorStake> for ValidatorStakeView {
2112 fn from(stake: ValidatorStake) -> Self {
2113 match stake {
2114 ValidatorStake::V1(v1) => Self::V1(ValidatorStakeViewV1 {
2115 account_id: v1.account_id,
2116 public_key: v1.public_key,
2117 stake: v1.stake,
2118 }),
2119 }
2120 }
2121 }
2122
2123 impl From<ValidatorStakeView> for ValidatorStake {
2124 fn from(view: ValidatorStakeView) -> Self {
2125 match view {
2126 ValidatorStakeView::V1(v1) => Self::new_v1(v1.account_id, v1.public_key, v1.stake),
2127 }
2128 }
2129 }
2130}
2131
2132#[derive(
2133 BorshSerialize,
2134 BorshDeserialize,
2135 Debug,
2136 Clone,
2137 Eq,
2138 PartialEq,
2139 serde::Serialize,
2140 serde::Deserialize,
2141)]
2142#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
2143pub struct ValidatorStakeViewV1 {
2144 pub account_id: AccountId,
2145 pub public_key: PublicKey,
2146 pub stake: Balance,
2147}
2148
2149#[derive(
2150 BorshSerialize,
2151 BorshDeserialize,
2152 Clone,
2153 Debug,
2154 PartialEq,
2155 Eq,
2156 serde::Serialize,
2157 serde::Deserialize,
2158)]
2159#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
2160pub struct ReceiptView {
2161 pub predecessor_id: AccountId,
2162 pub receiver_id: AccountId,
2163 pub receipt_id: CryptoHash,
2164
2165 pub receipt: ReceiptEnumView,
2166 #[serde(default)]
2170 pub priority: u64,
2171}
2172
2173#[derive(
2174 BorshSerialize,
2175 BorshDeserialize,
2176 Clone,
2177 Debug,
2178 PartialEq,
2179 Eq,
2180 serde::Serialize,
2181 serde::Deserialize,
2182)]
2183#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
2184pub struct DataReceiverView {
2185 pub data_id: CryptoHash,
2186 pub receiver_id: AccountId,
2187}
2188
2189#[serde_as]
2190#[derive(
2191 BorshSerialize,
2192 BorshDeserialize,
2193 Clone,
2194 Debug,
2195 PartialEq,
2196 Eq,
2197 serde::Serialize,
2198 serde::Deserialize,
2199)]
2200#[borsh(use_discriminant = true)]
2201#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
2202#[repr(u8)]
2203pub enum ReceiptEnumView {
2204 Action {
2205 signer_id: AccountId,
2206 signer_public_key: PublicKey,
2207 gas_price: Balance,
2208 output_data_receivers: Vec<DataReceiverView>,
2209 input_data_ids: Vec<CryptoHash>,
2210 actions: Vec<ActionView>,
2211 #[serde(default = "default_is_promise")]
2212 is_promise_yield: bool,
2213 #[serde(default, skip_serializing_if = "Option::is_none")]
2214 refund_to: Option<AccountId>,
2215 } = 0,
2216 Data {
2217 data_id: CryptoHash,
2218 #[serde_as(as = "Option<Base64>")]
2219 #[cfg_attr(feature = "schemars", schemars(with = "Option<String>"))]
2220 data: Option<Vec<u8>>,
2221 #[serde(default = "default_is_promise")]
2222 is_promise_resume: bool,
2223 } = 1,
2224 GlobalContractDistribution {
2225 id: GlobalContractIdentifier,
2226 target_shard: ShardId,
2227 already_delivered_shards: Vec<ShardId>,
2228 #[serde_as(as = "Base64")]
2229 #[cfg_attr(feature = "schemars", schemars(with = "String"))]
2230 code: Vec<u8>,
2231 } = 2,
2232}
2233
2234fn default_is_promise() -> bool {
2238 false
2239}
2240
2241impl From<Receipt> for ReceiptView {
2242 fn from(receipt: Receipt) -> Self {
2243 let is_promise_yield =
2244 matches!(receipt.versioned_receipt(), VersionedReceiptEnum::PromiseYield(_));
2245 let is_promise_resume = matches!(receipt.receipt(), ReceiptEnum::PromiseResume(_));
2246 let priority = receipt.priority().value();
2247
2248 ReceiptView {
2249 predecessor_id: receipt.predecessor_id().clone(),
2250 receiver_id: receipt.receiver_id().clone(),
2251 receipt_id: *receipt.receipt_id(),
2252 receipt: match receipt.take_versioned_receipt() {
2253 VersionedReceiptEnum::Action(action_receipt)
2254 | VersionedReceiptEnum::PromiseYield(action_receipt) => {
2255 ReceiptEnumView::from_action_receipt(action_receipt, is_promise_yield)
2256 }
2257 VersionedReceiptEnum::Data(data_receipt)
2258 | VersionedReceiptEnum::PromiseResume(data_receipt) => {
2259 let data_receipt = data_receipt.into_owned();
2261 ReceiptEnumView::Data {
2262 data_id: data_receipt.data_id,
2263 data: data_receipt.data,
2264 is_promise_resume,
2265 }
2266 }
2267 VersionedReceiptEnum::GlobalContractDistribution(receipt) => {
2268 ReceiptEnumView::GlobalContractDistribution {
2269 id: receipt.id().clone(),
2270 target_shard: receipt.target_shard(),
2271 already_delivered_shards: receipt.already_delivered_shards().to_vec(),
2272 code: hash(receipt.code()).as_bytes().to_vec(),
2273 }
2274 }
2275 },
2276 priority,
2277 }
2278 }
2279}
2280
2281impl ReceiptEnumView {
2282 fn from_action_receipt(
2283 action_receipt: VersionedActionReceipt,
2284 is_promise_yield: bool,
2285 ) -> ReceiptEnumView {
2286 ReceiptEnumView::Action {
2287 signer_id: action_receipt.signer_id().clone(),
2288 signer_public_key: action_receipt.signer_public_key().clone(),
2289 gas_price: action_receipt.gas_price(),
2290 output_data_receivers: action_receipt
2291 .output_data_receivers()
2292 .iter()
2293 .cloned()
2294 .map(|data_receiver| DataReceiverView {
2295 data_id: data_receiver.data_id,
2296 receiver_id: data_receiver.receiver_id,
2297 })
2298 .collect(),
2299 input_data_ids: action_receipt
2300 .input_data_ids()
2301 .iter()
2302 .cloned()
2303 .map(Into::into)
2304 .collect(),
2305 actions: action_receipt.actions().iter().cloned().map(Into::into).collect(),
2306 is_promise_yield,
2307 refund_to: action_receipt.refund_to().clone(),
2308 }
2309 }
2310}
2311
2312impl TryFrom<ReceiptView> for Receipt {
2313 type Error = Box<dyn std::error::Error + Send + Sync>;
2314
2315 fn try_from(receipt_view: ReceiptView) -> Result<Self, Self::Error> {
2316 Ok(Receipt::V1(ReceiptV1 {
2317 predecessor_id: receipt_view.predecessor_id,
2318 receiver_id: receipt_view.receiver_id,
2319 receipt_id: receipt_view.receipt_id,
2320 receipt: match receipt_view.receipt {
2321 ReceiptEnumView::Action {
2322 signer_id,
2323 signer_public_key,
2324 gas_price,
2325 output_data_receivers,
2326 input_data_ids,
2327 actions,
2328 is_promise_yield,
2329 refund_to,
2330 } => {
2331 let output_data_receivers: Vec<_> = output_data_receivers
2332 .into_iter()
2333 .map(|data_receiver_view| DataReceiver {
2334 data_id: data_receiver_view.data_id,
2335 receiver_id: data_receiver_view.receiver_id,
2336 })
2337 .collect();
2338 let input_data_ids: Vec<CryptoHash> =
2339 input_data_ids.into_iter().map(Into::into).collect();
2340 let actions = actions
2341 .into_iter()
2342 .map(TryInto::try_into)
2343 .collect::<Result<Vec<_>, _>>()?;
2344 if refund_to.is_some() {
2345 let action_receipt = ActionReceiptV2 {
2346 signer_id,
2347 signer_public_key,
2348 gas_price,
2349 output_data_receivers,
2350 input_data_ids,
2351 actions,
2352 refund_to,
2353 };
2354 if is_promise_yield {
2355 ReceiptEnum::PromiseYieldV2(action_receipt)
2356 } else {
2357 ReceiptEnum::ActionV2(action_receipt)
2358 }
2359 } else {
2360 let action_receipt = ActionReceipt {
2361 signer_id,
2362 signer_public_key,
2363 gas_price,
2364 output_data_receivers,
2365 input_data_ids,
2366 actions,
2367 };
2368 if is_promise_yield {
2369 ReceiptEnum::PromiseYield(action_receipt)
2370 } else {
2371 ReceiptEnum::Action(action_receipt)
2372 }
2373 }
2374 }
2375 ReceiptEnumView::Data { data_id, data, is_promise_resume } => {
2376 let data_receipt = DataReceipt { data_id, data };
2377
2378 if is_promise_resume {
2379 ReceiptEnum::PromiseResume(data_receipt)
2380 } else {
2381 ReceiptEnum::Data(data_receipt)
2382 }
2383 }
2384 ReceiptEnumView::GlobalContractDistribution {
2385 id,
2386 target_shard,
2387 already_delivered_shards,
2388 code,
2389 } => {
2390 ReceiptEnum::GlobalContractDistribution(GlobalContractDistributionReceipt::new(
2391 id,
2392 target_shard,
2393 already_delivered_shards,
2394 code.into(),
2395 ))
2396 }
2397 },
2398 priority: receipt_view.priority,
2399 }))
2400 }
2401}
2402
2403#[derive(serde::Serialize, serde::Deserialize, Debug, PartialEq, Eq, Clone, ProtocolSchema)]
2405#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
2406pub struct EpochValidatorInfo {
2407 pub current_validators: Vec<CurrentEpochValidatorInfo>,
2409 pub next_validators: Vec<NextEpochValidatorInfo>,
2411 pub current_fishermen: Vec<ValidatorStakeView>,
2413 pub next_fishermen: Vec<ValidatorStakeView>,
2415 pub current_proposals: Vec<ValidatorStakeView>,
2417 pub prev_epoch_kickout: Vec<ValidatorKickoutView>,
2419 pub epoch_start_height: BlockHeight,
2421 pub epoch_height: EpochHeight,
2423}
2424
2425#[derive(
2426 BorshSerialize,
2427 BorshDeserialize,
2428 Debug,
2429 PartialEq,
2430 Eq,
2431 Clone,
2432 serde::Serialize,
2433 serde::Deserialize,
2434 ProtocolSchema,
2435)]
2436#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
2437pub struct ValidatorKickoutView {
2438 pub account_id: AccountId,
2439 pub reason: ValidatorKickoutReason,
2440}
2441
2442#[derive(serde::Serialize, serde::Deserialize, Debug, PartialEq, Eq, Clone, ProtocolSchema)]
2444#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
2445pub struct CurrentEpochValidatorInfo {
2446 pub account_id: AccountId,
2447 pub public_key: PublicKey,
2448 pub is_slashed: bool,
2449 pub stake: Balance,
2450 #[serde(rename = "shards")]
2452 pub shards_produced: Vec<ShardId>,
2453 pub num_produced_blocks: NumBlocks,
2454 pub num_expected_blocks: NumBlocks,
2455 #[serde(default)]
2456 pub num_produced_chunks: NumBlocks,
2457 #[serde(default)]
2458 pub num_expected_chunks: NumBlocks,
2459 #[serde(default)]
2461 pub num_produced_chunks_per_shard: Vec<NumBlocks>,
2462 #[serde(default)]
2465 pub num_expected_chunks_per_shard: Vec<NumBlocks>,
2466 #[serde(default)]
2467 pub num_produced_endorsements: NumBlocks,
2468 #[serde(default)]
2469 pub num_expected_endorsements: NumBlocks,
2470 #[serde(default)]
2471 pub num_produced_endorsements_per_shard: Vec<NumBlocks>,
2472 #[serde(default)]
2475 pub num_expected_endorsements_per_shard: Vec<NumBlocks>,
2476 #[serde(default)]
2478 pub shards_endorsed: Vec<ShardId>,
2479}
2480
2481#[derive(
2482 BorshSerialize,
2483 BorshDeserialize,
2484 Debug,
2485 PartialEq,
2486 Eq,
2487 Clone,
2488 serde::Serialize,
2489 serde::Deserialize,
2490 ProtocolSchema,
2491)]
2492#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
2493pub struct NextEpochValidatorInfo {
2494 pub account_id: AccountId,
2495 pub public_key: PublicKey,
2496 pub stake: Balance,
2497 pub shards: Vec<ShardId>,
2498}
2499
2500#[derive(
2502 PartialEq,
2503 Eq,
2504 Debug,
2505 Clone,
2506 BorshDeserialize,
2507 BorshSerialize,
2508 serde::Serialize,
2509 serde::Deserialize,
2510)]
2511#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
2512pub struct LightClientBlockView {
2513 pub prev_block_hash: CryptoHash,
2514 pub next_block_inner_hash: CryptoHash,
2515 pub inner_lite: BlockHeaderInnerLiteView,
2518 pub inner_rest_hash: CryptoHash,
2519 pub next_bps: Option<Vec<ValidatorStakeView>>,
2520 pub approvals_after_next: Vec<Option<Box<Signature>>>,
2521}
2522
2523#[derive(serde::Serialize, serde::Deserialize, Debug, Clone, BorshDeserialize, BorshSerialize)]
2524#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
2525pub struct LightClientBlockLiteView {
2526 pub prev_block_hash: CryptoHash,
2527 pub inner_rest_hash: CryptoHash,
2528 pub inner_lite: BlockHeaderInnerLiteView,
2529}
2530
2531impl From<BlockHeader> for LightClientBlockLiteView {
2532 fn from(header: BlockHeader) -> Self {
2533 Self {
2534 prev_block_hash: *header.prev_hash(),
2535 inner_rest_hash: hash(&header.inner_rest_bytes()),
2536 inner_lite: header.into(),
2537 }
2538 }
2539}
2540impl LightClientBlockLiteView {
2541 pub fn hash(&self) -> CryptoHash {
2542 let block_header_inner_lite: BlockHeaderInnerLite = self.inner_lite.clone().into();
2543 combine_hash(
2544 &combine_hash(
2545 &hash(&borsh::to_vec(&block_header_inner_lite).unwrap()),
2546 &self.inner_rest_hash,
2547 ),
2548 &self.prev_block_hash,
2549 )
2550 }
2551}
2552
2553#[derive(serde::Serialize, serde::Deserialize, Debug)]
2554#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
2555pub struct GasPriceView {
2556 pub gas_price: Balance,
2557}
2558
2559#[derive(Debug, serde::Serialize, serde::Deserialize)]
2564#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
2565#[serde(tag = "changes_type", rename_all = "snake_case")]
2566pub enum StateChangesRequestView {
2567 AccountChanges {
2568 account_ids: Vec<AccountId>,
2569 },
2570 SingleAccessKeyChanges {
2571 keys: Vec<AccountWithPublicKey>,
2572 },
2573 SingleGasKeyChanges {
2574 keys: Vec<AccountWithPublicKey>,
2575 },
2576 AllAccessKeyChanges {
2577 account_ids: Vec<AccountId>,
2578 },
2579 AllGasKeyChanges {
2580 account_ids: Vec<AccountId>,
2581 },
2582 ContractCodeChanges {
2583 account_ids: Vec<AccountId>,
2584 },
2585 DataChanges {
2586 account_ids: Vec<AccountId>,
2587 #[serde(rename = "key_prefix_base64")]
2588 key_prefix: StoreKey,
2589 },
2590}
2591
2592impl From<StateChangesRequestView> for StateChangesRequest {
2593 fn from(request: StateChangesRequestView) -> Self {
2594 match request {
2595 StateChangesRequestView::AccountChanges { account_ids } => {
2596 Self::AccountChanges { account_ids }
2597 }
2598 StateChangesRequestView::SingleAccessKeyChanges { keys } => {
2599 Self::SingleAccessKeyChanges { keys }
2600 }
2601 StateChangesRequestView::SingleGasKeyChanges { keys } => {
2602 Self::SingleGasKeyChanges { keys }
2603 }
2604 StateChangesRequestView::AllAccessKeyChanges { account_ids } => {
2605 Self::AllAccessKeyChanges { account_ids }
2606 }
2607 StateChangesRequestView::AllGasKeyChanges { account_ids } => {
2608 Self::AllGasKeyChanges { account_ids }
2609 }
2610 StateChangesRequestView::ContractCodeChanges { account_ids } => {
2611 Self::ContractCodeChanges { account_ids }
2612 }
2613 StateChangesRequestView::DataChanges { account_ids, key_prefix } => {
2614 Self::DataChanges { account_ids, key_prefix }
2615 }
2616 }
2617 }
2618}
2619
2620#[derive(Debug, PartialEq, Eq, serde::Serialize, serde::Deserialize)]
2625#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
2626#[serde(rename_all = "snake_case", tag = "type")]
2627pub enum StateChangeKindView {
2628 AccountTouched { account_id: AccountId },
2629 AccessKeyTouched { account_id: AccountId },
2630 DataTouched { account_id: AccountId },
2631 ContractCodeTouched { account_id: AccountId },
2632}
2633
2634impl From<StateChangeKind> for StateChangeKindView {
2635 fn from(state_change_kind: StateChangeKind) -> Self {
2636 match state_change_kind {
2637 StateChangeKind::AccountTouched { account_id } => Self::AccountTouched { account_id },
2638 StateChangeKind::AccessKeyTouched { account_id } => {
2639 Self::AccessKeyTouched { account_id }
2640 }
2641 StateChangeKind::DataTouched { account_id } => Self::DataTouched { account_id },
2642 StateChangeKind::ContractCodeTouched { account_id } => {
2643 Self::ContractCodeTouched { account_id }
2644 }
2645 }
2646 }
2647}
2648
2649pub type StateChangesKindsView = Vec<StateChangeKindView>;
2650
2651#[derive(Clone, Debug, serde::Serialize, serde::Deserialize)]
2653#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
2654#[serde(rename_all = "snake_case", tag = "type")]
2655pub enum StateChangeCauseView {
2656 NotWritableToDisk,
2657 InitialState,
2658 TransactionProcessing { tx_hash: CryptoHash },
2659 ActionReceiptProcessingStarted { receipt_hash: CryptoHash },
2660 ActionReceiptGasReward { receipt_hash: CryptoHash },
2661 ReceiptProcessing { receipt_hash: CryptoHash },
2662 PostponedReceipt { receipt_hash: CryptoHash },
2663 UpdatedDelayedReceipts,
2664 ValidatorAccountsUpdate,
2665 Migration,
2666 BandwidthSchedulerStateUpdate,
2667}
2668
2669impl From<StateChangeCause> for StateChangeCauseView {
2670 fn from(state_change_cause: StateChangeCause) -> Self {
2671 match state_change_cause {
2672 StateChangeCause::NotWritableToDisk => Self::NotWritableToDisk,
2673 StateChangeCause::InitialState => Self::InitialState,
2674 StateChangeCause::TransactionProcessing { tx_hash } => {
2675 Self::TransactionProcessing { tx_hash }
2676 }
2677 StateChangeCause::ActionReceiptProcessingStarted { receipt_hash } => {
2678 Self::ActionReceiptProcessingStarted { receipt_hash }
2679 }
2680 StateChangeCause::ActionReceiptGasReward { receipt_hash } => {
2681 Self::ActionReceiptGasReward { receipt_hash }
2682 }
2683 StateChangeCause::ReceiptProcessing { receipt_hash } => {
2684 Self::ReceiptProcessing { receipt_hash }
2685 }
2686 StateChangeCause::PostponedReceipt { receipt_hash } => {
2687 Self::PostponedReceipt { receipt_hash }
2688 }
2689 StateChangeCause::UpdatedDelayedReceipts => Self::UpdatedDelayedReceipts,
2690 StateChangeCause::ValidatorAccountsUpdate => Self::ValidatorAccountsUpdate,
2691 StateChangeCause::Migration => Self::Migration,
2692 StateChangeCause::_UnusedReshardingV2 => Self::BandwidthSchedulerStateUpdate,
2699 StateChangeCause::BandwidthSchedulerStateUpdate => Self::BandwidthSchedulerStateUpdate,
2700 }
2701 }
2702}
2703
2704#[serde_as]
2705#[derive(Clone, Debug, serde::Serialize, serde::Deserialize)]
2706#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
2707#[serde(rename_all = "snake_case", tag = "type", content = "change")]
2708pub enum StateChangeValueView {
2709 AccountUpdate {
2710 account_id: AccountId,
2711 #[serde(flatten)]
2712 account: AccountView,
2713 },
2714 AccountDeletion {
2715 account_id: AccountId,
2716 },
2717 AccessKeyUpdate {
2718 account_id: AccountId,
2719 public_key: PublicKey,
2720 access_key: AccessKeyView,
2721 },
2722 AccessKeyDeletion {
2723 account_id: AccountId,
2724 public_key: PublicKey,
2725 },
2726 GasKeyUpdate {
2727 account_id: AccountId,
2728 public_key: PublicKey,
2729 gas_key: GasKeyView,
2730 },
2731 GasKeyNonceUpdate {
2732 account_id: AccountId,
2733 public_key: PublicKey,
2734 index: u32,
2735 nonce: Nonce,
2736 },
2737 GasKeyDeletion {
2738 account_id: AccountId,
2739 public_key: PublicKey,
2740 },
2741 DataUpdate {
2742 account_id: AccountId,
2743 #[serde(rename = "key_base64")]
2744 key: StoreKey,
2745 #[serde(rename = "value_base64")]
2746 value: StoreValue,
2747 },
2748 DataDeletion {
2749 account_id: AccountId,
2750 #[serde(rename = "key_base64")]
2751 key: StoreKey,
2752 },
2753 ContractCodeUpdate {
2754 account_id: AccountId,
2755 #[serde(rename = "code_base64")]
2756 #[serde_as(as = "Base64")]
2757 #[cfg_attr(feature = "schemars", schemars(with = "String"))]
2758 code: Vec<u8>,
2759 },
2760 ContractCodeDeletion {
2761 account_id: AccountId,
2762 },
2763}
2764
2765impl From<StateChangeValue> for StateChangeValueView {
2766 fn from(state_change: StateChangeValue) -> Self {
2767 match state_change {
2768 StateChangeValue::AccountUpdate { account_id, account } => {
2769 Self::AccountUpdate { account_id, account: account.into() }
2770 }
2771 StateChangeValue::AccountDeletion { account_id } => {
2772 Self::AccountDeletion { account_id }
2773 }
2774 StateChangeValue::AccessKeyUpdate { account_id, public_key, access_key } => {
2775 Self::AccessKeyUpdate { account_id, public_key, access_key: access_key.into() }
2776 }
2777 StateChangeValue::AccessKeyDeletion { account_id, public_key } => {
2778 Self::AccessKeyDeletion { account_id, public_key }
2779 }
2780 StateChangeValue::GasKeyUpdate { account_id, public_key, gas_key } => {
2781 Self::GasKeyUpdate { account_id, public_key, gas_key: gas_key.into() }
2782 }
2783 StateChangeValue::GasKeyNonceUpdate { account_id, public_key, index, nonce } => {
2784 Self::GasKeyNonceUpdate { account_id, public_key, index, nonce }
2785 }
2786 StateChangeValue::GasKeyDeletion { account_id, public_key } => {
2787 Self::GasKeyDeletion { account_id, public_key }
2788 }
2789 StateChangeValue::DataUpdate { account_id, key, value } => {
2790 Self::DataUpdate { account_id, key, value }
2791 }
2792 StateChangeValue::DataDeletion { account_id, key } => {
2793 Self::DataDeletion { account_id, key }
2794 }
2795 StateChangeValue::ContractCodeUpdate { account_id, code } => {
2796 Self::ContractCodeUpdate { account_id, code }
2797 }
2798 StateChangeValue::ContractCodeDeletion { account_id } => {
2799 Self::ContractCodeDeletion { account_id }
2800 }
2801 }
2802 }
2803}
2804
2805#[derive(Clone, Debug, serde::Serialize, serde::Deserialize)]
2806#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
2807pub struct StateChangeWithCauseView {
2808 pub cause: StateChangeCauseView,
2809 #[serde(flatten)]
2810 pub value: StateChangeValueView,
2811}
2812
2813impl From<StateChangeWithCause> for StateChangeWithCauseView {
2814 fn from(state_change_with_cause: StateChangeWithCause) -> Self {
2815 let StateChangeWithCause { cause, value } = state_change_with_cause;
2816 Self { cause: cause.into(), value: value.into() }
2817 }
2818}
2819
2820pub type StateChangesView = Vec<StateChangeWithCauseView>;
2821
2822pub type MaintenanceWindowsView = Vec<Range<BlockHeight>>;
2824
2825#[derive(serde::Serialize, serde::Deserialize, Debug)]
2827#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
2828pub struct SplitStorageInfoView {
2829 pub head_height: Option<BlockHeight>,
2830 pub final_head_height: Option<BlockHeight>,
2831 pub cold_head_height: Option<BlockHeight>,
2832
2833 pub hot_db_kind: Option<String>,
2834}
2835
2836#[derive(Clone, Debug, serde::Serialize, serde::Deserialize)]
2838#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
2839pub struct CongestionInfoView {
2840 #[serde(with = "dec_format")]
2841 #[cfg_attr(feature = "schemars", schemars(with = "String"))]
2842 pub delayed_receipts_gas: u128,
2843
2844 #[serde(with = "dec_format")]
2845 #[cfg_attr(feature = "schemars", schemars(with = "String"))]
2846 pub buffered_receipts_gas: u128,
2847
2848 pub receipt_bytes: u64,
2849
2850 pub allowed_shard: u16,
2851}
2852
2853impl From<CongestionInfo> for CongestionInfoView {
2854 fn from(congestion_info: CongestionInfo) -> Self {
2855 match congestion_info {
2856 CongestionInfo::V1(congestion_info) => congestion_info.into(),
2857 }
2858 }
2859}
2860
2861impl From<CongestionInfoV1> for CongestionInfoView {
2862 fn from(congestion_info: CongestionInfoV1) -> Self {
2863 Self {
2864 delayed_receipts_gas: congestion_info.delayed_receipts_gas,
2865 buffered_receipts_gas: congestion_info.buffered_receipts_gas,
2866 receipt_bytes: congestion_info.receipt_bytes,
2867 allowed_shard: congestion_info.allowed_shard,
2868 }
2869 }
2870}
2871
2872impl From<CongestionInfoView> for CongestionInfo {
2873 fn from(congestion_info: CongestionInfoView) -> Self {
2874 CongestionInfo::V1(CongestionInfoV1 {
2875 delayed_receipts_gas: congestion_info.delayed_receipts_gas,
2876 buffered_receipts_gas: congestion_info.buffered_receipts_gas,
2877 receipt_bytes: congestion_info.receipt_bytes,
2878 allowed_shard: congestion_info.allowed_shard,
2879 })
2880 }
2881}
2882
2883impl CongestionInfoView {
2884 pub fn congestion_level(&self, config_view: CongestionControlConfigView) -> f64 {
2885 let congestion_config = CongestionControlConfig::from(config_view);
2886 CongestionInfo::from(self.clone()).localized_congestion_level(&congestion_config)
2895 }
2896}
2897
2898#[cfg(test)]
2899#[cfg(not(feature = "nightly"))]
2900mod tests {
2901 use super::{ExecutionMetadataView, FinalExecutionOutcomeViewEnum};
2902 use crate::profile_data_v2::ProfileDataV2;
2903 use crate::profile_data_v3::ProfileDataV3;
2904 use crate::transaction::ExecutionMetadata;
2905
2906 #[test]
2909 fn test_runtime_config_view() {
2910 use near_parameters::{RuntimeConfig, RuntimeConfigStore, RuntimeConfigView};
2911 use near_primitives_core::version::PROTOCOL_VERSION;
2912
2913 let config_store = RuntimeConfigStore::new(None);
2914 let config = config_store.get_config(PROTOCOL_VERSION);
2915 let view = RuntimeConfigView::from(RuntimeConfig::clone(config));
2916 insta::assert_json_snapshot!(&view, { ".wasm_config.vm_kind" => "<REDACTED>"});
2917 }
2918
2919 #[test]
2921 fn test_exec_metadata_v1_view() {
2922 let metadata = ExecutionMetadata::V1;
2923 let view = ExecutionMetadataView::from(metadata);
2924 insta::assert_json_snapshot!(view);
2925 }
2926
2927 #[test]
2929 fn test_exec_metadata_v2_view() {
2930 let metadata = ExecutionMetadata::V2(ProfileDataV2::test());
2931 let view = ExecutionMetadataView::from(metadata);
2932 insta::assert_json_snapshot!(view);
2933 }
2934
2935 #[test]
2937 fn test_exec_metadata_v3_view() {
2938 let metadata = ExecutionMetadata::V3(ProfileDataV3::test().into());
2939 let view = ExecutionMetadataView::from(metadata);
2940 insta::assert_json_snapshot!(view);
2941 }
2942
2943 #[test]
2944 fn test_deserialize_execution_outcome_with_receipt() {
2945 let json = r#"{"final_execution_status":"FINAL","receipts":[{"predecessor_id":"system","priority":0,"receipt":{"Action":{"actions":[{"Transfer":{"deposit":"17930928991009412192152"}}],"gas_price":"0","input_data_ids":[],"is_promise_yield":false,"output_data_receivers":[],"signer_id":"btc-client.testnet","signer_public_key":"ed25519:HM7ax8jJf41JozvanXepzhtD45AeRFcwJQCuLXFuDkjA"}},"receipt_id":"8ZD92cLpoCEU46hPGFfk3VqZpU8s6DoQhZ4pCMqWwDT6","receiver_id":"btc-client.testnet"}],"receipts_outcome":[{"block_hash":"9SP8Y3sVADWNN5QoEB5CsvPUE5HT4o8YfBaCnhLss87K","id":"e2XGEosf843XMiCJHvZufvHKyw419ZYibDBdVJQr9cB","outcome":{"executor_id":"btc-client.testnet","gas_burnt":2906160054161,"logs":["Block hash: 0000000000000000ee617846a3e081ae2f30091451442e1b5fb027d8eba09b3a","Saving to mainchain"],"metadata":{"gas_profile":[{"cost":"BASE","cost_category":"WASM_HOST_COST","gas_used":"8472579552"},{"cost":"CONTRACT_LOADING_BASE","cost_category":"WASM_HOST_COST","gas_used":"35445963"},{"cost":"CONTRACT_LOADING_BYTES","cost_category":"WASM_HOST_COST","gas_used":"413841688515"},{"cost":"LOG_BASE","cost_category":"WASM_HOST_COST","gas_used":"7086626100"},{"cost":"LOG_BYTE","cost_category":"WASM_HOST_COST","gas_used":"1253885145"},{"cost":"READ_CACHED_TRIE_NODE","cost_category":"WASM_HOST_COST","gas_used":"102600000000"},{"cost":"READ_MEMORY_BASE","cost_category":"WASM_HOST_COST","gas_used":"54807127200"},{"cost":"READ_MEMORY_BYTE","cost_category":"WASM_HOST_COST","gas_used":"2873807748"},{"cost":"READ_REGISTER_BASE","cost_category":"WASM_HOST_COST","gas_used":"22654486674"},{"cost":"READ_REGISTER_BYTE","cost_category":"WASM_HOST_COST","gas_used":"51252240"},{"cost":"SHA256_BASE","cost_category":"WASM_HOST_COST","gas_used":"13622910750"},{"cost":"SHA256_BYTE","cost_category":"WASM_HOST_COST","gas_used":"3400546491"},{"cost":"STORAGE_READ_BASE","cost_category":"WASM_HOST_COST","gas_used":"450854766000"},{"cost":"STORAGE_READ_KEY_BYTE","cost_category":"WASM_HOST_COST","gas_used":"4952405280"},{"cost":"STORAGE_READ_VALUE_BYTE","cost_category":"WASM_HOST_COST","gas_used":"1806743610"},{"cost":"STORAGE_WRITE_BASE","cost_category":"WASM_HOST_COST","gas_used":"256786944000"},{"cost":"STORAGE_WRITE_EVICTED_BYTE","cost_category":"WASM_HOST_COST","gas_used":"2826323016"},{"cost":"STORAGE_WRITE_KEY_BYTE","cost_category":"WASM_HOST_COST","gas_used":"5638629360"},{"cost":"STORAGE_WRITE_VALUE_BYTE","cost_category":"WASM_HOST_COST","gas_used":"8685190920"},{"cost":"TOUCHING_TRIE_NODE","cost_category":"WASM_HOST_COST","gas_used":"434752810002"},{"cost":"UTF8_DECODING_BASE","cost_category":"WASM_HOST_COST","gas_used":"6223558122"},{"cost":"UTF8_DECODING_BYTE","cost_category":"WASM_HOST_COST","gas_used":"27700145505"},{"cost":"WASM_INSTRUCTION","cost_category":"WASM_HOST_COST","gas_used":"126491330196"},{"cost":"WRITE_MEMORY_BASE","cost_category":"WASM_HOST_COST","gas_used":"28037948610"},{"cost":"WRITE_MEMORY_BYTE","cost_category":"WASM_HOST_COST","gas_used":"1459941792"},{"cost":"WRITE_REGISTER_BASE","cost_category":"WASM_HOST_COST","gas_used":"28655224860"},{"cost":"WRITE_REGISTER_BYTE","cost_category":"WASM_HOST_COST","gas_used":"2311350912"}],"version":3},"receipt_ids":["8ZD92cLpoCEU46hPGFfk3VqZpU8s6DoQhZ4pCMqWwDT6"],"status":{"SuccessValue":""},"tokens_burnt":"290616005416100000000"},"proof":[{"direction":"Left","hash":"BoQHueiPH9e4C7fkxouV4tFpGZ4hK5fJhKQnPBWwPazS"},{"direction":"Right","hash":"Ayxj8iVFTJMzZa7estoTtuBKJaUNhoipaaM7WmTjkkiS"}]},{"block_hash":"3rEx3xmgLCRgUfSgueD71YNrJYQYNvhtkXaqVQxdmj4U","id":"8ZD92cLpoCEU46hPGFfk3VqZpU8s6DoQhZ4pCMqWwDT6","outcome":{"executor_id":"btc-client.testnet","gas_burnt":223182562500,"logs":[],"metadata":{"gas_profile":[],"version":3},"receipt_ids":[],"status":{"SuccessValue":""},"tokens_burnt":"0"},"proof":[{"direction":"Right","hash":"8yEwg14D2GyyLNnJMxdSLDJKyrKShMAL3zTnf9YpQyPW"},{"direction":"Right","hash":"2UK7BfpHf9fCCsvmfHktDfz6Rh8sFihhN6cuTU3R4BBA"}]}],"status":{"SuccessValue":""},"transaction":{"actions":[{"FunctionCall":{"args":"AQAAAABA0CKoR96WKs+KPP6zPl0flT6XC91eR3uAUgwNAAAAAAAAAAzcZU0cipmejc+wGqnRJchd5uM6qRJM5Oojp3FrkJ2HVmGyZsnyFBlkvks8","deposit":"0","gas":100000000000000,"method_name":"submit_blocks"}}],"hash":"GMUCDLHFJVvmZYXmPf9QeUVAt9r9hXcQP1yL5emPFnvx","nonce":170437577001422,"priority_fee":0,"public_key":"ed25519:HM7ax8jJf41JozvanXepzhtD45AeRFcwJQCuLXFuDkjA","receiver_id":"btc-client.testnet","signature":"ed25519:2Qe3ccPSdzPddk764vm5jt4yXcvXgYQz3WzGF3oXpZLuaRa6ggpD131nSSy3FRVPquCvxYqgMGtdum8TKX3dVqNk","signer_id":"btc-client.testnet"},"transaction_outcome":{"block_hash":"9SP8Y3sVADWNN5QoEB5CsvPUE5HT4o8YfBaCnhLss87K","id":"GMUCDLHFJVvmZYXmPf9QeUVAt9r9hXcQP1yL5emPFnvx","outcome":{"executor_id":"btc-client.testnet","gas_burnt":308276385598,"logs":[],"metadata":{"gas_profile":null,"version":1},"receipt_ids":["e2XGEosf843XMiCJHvZufvHKyw419ZYibDBdVJQr9cB"],"status":{"SuccessReceiptId":"e2XGEosf843XMiCJHvZufvHKyw419ZYibDBdVJQr9cB"},"tokens_burnt":"30827638559800000000"},"proof":[{"direction":"Right","hash":"HDgWEk2okmDdAFAVf6ffxGBH6F6vdLM1X3H5Fmaafe4S"},{"direction":"Right","hash":"Ayxj8iVFTJMzZa7estoTtuBKJaUNhoipaaM7WmTjkkiS"}]}}"#;
2948 let view: FinalExecutionOutcomeViewEnum = serde_json::from_str(json).unwrap();
2949 assert!(matches!(view, FinalExecutionOutcomeViewEnum::FinalExecutionOutcomeWithReceipt(_)));
2950 }
2951
2952 #[test]
2953 fn test_deserialize_execution_outcome_without_receipt() {
2954 let json = r#"{"final_execution_status":"FINAL","receipts_outcome":[{"block_hash":"9SP8Y3sVADWNN5QoEB5CsvPUE5HT4o8YfBaCnhLss87K","id":"e2XGEosf843XMiCJHvZufvHKyw419ZYibDBdVJQr9cB","outcome":{"executor_id":"btc-client.testnet","gas_burnt":2906160054161,"logs":["Block hash: 0000000000000000ee617846a3e081ae2f30091451442e1b5fb027d8eba09b3a","Saving to mainchain"],"metadata":{"gas_profile":[{"cost":"BASE","cost_category":"WASM_HOST_COST","gas_used":"8472579552"},{"cost":"CONTRACT_LOADING_BASE","cost_category":"WASM_HOST_COST","gas_used":"35445963"},{"cost":"CONTRACT_LOADING_BYTES","cost_category":"WASM_HOST_COST","gas_used":"413841688515"},{"cost":"LOG_BASE","cost_category":"WASM_HOST_COST","gas_used":"7086626100"},{"cost":"LOG_BYTE","cost_category":"WASM_HOST_COST","gas_used":"1253885145"},{"cost":"READ_CACHED_TRIE_NODE","cost_category":"WASM_HOST_COST","gas_used":"102600000000"},{"cost":"READ_MEMORY_BASE","cost_category":"WASM_HOST_COST","gas_used":"54807127200"},{"cost":"READ_MEMORY_BYTE","cost_category":"WASM_HOST_COST","gas_used":"2873807748"},{"cost":"READ_REGISTER_BASE","cost_category":"WASM_HOST_COST","gas_used":"22654486674"},{"cost":"READ_REGISTER_BYTE","cost_category":"WASM_HOST_COST","gas_used":"51252240"},{"cost":"SHA256_BASE","cost_category":"WASM_HOST_COST","gas_used":"13622910750"},{"cost":"SHA256_BYTE","cost_category":"WASM_HOST_COST","gas_used":"3400546491"},{"cost":"STORAGE_READ_BASE","cost_category":"WASM_HOST_COST","gas_used":"450854766000"},{"cost":"STORAGE_READ_KEY_BYTE","cost_category":"WASM_HOST_COST","gas_used":"4952405280"},{"cost":"STORAGE_READ_VALUE_BYTE","cost_category":"WASM_HOST_COST","gas_used":"1806743610"},{"cost":"STORAGE_WRITE_BASE","cost_category":"WASM_HOST_COST","gas_used":"256786944000"},{"cost":"STORAGE_WRITE_EVICTED_BYTE","cost_category":"WASM_HOST_COST","gas_used":"2826323016"},{"cost":"STORAGE_WRITE_KEY_BYTE","cost_category":"WASM_HOST_COST","gas_used":"5638629360"},{"cost":"STORAGE_WRITE_VALUE_BYTE","cost_category":"WASM_HOST_COST","gas_used":"8685190920"},{"cost":"TOUCHING_TRIE_NODE","cost_category":"WASM_HOST_COST","gas_used":"434752810002"},{"cost":"UTF8_DECODING_BASE","cost_category":"WASM_HOST_COST","gas_used":"6223558122"},{"cost":"UTF8_DECODING_BYTE","cost_category":"WASM_HOST_COST","gas_used":"27700145505"},{"cost":"WASM_INSTRUCTION","cost_category":"WASM_HOST_COST","gas_used":"126491330196"},{"cost":"WRITE_MEMORY_BASE","cost_category":"WASM_HOST_COST","gas_used":"28037948610"},{"cost":"WRITE_MEMORY_BYTE","cost_category":"WASM_HOST_COST","gas_used":"1459941792"},{"cost":"WRITE_REGISTER_BASE","cost_category":"WASM_HOST_COST","gas_used":"28655224860"},{"cost":"WRITE_REGISTER_BYTE","cost_category":"WASM_HOST_COST","gas_used":"2311350912"}],"version":3},"receipt_ids":["8ZD92cLpoCEU46hPGFfk3VqZpU8s6DoQhZ4pCMqWwDT6"],"status":{"SuccessValue":""},"tokens_burnt":"290616005416100000000"},"proof":[{"direction":"Left","hash":"BoQHueiPH9e4C7fkxouV4tFpGZ4hK5fJhKQnPBWwPazS"},{"direction":"Right","hash":"Ayxj8iVFTJMzZa7estoTtuBKJaUNhoipaaM7WmTjkkiS"}]},{"block_hash":"3rEx3xmgLCRgUfSgueD71YNrJYQYNvhtkXaqVQxdmj4U","id":"8ZD92cLpoCEU46hPGFfk3VqZpU8s6DoQhZ4pCMqWwDT6","outcome":{"executor_id":"btc-client.testnet","gas_burnt":223182562500,"logs":[],"metadata":{"gas_profile":[],"version":3},"receipt_ids":[],"status":{"SuccessValue":""},"tokens_burnt":"0"},"proof":[{"direction":"Right","hash":"8yEwg14D2GyyLNnJMxdSLDJKyrKShMAL3zTnf9YpQyPW"},{"direction":"Right","hash":"2UK7BfpHf9fCCsvmfHktDfz6Rh8sFihhN6cuTU3R4BBA"}]}],"status":{"SuccessValue":""},"transaction":{"actions":[{"FunctionCall":{"args":"AQAAAABA0CKoR96WKs+KPP6zPl0flT6XC91eR3uAUgwNAAAAAAAAAAzcZU0cipmejc+wGqnRJchd5uM6qRJM5Oojp3FrkJ2HVmGyZsnyFBlkvks8","deposit":"0","gas":100000000000000,"method_name":"submit_blocks"}}],"hash":"GMUCDLHFJVvmZYXmPf9QeUVAt9r9hXcQP1yL5emPFnvx","nonce":170437577001422,"priority_fee":0,"public_key":"ed25519:HM7ax8jJf41JozvanXepzhtD45AeRFcwJQCuLXFuDkjA","receiver_id":"btc-client.testnet","signature":"ed25519:2Qe3ccPSdzPddk764vm5jt4yXcvXgYQz3WzGF3oXpZLuaRa6ggpD131nSSy3FRVPquCvxYqgMGtdum8TKX3dVqNk","signer_id":"btc-client.testnet"},"transaction_outcome":{"block_hash":"9SP8Y3sVADWNN5QoEB5CsvPUE5HT4o8YfBaCnhLss87K","id":"GMUCDLHFJVvmZYXmPf9QeUVAt9r9hXcQP1yL5emPFnvx","outcome":{"executor_id":"btc-client.testnet","gas_burnt":308276385598,"logs":[],"metadata":{"gas_profile":null,"version":1},"receipt_ids":["e2XGEosf843XMiCJHvZufvHKyw419ZYibDBdVJQr9cB"],"status":{"SuccessReceiptId":"e2XGEosf843XMiCJHvZufvHKyw419ZYibDBdVJQr9cB"},"tokens_burnt":"30827638559800000000"},"proof":[{"direction":"Right","hash":"HDgWEk2okmDdAFAVf6ffxGBH6F6vdLM1X3H5Fmaafe4S"},{"direction":"Right","hash":"Ayxj8iVFTJMzZa7estoTtuBKJaUNhoipaaM7WmTjkkiS"}]}}"#;
2956 let view: FinalExecutionOutcomeViewEnum = serde_json::from_str(json).unwrap();
2957 assert!(matches!(view, FinalExecutionOutcomeViewEnum::FinalExecutionOutcome(_)));
2958 }
2959}