You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

views.rs 35KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044
  1. use crate::errors::TxExecutionError;
  2. use crate::receipt::*;
  3. use crate::transaction::*;
  4. use crate::types::*;
  5. use borsh::{BorshDeserialize, BorshSerialize};
  6. use common_api::crypto::prelude::*;
  7. use near_primitives_core::{
  8. account::{AccessKey, AccessKeyPermission, Account, FunctionCallPermission},
  9. contract::ContractCode,
  10. hash::{hash, CryptoHash},
  11. profile::Cost,
  12. serialize::{base64_format, dec_format, option_base64_format},
  13. types::*,
  14. };
  15. use serde::{Deserialize, Serialize};
  16. use std::{fmt, sync::Arc};
  17. use chrono::DateTime;
  18. #[derive(
  19. BorshSerialize,
  20. BorshDeserialize,
  21. Serialize,
  22. Deserialize,
  23. Hash,
  24. Eq,
  25. PartialEq,
  26. Ord,
  27. PartialOrd,
  28. Clone,
  29. Debug,
  30. Default,
  31. )]
  32. pub struct ChunkHash(pub CryptoHash);
  33. impl ChunkHash {
  34. pub fn as_bytes(&self) -> &[u8; 32] {
  35. self.0.as_bytes()
  36. }
  37. }
  38. impl AsRef<[u8]> for ChunkHash {
  39. fn as_ref(&self) -> &[u8] {
  40. self.0.as_ref()
  41. }
  42. }
  43. impl From<ChunkHash> for Vec<u8> {
  44. fn from(chunk_hash: ChunkHash) -> Self {
  45. chunk_hash.0.into()
  46. }
  47. }
  48. impl From<CryptoHash> for ChunkHash {
  49. fn from(crypto_hash: CryptoHash) -> Self {
  50. Self(crypto_hash)
  51. }
  52. }
  53. #[derive(Debug, Clone, PartialEq, Eq, BorshSerialize, BorshDeserialize, Serialize, Deserialize)]
  54. pub struct MerklePathItem {
  55. pub hash: MerkleHash,
  56. pub direction: Direction,
  57. }
  58. #[derive(Debug, Clone, PartialEq, Eq, BorshSerialize, BorshDeserialize, Serialize, Deserialize)]
  59. pub enum Direction {
  60. Left,
  61. Right,
  62. }
  63. pub type MerklePath = Vec<MerklePathItem>;
  64. /// A view of the account
  65. #[derive(Serialize, Deserialize, Debug, Eq, PartialEq, Clone)]
  66. pub struct AccountView {
  67. #[serde(with = "dec_format")]
  68. pub amount: Balance,
  69. #[serde(with = "dec_format")]
  70. pub locked: Balance,
  71. pub code_hash: CryptoHash,
  72. pub storage_usage: StorageUsage,
  73. /// TODO(2271): deprecated.
  74. #[serde(default)]
  75. pub storage_paid_at: BlockHeight,
  76. }
  77. /// A view of the contract code.
  78. #[derive(Serialize, Deserialize, PartialEq, Eq, Debug, Clone)]
  79. pub struct ContractCodeView {
  80. #[serde(rename = "code_base64", with = "base64_format")]
  81. pub code: Vec<u8>,
  82. pub hash: CryptoHash,
  83. }
  84. impl From<&Account> for AccountView {
  85. fn from(account: &Account) -> Self {
  86. AccountView {
  87. amount: account.amount(),
  88. locked: account.locked(),
  89. code_hash: account.code_hash(),
  90. storage_usage: account.storage_usage(),
  91. storage_paid_at: 0,
  92. }
  93. }
  94. }
  95. impl From<Account> for AccountView {
  96. fn from(account: Account) -> Self {
  97. (&account).into()
  98. }
  99. }
  100. impl From<&AccountView> for Account {
  101. fn from(view: &AccountView) -> Self {
  102. Account::new(view.amount, view.locked, view.code_hash, view.storage_usage)
  103. }
  104. }
  105. impl From<AccountView> for Account {
  106. fn from(view: AccountView) -> Self {
  107. (&view).into()
  108. }
  109. }
  110. impl From<ContractCode> for ContractCodeView {
  111. fn from(contract_code: ContractCode) -> Self {
  112. let hash = *contract_code.hash();
  113. let code = contract_code.into_code();
  114. ContractCodeView { code, hash }
  115. }
  116. }
  117. impl From<ContractCodeView> for ContractCode {
  118. fn from(contract_code: ContractCodeView) -> Self {
  119. ContractCode::new(contract_code.code, Some(contract_code.hash))
  120. }
  121. }
  122. #[derive(BorshSerialize, BorshDeserialize, Serialize, Deserialize, Debug, Eq, PartialEq, Clone)]
  123. pub enum AccessKeyPermissionView {
  124. FunctionCall {
  125. #[serde(with = "dec_format")]
  126. allowance: Option<Balance>,
  127. receiver_id: String,
  128. method_names: Vec<String>,
  129. },
  130. FullAccess,
  131. }
  132. impl From<AccessKeyPermission> for AccessKeyPermissionView {
  133. fn from(permission: AccessKeyPermission) -> Self {
  134. match permission {
  135. AccessKeyPermission::FunctionCall(func_call) => AccessKeyPermissionView::FunctionCall {
  136. allowance: func_call.allowance,
  137. receiver_id: func_call.receiver_id,
  138. method_names: func_call.method_names,
  139. },
  140. AccessKeyPermission::FullAccess => AccessKeyPermissionView::FullAccess,
  141. }
  142. }
  143. }
  144. impl From<AccessKeyPermissionView> for AccessKeyPermission {
  145. fn from(view: AccessKeyPermissionView) -> Self {
  146. match view {
  147. AccessKeyPermissionView::FunctionCall {
  148. allowance,
  149. receiver_id,
  150. method_names,
  151. } => AccessKeyPermission::FunctionCall(FunctionCallPermission {
  152. allowance,
  153. receiver_id,
  154. method_names,
  155. }),
  156. AccessKeyPermissionView::FullAccess => AccessKeyPermission::FullAccess,
  157. }
  158. }
  159. }
  160. #[derive(BorshSerialize, BorshDeserialize, Serialize, Deserialize, Debug, Eq, PartialEq, Clone)]
  161. pub struct AccessKeyView {
  162. pub nonce: Nonce,
  163. pub permission: AccessKeyPermissionView,
  164. }
  165. impl From<AccessKey> for AccessKeyView {
  166. fn from(access_key: AccessKey) -> Self {
  167. Self {
  168. nonce: access_key.nonce,
  169. permission: access_key.permission.into(),
  170. }
  171. }
  172. }
  173. impl From<AccessKeyView> for AccessKey {
  174. fn from(view: AccessKeyView) -> Self {
  175. Self {
  176. nonce: view.nonce,
  177. permission: view.permission.into(),
  178. }
  179. }
  180. }
  181. /// Item of the state, key and value are serialized in base64 and proof for inclusion of given state item.
  182. #[derive(Serialize, Deserialize, Debug, PartialEq, Eq, Clone)]
  183. pub struct StateItem {
  184. #[serde(with = "base64_format")]
  185. pub key: Vec<u8>,
  186. #[serde(with = "base64_format")]
  187. pub value: Vec<u8>,
  188. /// Deprecated, always empty, eventually will be deleted.
  189. // TODO(mina86): This was deprecated in 1.30. Get rid of the field
  190. // altogether at 1.33 or something.
  191. #[serde(default)]
  192. pub proof: Vec<()>,
  193. }
  194. #[derive(Serialize, Deserialize, Debug, PartialEq, Eq, Clone)]
  195. pub struct ViewStateResult {
  196. pub values: Vec<StateItem>,
  197. // TODO(mina86): Empty proof (i.e. sending proof when include_proof is not
  198. // set in the request) was deprecated in 1.30. Add
  199. // `#[serde(skip(Vec::if_empty))` at 1.33 or something.
  200. pub proof: Vec<Arc<[u8]>>,
  201. }
  202. #[derive(Serialize, Deserialize, Debug, PartialEq, Eq, Clone, Default)]
  203. pub struct CallResult {
  204. pub result: Vec<u8>,
  205. pub logs: Vec<String>,
  206. }
  207. #[derive(Serialize, Deserialize, Debug, PartialEq, Eq, Clone)]
  208. pub struct QueryError {
  209. pub error: String,
  210. pub logs: Vec<String>,
  211. }
  212. #[derive(Serialize, Deserialize, Debug, PartialEq, Eq, Clone)]
  213. pub struct AccessKeyInfoView {
  214. pub public_key: Ed25519PublicKey,
  215. pub access_key: AccessKeyView,
  216. }
  217. #[derive(Serialize, Deserialize, Debug, PartialEq, Eq, Clone)]
  218. pub struct AccessKeyList {
  219. pub keys: Vec<AccessKeyInfoView>,
  220. }
  221. impl FromIterator<AccessKeyInfoView> for AccessKeyList {
  222. fn from_iter<I: IntoIterator<Item = AccessKeyInfoView>>(iter: I) -> Self {
  223. Self {
  224. keys: iter.into_iter().collect(),
  225. }
  226. }
  227. }
  228. #[derive(Serialize, Deserialize, Debug, PartialEq, Eq)]
  229. pub struct BlockStatusView {
  230. pub height: BlockHeight,
  231. pub hash: CryptoHash,
  232. }
  233. impl BlockStatusView {
  234. pub fn new(height: &BlockHeight, hash: &CryptoHash) -> BlockStatusView {
  235. Self {
  236. height: *height,
  237. hash: *hash,
  238. }
  239. }
  240. }
  241. #[derive(Serialize, Deserialize, Debug)]
  242. pub struct BlockByChunksView {
  243. pub height: BlockHeight,
  244. pub hash: CryptoHash,
  245. pub block_status: String,
  246. pub chunk_status: String,
  247. }
  248. #[derive(Serialize, Deserialize, Debug)]
  249. pub struct ChainProcessingInfo {
  250. pub num_blocks_in_processing: usize,
  251. pub num_orphans: usize,
  252. pub num_blocks_missing_chunks: usize,
  253. /// contains processing info of recent blocks, ordered by height high to low
  254. pub blocks_info: Vec<BlockProcessingInfo>,
  255. /// contains processing info of chunks that we don't know which block it belongs to yet
  256. pub floating_chunks_info: Vec<ChunkProcessingInfo>,
  257. }
  258. #[derive(Serialize, Deserialize, Debug)]
  259. pub struct BlockProcessingInfo {
  260. pub height: BlockHeight,
  261. pub hash: CryptoHash,
  262. pub received_timestamp: DateTime<chrono::Utc>,
  263. /// Timestamp when block was received.
  264. //pub received_timestamp: DateTime<chrono::Utc>,
  265. /// Time (in ms) between when the block was first received and when it was processed
  266. pub in_progress_ms: u128,
  267. /// Time (in ms) that the block spent in the orphan pool. If the block was never put in the
  268. /// orphan pool, it is None. If the block is still in the orphan pool, it is since the time
  269. /// it was put into the pool until the current time.
  270. pub orphaned_ms: Option<u128>,
  271. /// Time (in ms) that the block spent in the missing chunks pool. If the block was never put in the
  272. /// missing chunks pool, it is None. If the block is still in the missing chunks pool, it is
  273. /// since the time it was put into the pool until the current time.
  274. pub missing_chunks_ms: Option<u128>,
  275. pub block_status: BlockProcessingStatus,
  276. /// Only contains new chunks that belong to this block, if the block doesn't produce a new chunk
  277. /// for a shard, the corresponding item will be None.
  278. pub chunks_info: Vec<Option<ChunkProcessingInfo>>,
  279. }
  280. #[derive(BorshSerialize, BorshDeserialize, Serialize, Deserialize, Clone, Debug, PartialEq, Eq)]
  281. pub enum BlockProcessingStatus {
  282. Orphan,
  283. WaitingForChunks,
  284. InProcessing,
  285. Accepted,
  286. Error(String),
  287. Dropped(DroppedReason),
  288. Unknown,
  289. }
  290. #[derive(BorshSerialize, BorshDeserialize, Serialize, Deserialize, Clone, Debug, PartialEq, Eq)]
  291. pub enum DroppedReason {
  292. // If the node has already processed a block at this height
  293. HeightProcessed,
  294. // If the block processing pool is full
  295. TooManyProcessingBlocks,
  296. }
  297. #[derive(Serialize, Deserialize, Debug)]
  298. pub struct ChunkProcessingInfo {
  299. pub height_created: BlockHeight,
  300. pub shard_id: ShardId,
  301. pub chunk_hash: ChunkHash,
  302. pub prev_block_hash: CryptoHash,
  303. /// Account id of the validator who created this chunk
  304. /// Theoretically this field should never be None unless there is some database corruption.
  305. pub created_by: Option<AccountId>,
  306. pub status: ChunkProcessingStatus,
  307. /// Timestamp of first time when we request for this chunk.
  308. pub requested_timestamp: Option<DateTime<chrono::Utc>>,
  309. /// Timestamp of when the chunk is complete
  310. pub completed_timestamp: Option<DateTime<chrono::Utc>>,
  311. /// Time (in millis) that it takes between when the chunk is requested and when it is completed.
  312. pub request_duration: Option<u64>,
  313. pub chunk_parts_collection: Vec<PartCollectionInfo>,
  314. }
  315. #[derive(Serialize, Deserialize, Debug)]
  316. pub struct PartCollectionInfo {
  317. pub part_owner: AccountId,
  318. // Time when the part is received through any message
  319. pub received_time: Option<DateTime<chrono::Utc>>,
  320. // Time when we receive a PartialEncodedChunkForward containing this part
  321. pub forwarded_received_time: Option<DateTime<chrono::Utc>>,
  322. // Time when we receive the PartialEncodedChunk message containing this part
  323. pub chunk_received_time: Option<DateTime<chrono::Utc>>,
  324. }
  325. #[derive(Serialize, Deserialize, Debug)]
  326. pub enum ChunkProcessingStatus {
  327. NeedToRequest,
  328. Requested,
  329. Completed,
  330. }
  331. #[derive(Serialize, Deserialize, Debug, Clone)]
  332. pub struct BlockHeaderView {
  333. pub height: BlockHeight,
  334. pub prev_height: Option<BlockHeight>,
  335. pub epoch_id: CryptoHash,
  336. pub next_epoch_id: CryptoHash,
  337. pub hash: CryptoHash,
  338. pub prev_hash: CryptoHash,
  339. pub prev_state_root: CryptoHash,
  340. pub chunk_receipts_root: CryptoHash,
  341. pub chunk_headers_root: CryptoHash,
  342. pub chunk_tx_root: CryptoHash,
  343. pub outcome_root: CryptoHash,
  344. pub chunks_included: u64,
  345. pub challenges_root: CryptoHash,
  346. /// Legacy json number. Should not be used.
  347. pub timestamp: u64,
  348. #[serde(with = "dec_format")]
  349. pub timestamp_nanosec: u64,
  350. pub random_value: CryptoHash,
  351. pub chunk_mask: Vec<bool>,
  352. #[serde(with = "dec_format")]
  353. pub gas_price: Balance,
  354. pub block_ordinal: Option<NumBlocks>,
  355. /// TODO(2271): deprecated.
  356. #[serde(with = "dec_format")]
  357. pub rent_paid: Balance,
  358. /// TODO(2271): deprecated.
  359. #[serde(with = "dec_format")]
  360. pub validator_reward: Balance,
  361. #[serde(with = "dec_format")]
  362. pub total_supply: Balance,
  363. pub last_final_block: CryptoHash,
  364. pub last_ds_final_block: CryptoHash,
  365. pub next_bp_hash: CryptoHash,
  366. pub block_merkle_root: CryptoHash,
  367. pub epoch_sync_data_hash: Option<CryptoHash>,
  368. pub approvals: Vec<Option<Ed25519Signature>>,
  369. pub signature: Ed25519Signature,
  370. pub latest_protocol_version: ProtocolVersion,
  371. }
  372. #[derive(Serialize, Deserialize, Debug, Clone)]
  373. pub struct ChunkHeaderView {
  374. pub chunk_hash: CryptoHash,
  375. pub prev_block_hash: CryptoHash,
  376. pub outcome_root: CryptoHash,
  377. pub prev_state_root: StateRoot,
  378. pub encoded_merkle_root: CryptoHash,
  379. pub encoded_length: u64,
  380. pub height_created: BlockHeight,
  381. pub height_included: BlockHeight,
  382. pub shard_id: ShardId,
  383. pub gas_used: Gas,
  384. pub gas_limit: Gas,
  385. /// TODO(2271): deprecated.
  386. #[serde(with = "dec_format")]
  387. pub rent_paid: Balance,
  388. /// TODO(2271): deprecated.
  389. #[serde(with = "dec_format")]
  390. pub validator_reward: Balance,
  391. #[serde(with = "dec_format")]
  392. pub balance_burnt: Balance,
  393. pub outgoing_receipts_root: CryptoHash,
  394. pub tx_root: CryptoHash,
  395. pub signature: Ed25519Signature,
  396. }
  397. #[derive(Serialize, Deserialize, Debug)]
  398. pub struct BlockView {
  399. pub author: AccountId,
  400. pub header: BlockHeaderView,
  401. pub chunks: Vec<ChunkHeaderView>,
  402. }
  403. #[derive(Serialize, Deserialize, Debug)]
  404. pub struct ChunkView {
  405. pub author: AccountId,
  406. pub header: ChunkHeaderView,
  407. pub transactions: Vec<SignedTransactionView>,
  408. pub receipts: Vec<ReceiptView>,
  409. }
  410. #[derive(BorshSerialize, BorshDeserialize, Serialize, Deserialize, Clone, Debug, PartialEq, Eq)]
  411. pub enum ActionView {
  412. CreateAccount,
  413. DeployContract {
  414. #[serde(with = "base64_format")]
  415. code: Vec<u8>,
  416. },
  417. FunctionCall {
  418. method_name: String,
  419. #[serde(with = "base64_format")]
  420. args: Vec<u8>,
  421. gas: Gas,
  422. #[serde(with = "dec_format")]
  423. deposit: Balance,
  424. },
  425. Transfer {
  426. #[serde(with = "dec_format")]
  427. deposit: Balance,
  428. },
  429. Stake {
  430. #[serde(with = "dec_format")]
  431. stake: Balance,
  432. public_key: Ed25519PublicKey,
  433. },
  434. AddKey {
  435. public_key: Ed25519PublicKey,
  436. access_key: AccessKeyView,
  437. },
  438. DeleteKey {
  439. public_key: Ed25519PublicKey,
  440. },
  441. DeleteAccount {
  442. beneficiary_id: AccountId,
  443. },
  444. }
  445. impl From<Action> for ActionView {
  446. fn from(action: Action) -> Self {
  447. match action {
  448. Action::CreateAccount(_) => ActionView::CreateAccount,
  449. Action::DeployContract(action) => {
  450. let code = hash(&action.code).as_ref().to_vec();
  451. ActionView::DeployContract { code }
  452. }
  453. Action::FunctionCall(action) => ActionView::FunctionCall {
  454. method_name: action.method_name,
  455. args: action.args,
  456. gas: action.gas,
  457. deposit: action.deposit,
  458. },
  459. Action::Transfer(action) => ActionView::Transfer {
  460. deposit: action.deposit,
  461. },
  462. Action::Stake(action) => ActionView::Stake {
  463. stake: action.stake,
  464. public_key: action.public_key,
  465. },
  466. Action::AddKey(action) => ActionView::AddKey {
  467. public_key: action.public_key,
  468. access_key: action.access_key.into(),
  469. },
  470. Action::DeleteKey(action) => ActionView::DeleteKey {
  471. public_key: action.public_key,
  472. },
  473. Action::DeleteAccount(action) => ActionView::DeleteAccount {
  474. beneficiary_id: action.beneficiary_id,
  475. },
  476. }
  477. }
  478. }
  479. impl TryFrom<ActionView> for Action {
  480. type Error = Box<dyn std::error::Error + Send + Sync>;
  481. fn try_from(action_view: ActionView) -> Result<Self, Self::Error> {
  482. Ok(match action_view {
  483. ActionView::CreateAccount => Action::CreateAccount(CreateAccountAction {}),
  484. ActionView::DeployContract { code } => {
  485. Action::DeployContract(DeployContractAction { code })
  486. }
  487. ActionView::FunctionCall {
  488. method_name,
  489. args,
  490. gas,
  491. deposit,
  492. } => Action::FunctionCall(FunctionCallAction {
  493. method_name,
  494. args,
  495. gas,
  496. deposit,
  497. }),
  498. ActionView::Transfer { deposit } => Action::Transfer(TransferAction { deposit }),
  499. ActionView::Stake { stake, public_key } => {
  500. Action::Stake(StakeAction { stake, public_key })
  501. }
  502. ActionView::AddKey {
  503. public_key,
  504. access_key,
  505. } => Action::AddKey(AddKeyAction {
  506. public_key,
  507. access_key: access_key.into(),
  508. }),
  509. ActionView::DeleteKey { public_key } => {
  510. Action::DeleteKey(DeleteKeyAction { public_key })
  511. }
  512. ActionView::DeleteAccount { beneficiary_id } => {
  513. Action::DeleteAccount(DeleteAccountAction { beneficiary_id })
  514. }
  515. })
  516. }
  517. }
  518. #[derive(BorshSerialize, BorshDeserialize, Serialize, Deserialize, Debug, PartialEq, Eq, Clone)]
  519. pub struct SignedTransactionView {
  520. pub signer_id: AccountId,
  521. pub public_key: Ed25519PublicKey,
  522. pub nonce: Nonce,
  523. pub receiver_id: AccountId,
  524. pub actions: Vec<ActionView>,
  525. pub signature: Ed25519Signature,
  526. pub hash: CryptoHash,
  527. }
  528. impl From<SignedTransaction> for SignedTransactionView {
  529. fn from(signed_tx: SignedTransaction) -> Self {
  530. let hash = signed_tx.get_hash();
  531. SignedTransactionView {
  532. signer_id: signed_tx.transaction.signer_id,
  533. public_key: signed_tx.transaction.public_key,
  534. nonce: signed_tx.transaction.nonce,
  535. receiver_id: signed_tx.transaction.receiver_id,
  536. actions: signed_tx
  537. .transaction
  538. .actions
  539. .into_iter()
  540. .map(|action| action.into())
  541. .collect(),
  542. signature: signed_tx.signature,
  543. hash,
  544. }
  545. }
  546. }
  547. #[allow(clippy::large_enum_variant)]
  548. #[derive(
  549. Default, BorshSerialize, BorshDeserialize, Serialize, Deserialize, PartialEq, Eq, Clone,
  550. )]
  551. pub enum FinalExecutionStatus {
  552. /// The execution has not yet started.
  553. #[default]
  554. NotStarted,
  555. /// The execution has started and still going.
  556. Started,
  557. /// The execution has failed with the given error.
  558. Failure(TxExecutionError),
  559. /// The execution has succeeded and returned some value or an empty vec encoded in base64.
  560. SuccessValue(#[serde(with = "base64_format")] Vec<u8>),
  561. }
  562. impl fmt::Debug for FinalExecutionStatus {
  563. fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
  564. match self {
  565. FinalExecutionStatus::NotStarted => f.write_str("NotStarted"),
  566. FinalExecutionStatus::Started => f.write_str("Started"),
  567. FinalExecutionStatus::Failure(e) => f.write_fmt(format_args!("Failure({e:?})")),
  568. FinalExecutionStatus::SuccessValue(v) => {
  569. f.write_fmt(format_args!("SuccessValue({v:?})"))
  570. }
  571. }
  572. }
  573. }
  574. #[allow(clippy::large_enum_variant)]
  575. #[derive(BorshSerialize, BorshDeserialize, Serialize, Deserialize, Debug, PartialEq, Eq, Clone)]
  576. pub enum ServerError {
  577. TxExecutionError(TxExecutionError),
  578. Timeout,
  579. Closed,
  580. }
  581. #[allow(clippy::large_enum_variant)]
  582. #[derive(BorshSerialize, BorshDeserialize, Serialize, Deserialize, PartialEq, Eq, Clone)]
  583. pub enum ExecutionStatusView {
  584. /// The execution is pending or unknown.
  585. Unknown,
  586. /// The execution has failed.
  587. Failure(TxExecutionError),
  588. /// The final action succeeded and returned some value or an empty vec encoded in base64.
  589. SuccessValue(#[serde(with = "base64_format")] Vec<u8>),
  590. /// The final action of the receipt returned a promise or the signed transaction was converted
  591. /// to a receipt. Contains the receipt_id of the generated receipt.
  592. SuccessReceiptId(CryptoHash),
  593. }
  594. impl fmt::Debug for ExecutionStatusView {
  595. fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
  596. match self {
  597. ExecutionStatusView::Unknown => f.write_str("Unknown"),
  598. ExecutionStatusView::Failure(e) => f.write_fmt(format_args!("Failure({e:?})")),
  599. ExecutionStatusView::SuccessValue(v) => {
  600. f.write_fmt(format_args!("SuccessValue({v:?})"))
  601. }
  602. ExecutionStatusView::SuccessReceiptId(receipt_id) => {
  603. f.write_fmt(format_args!("SuccessReceiptId({receipt_id})"))
  604. }
  605. }
  606. }
  607. }
  608. impl From<ExecutionStatus> for ExecutionStatusView {
  609. fn from(outcome: ExecutionStatus) -> Self {
  610. match outcome {
  611. ExecutionStatus::Unknown => ExecutionStatusView::Unknown,
  612. ExecutionStatus::Failure(e) => ExecutionStatusView::Failure(*e),
  613. ExecutionStatus::SuccessValue(v) => ExecutionStatusView::SuccessValue(v),
  614. ExecutionStatus::SuccessReceiptId(receipt_id) => {
  615. ExecutionStatusView::SuccessReceiptId(receipt_id)
  616. }
  617. }
  618. }
  619. }
  620. #[derive(BorshSerialize, BorshDeserialize, Serialize, Deserialize, PartialEq, Clone, Eq, Debug)]
  621. pub struct CostGasUsed {
  622. pub cost_category: String,
  623. pub cost: String,
  624. #[serde(with = "dec_format")]
  625. pub gas_used: Gas,
  626. }
  627. #[derive(BorshSerialize, BorshDeserialize, Serialize, Deserialize, PartialEq, Clone, Eq, Debug)]
  628. pub struct ExecutionMetadataView {
  629. pub version: u32,
  630. pub gas_profile: Option<Vec<CostGasUsed>>,
  631. }
  632. impl Default for ExecutionMetadataView {
  633. fn default() -> Self {
  634. ExecutionMetadata::V1.into()
  635. }
  636. }
  637. impl From<ExecutionMetadata> for ExecutionMetadataView {
  638. fn from(metadata: ExecutionMetadata) -> Self {
  639. let gas_profile = match metadata {
  640. ExecutionMetadata::V1 => None,
  641. ExecutionMetadata::V2(profile_data) => {
  642. let mut costs: Vec<_> = Cost::ALL
  643. .iter()
  644. .filter(|&cost| profile_data[*cost] > 0)
  645. .map(|&cost| CostGasUsed {
  646. cost_category: match cost {
  647. Cost::ActionCost { .. } => "ACTION_COST",
  648. Cost::ExtCost { .. } => "WASM_HOST_COST",
  649. Cost::WasmInstruction => "WASM_HOST_COST",
  650. }
  651. .to_string(),
  652. cost: match cost {
  653. Cost::ActionCost {
  654. action_cost_kind: action_cost,
  655. } => format!("{action_cost:?}").to_ascii_uppercase(),
  656. Cost::ExtCost {
  657. ext_cost_kind: ext_cost,
  658. } => format!("{ext_cost:?}").to_ascii_uppercase(),
  659. Cost::WasmInstruction => "WASM_INSTRUCTION".to_string(),
  660. },
  661. gas_used: profile_data[cost],
  662. })
  663. .collect();
  664. // The order doesn't really matter, but the default one is just
  665. // historical, which is especially unintuitive, so let's sort
  666. // lexicographically.
  667. //
  668. // Can't `sort_by_key` here because lifetime inference in
  669. // closures is limited.
  670. costs.sort_by(|lhs, rhs| {
  671. lhs.cost_category
  672. .cmp(&rhs.cost_category)
  673. .then(lhs.cost.cmp(&rhs.cost))
  674. });
  675. Some(costs)
  676. }
  677. };
  678. ExecutionMetadataView {
  679. version: 1,
  680. gas_profile,
  681. }
  682. }
  683. }
  684. #[derive(BorshSerialize, BorshDeserialize, Serialize, Deserialize, Debug, Clone, PartialEq, Eq)]
  685. pub struct ExecutionOutcomeView {
  686. /// Logs from this transaction or receipt.
  687. pub logs: Vec<String>,
  688. /// Receipt IDs generated by this transaction or receipt.
  689. pub receipt_ids: Vec<CryptoHash>,
  690. /// The amount of the gas burnt by the given transaction or receipt.
  691. pub gas_burnt: Gas,
  692. /// The amount of tokens burnt corresponding to the burnt gas amount.
  693. /// This value doesn't always equal to the `gas_burnt` multiplied by the gas price, because
  694. /// the prepaid gas price might be lower than the actual gas price and it creates a deficit.
  695. #[serde(with = "dec_format")]
  696. pub tokens_burnt: Balance,
  697. /// The id of the account on which the execution happens. For transaction this is signer_id,
  698. /// for receipt this is receiver_id.
  699. pub executor_id: AccountId,
  700. /// Execution status. Contains the result in case of successful execution.
  701. pub status: ExecutionStatusView,
  702. /// Execution metadata, versioned
  703. #[serde(default)]
  704. pub metadata: ExecutionMetadataView,
  705. }
  706. impl From<ExecutionOutcome> for ExecutionOutcomeView {
  707. fn from(outcome: ExecutionOutcome) -> Self {
  708. Self {
  709. logs: outcome.logs,
  710. receipt_ids: outcome.receipt_ids,
  711. gas_burnt: outcome.gas_burnt,
  712. tokens_burnt: outcome.tokens_burnt,
  713. executor_id: outcome.executor_id,
  714. status: outcome.status.into(),
  715. metadata: outcome.metadata.into(),
  716. }
  717. }
  718. }
  719. impl From<&ExecutionOutcomeView> for PartialExecutionOutcome {
  720. fn from(outcome: &ExecutionOutcomeView) -> Self {
  721. Self {
  722. receipt_ids: outcome.receipt_ids.clone(),
  723. gas_burnt: outcome.gas_burnt,
  724. tokens_burnt: outcome.tokens_burnt,
  725. executor_id: outcome.executor_id.clone(),
  726. status: outcome.status.clone().into(),
  727. }
  728. }
  729. }
  730. impl From<ExecutionStatusView> for PartialExecutionStatus {
  731. fn from(status: ExecutionStatusView) -> PartialExecutionStatus {
  732. match status {
  733. ExecutionStatusView::Unknown => PartialExecutionStatus::Unknown,
  734. ExecutionStatusView::Failure(_) => PartialExecutionStatus::Failure,
  735. ExecutionStatusView::SuccessValue(value) => PartialExecutionStatus::SuccessValue(value),
  736. ExecutionStatusView::SuccessReceiptId(id) => {
  737. PartialExecutionStatus::SuccessReceiptId(id)
  738. }
  739. }
  740. }
  741. }
  742. impl ExecutionOutcomeView {
  743. // Same behavior as ExecutionOutcomeWithId's to_hashes.
  744. pub fn to_hashes(&self, id: CryptoHash) -> Vec<CryptoHash> {
  745. let mut result = Vec::with_capacity(2 + self.logs.len());
  746. result.push(id);
  747. result.push(CryptoHash::hash_borsh(&PartialExecutionOutcome::from(self)));
  748. result.extend(self.logs.iter().map(|log| hash(log.as_bytes())));
  749. result
  750. }
  751. }
  752. #[cfg_attr(feature = "deepsize_feature", derive(deepsize::DeepSizeOf))]
  753. #[derive(BorshSerialize, BorshDeserialize, Serialize, Deserialize, Debug, PartialEq, Eq, Clone)]
  754. pub struct ExecutionOutcomeWithIdView {
  755. pub proof: MerklePath,
  756. pub block_hash: CryptoHash,
  757. pub id: CryptoHash,
  758. pub outcome: ExecutionOutcomeView,
  759. }
  760. impl ExecutionOutcomeWithIdView {
  761. pub fn to_hashes(&self) -> Vec<CryptoHash> {
  762. self.outcome.to_hashes(self.id)
  763. }
  764. }
  765. #[derive(BorshSerialize, BorshDeserialize, Serialize, Deserialize, Debug)]
  766. #[serde(untagged)]
  767. pub enum FinalExecutionOutcomeViewEnum {
  768. FinalExecutionOutcome(FinalExecutionOutcomeView),
  769. FinalExecutionOutcomeWithReceipt(FinalExecutionOutcomeWithReceiptView),
  770. }
  771. impl FinalExecutionOutcomeViewEnum {
  772. pub fn into_outcome(self) -> FinalExecutionOutcomeView {
  773. match self {
  774. Self::FinalExecutionOutcome(outcome) => outcome,
  775. Self::FinalExecutionOutcomeWithReceipt(outcome) => outcome.final_outcome,
  776. }
  777. }
  778. }
  779. /// Final execution outcome of the transaction and all of subsequent the receipts.
  780. #[derive(BorshSerialize, BorshDeserialize, Serialize, Deserialize, PartialEq, Eq, Clone)]
  781. pub struct FinalExecutionOutcomeView {
  782. /// Execution status. Contains the result in case of successful execution.
  783. pub status: FinalExecutionStatus,
  784. /// Signed Transaction
  785. pub transaction: SignedTransactionView,
  786. /// The execution outcome of the signed transaction.
  787. pub transaction_outcome: ExecutionOutcomeWithIdView,
  788. /// The execution outcome of receipts.
  789. pub receipts_outcome: Vec<ExecutionOutcomeWithIdView>,
  790. }
  791. impl fmt::Debug for FinalExecutionOutcomeView {
  792. fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
  793. f.debug_struct("FinalExecutionOutcome")
  794. .field("status", &self.status)
  795. .field("transaction", &self.transaction)
  796. .field("transaction_outcome", &self.transaction_outcome)
  797. .field("receipts_outcome", &self.receipts_outcome)
  798. .finish()
  799. }
  800. }
  801. /// Final execution outcome of the transaction and all of subsequent the receipts. Also includes
  802. /// the generated receipt.
  803. #[derive(BorshSerialize, BorshDeserialize, Serialize, Deserialize, PartialEq, Eq, Clone, Debug)]
  804. pub struct FinalExecutionOutcomeWithReceiptView {
  805. /// Final outcome view without receipts
  806. #[serde(flatten)]
  807. pub final_outcome: FinalExecutionOutcomeView,
  808. /// Receipts generated from the transaction
  809. pub receipts: Vec<ReceiptView>,
  810. }
  811. #[derive(BorshSerialize, BorshDeserialize, Serialize, Deserialize, Clone, Debug, PartialEq, Eq)]
  812. pub struct ReceiptView {
  813. pub predecessor_id: AccountId,
  814. pub receiver_id: AccountId,
  815. pub receipt_id: CryptoHash,
  816. pub receipt: ReceiptEnumView,
  817. }
  818. #[derive(BorshSerialize, BorshDeserialize, Serialize, Deserialize, Clone, Debug, PartialEq, Eq)]
  819. pub struct DataReceiverView {
  820. pub data_id: CryptoHash,
  821. pub receiver_id: AccountId,
  822. }
  823. #[allow(clippy::large_enum_variant)]
  824. #[derive(BorshSerialize, BorshDeserialize, Serialize, Deserialize, Clone, Debug, PartialEq, Eq)]
  825. pub enum ReceiptEnumView {
  826. Action {
  827. signer_id: AccountId,
  828. signer_public_key: Ed25519PublicKey,
  829. #[serde(with = "dec_format")]
  830. gas_price: Balance,
  831. output_data_receivers: Vec<DataReceiverView>,
  832. input_data_ids: Vec<CryptoHash>,
  833. actions: Vec<ActionView>,
  834. },
  835. Data {
  836. data_id: CryptoHash,
  837. #[serde(with = "option_base64_format")]
  838. data: Option<Vec<u8>>,
  839. },
  840. }
  841. impl From<Receipt> for ReceiptView {
  842. fn from(receipt: Receipt) -> Self {
  843. ReceiptView {
  844. predecessor_id: receipt.predecessor_id,
  845. receiver_id: receipt.receiver_id,
  846. receipt_id: receipt.receipt_id,
  847. receipt: match receipt.receipt {
  848. ReceiptEnum::Action(action_receipt) => ReceiptEnumView::Action {
  849. signer_id: action_receipt.signer_id,
  850. signer_public_key: action_receipt.signer_public_key,
  851. gas_price: action_receipt.gas_price,
  852. output_data_receivers: action_receipt
  853. .output_data_receivers
  854. .into_iter()
  855. .map(|data_receiver| DataReceiverView {
  856. data_id: data_receiver.data_id,
  857. receiver_id: data_receiver.receiver_id,
  858. })
  859. .collect(),
  860. input_data_ids: action_receipt
  861. .input_data_ids
  862. .into_iter()
  863. .map(Into::into)
  864. .collect(),
  865. actions: action_receipt.actions.into_iter().map(Into::into).collect(),
  866. },
  867. ReceiptEnum::Data(data_receipt) => ReceiptEnumView::Data {
  868. data_id: data_receipt.data_id,
  869. data: data_receipt.data,
  870. },
  871. },
  872. }
  873. }
  874. }
  875. impl TryFrom<ReceiptView> for Receipt {
  876. type Error = Box<dyn std::error::Error + Send + Sync>;
  877. fn try_from(receipt_view: ReceiptView) -> Result<Self, Self::Error> {
  878. Ok(Receipt {
  879. predecessor_id: receipt_view.predecessor_id,
  880. receiver_id: receipt_view.receiver_id,
  881. receipt_id: receipt_view.receipt_id,
  882. receipt: match receipt_view.receipt {
  883. ReceiptEnumView::Action {
  884. signer_id,
  885. signer_public_key,
  886. gas_price,
  887. output_data_receivers,
  888. input_data_ids,
  889. actions,
  890. } => ReceiptEnum::Action(ActionReceipt {
  891. signer_id,
  892. signer_public_key,
  893. gas_price,
  894. output_data_receivers: output_data_receivers
  895. .into_iter()
  896. .map(|data_receiver_view| DataReceiver {
  897. data_id: data_receiver_view.data_id,
  898. receiver_id: data_receiver_view.receiver_id,
  899. })
  900. .collect(),
  901. input_data_ids: input_data_ids.into_iter().map(Into::into).collect(),
  902. actions: actions
  903. .into_iter()
  904. .map(TryInto::try_into)
  905. .collect::<Result<Vec<_>, _>>()?,
  906. }),
  907. ReceiptEnumView::Data { data_id, data } => {
  908. ReceiptEnum::Data(DataReceipt { data_id, data })
  909. }
  910. },
  911. })
  912. }
  913. }
  914. #[derive(Serialize, Deserialize, Debug)]
  915. pub struct GasPriceView {
  916. #[serde(with = "dec_format")]
  917. pub gas_price: Balance,
  918. }
  919. /// See crate::types::StateChangeCause for details.
  920. #[derive(Debug, Serialize, Deserialize)]
  921. #[serde(rename_all = "snake_case", tag = "type")]
  922. pub enum StateChangeCauseView {
  923. NotWritableToDisk,
  924. InitialState,
  925. TransactionProcessing { tx_hash: CryptoHash },
  926. ActionReceiptProcessingStarted { receipt_hash: CryptoHash },
  927. ActionReceiptGasReward { receipt_hash: CryptoHash },
  928. ReceiptProcessing { receipt_hash: CryptoHash },
  929. PostponedReceipt { receipt_hash: CryptoHash },
  930. UpdatedDelayedReceipts,
  931. ValidatorAccountsUpdate,
  932. Migration,
  933. Resharding,
  934. }
  935. impl From<StateChangeCause> for StateChangeCauseView {
  936. fn from(state_change_cause: StateChangeCause) -> Self {
  937. match state_change_cause {
  938. StateChangeCause::NotWritableToDisk => Self::NotWritableToDisk,
  939. StateChangeCause::InitialState => Self::InitialState,
  940. StateChangeCause::TransactionProcessing { tx_hash } => {
  941. Self::TransactionProcessing { tx_hash }
  942. }
  943. StateChangeCause::ActionReceiptProcessingStarted { receipt_hash } => {
  944. Self::ActionReceiptProcessingStarted { receipt_hash }
  945. }
  946. StateChangeCause::ActionReceiptGasReward { receipt_hash } => {
  947. Self::ActionReceiptGasReward { receipt_hash }
  948. }
  949. StateChangeCause::ReceiptProcessing { receipt_hash } => {
  950. Self::ReceiptProcessing { receipt_hash }
  951. }
  952. StateChangeCause::PostponedReceipt { receipt_hash } => {
  953. Self::PostponedReceipt { receipt_hash }
  954. }
  955. StateChangeCause::UpdatedDelayedReceipts => Self::UpdatedDelayedReceipts,
  956. StateChangeCause::ValidatorAccountsUpdate => Self::ValidatorAccountsUpdate,
  957. StateChangeCause::Migration => Self::Migration,
  958. StateChangeCause::Resharding => Self::Resharding,
  959. }
  960. }
  961. }