1pub mod lmdb;
5
6pub mod scratch;
8
9use num_rational::Ratio;
10use parking_lot::RwLock;
11use std::{
12 cell::RefCell,
13 collections::{BTreeMap, BTreeSet},
14 convert::TryFrom,
15 rc::Rc,
16 sync::Arc,
17};
18
19use tracing::{debug, error, info, warn};
20
21use casper_types::{
22 account::AccountHash,
23 bytesrepr::{self, ToBytes},
24 contracts::NamedKeys,
25 execution::{Effects, TransformError, TransformInstruction, TransformKindV2, TransformV2},
26 global_state::TrieMerkleProof,
27 system::{
28 self,
29 auction::{
30 SeigniorageRecipientsSnapshot, ERA_END_TIMESTAMP_MILLIS_KEY, ERA_ID_KEY,
31 SEIGNIORAGE_RECIPIENTS_SNAPSHOT_KEY, SEIGNIORAGE_RECIPIENTS_SNAPSHOT_VERSION_KEY,
32 },
33 mint::{
34 BalanceHoldAddr, BalanceHoldAddrTag, ARG_AMOUNT, ROUND_SEIGNIORAGE_RATE_KEY,
35 TOTAL_SUPPLY_KEY,
36 },
37 AUCTION, HANDLE_PAYMENT, MINT,
38 },
39 Account, AddressableEntity, BlockGlobalAddr, CLValue, Digest, EntityAddr, EntityEntryPoint,
40 EntryPointAddr, EntryPointValue, HoldsEpoch, Key, KeyTag, Phase, PublicKey, RuntimeArgs,
41 StoredValue, SystemHashRegistry, U512,
42};
43
44#[cfg(test)]
45pub use self::lmdb::make_temporary_global_state;
46
47use super::trie_store::{operations::batch_write, TrieStoreCacheError};
48use crate::{
49 data_access_layer::{
50 auction::{AuctionMethodRet, BiddingRequest, BiddingResult},
51 balance::BalanceHandling,
52 era_validators::EraValidatorsResult,
53 handle_fee::{HandleFeeMode, HandleFeeRequest, HandleFeeResult},
54 mint::{
55 BurnRequest, BurnRequestArgs, BurnResult, TransferRequest, TransferRequestArgs,
56 TransferResult,
57 },
58 prefixed_values::{PrefixedValuesRequest, PrefixedValuesResult},
59 tagged_values::{TaggedValuesRequest, TaggedValuesResult},
60 AddressableEntityRequest, AddressableEntityResult, AuctionMethod, BalanceHoldError,
61 BalanceHoldKind, BalanceHoldMode, BalanceHoldRequest, BalanceHoldResult, BalanceIdentifier,
62 BalanceIdentifierPurseRequest, BalanceIdentifierPurseResult, BalanceRequest, BalanceResult,
63 BidsRequest, BidsResult, BlockGlobalKind, BlockGlobalRequest, BlockGlobalResult,
64 BlockRewardsError, BlockRewardsRequest, BlockRewardsResult, ContractRequest,
65 ContractResult, EntryPointExistsRequest, EntryPointExistsResult, EntryPointRequest,
66 EntryPointResult, EraValidatorsRequest, ExecutionResultsChecksumRequest,
67 ExecutionResultsChecksumResult, FeeError, FeeRequest, FeeResult, FlushRequest, FlushResult,
68 GenesisRequest, GenesisResult, HandleRefundMode, HandleRefundRequest, HandleRefundResult,
69 InsufficientBalanceHandling, MessageTopicsRequest, MessageTopicsResult, ProofHandling,
70 ProofsResult, ProtocolUpgradeRequest, ProtocolUpgradeResult, PruneRequest, PruneResult,
71 PutTrieRequest, PutTrieResult, QueryRequest, QueryResult, RoundSeigniorageRateRequest,
72 RoundSeigniorageRateResult, SeigniorageRecipientsRequest, SeigniorageRecipientsResult,
73 StepError, StepRequest, StepResult, SystemEntityRegistryPayload,
74 SystemEntityRegistryRequest, SystemEntityRegistryResult, SystemEntityRegistrySelector,
75 TotalSupplyRequest, TotalSupplyResult, TrieRequest, TrieResult,
76 EXECUTION_RESULTS_CHECKSUM_NAME,
77 },
78 global_state::{
79 error::Error as GlobalStateError,
80 state::scratch::ScratchGlobalState,
81 transaction_source::{Transaction, TransactionSource},
82 trie::Trie,
83 trie_store::{
84 operations::{prune, read, write, ReadResult, TriePruneResult, WriteResult},
85 TrieStore,
86 },
87 },
88 system::{
89 auction::{self, Auction},
90 burn::{BurnError, BurnRuntimeArgsBuilder},
91 genesis::{GenesisError, GenesisInstaller},
92 handle_payment::HandlePayment,
93 mint::Mint,
94 protocol_upgrade::{ProtocolUpgradeError, ProtocolUpgrader},
95 runtime_native::{Id, RuntimeNative},
96 transfer::{TransferArgs, TransferError, TransferRuntimeArgsBuilder, TransferTargetMode},
97 },
98 tracking_copy::{TrackingCopy, TrackingCopyEntityExt, TrackingCopyError, TrackingCopyExt},
99 AddressGenerator,
100};
101
102pub trait StateReader<K = Key, V = StoredValue>: Sized + Send + Sync {
104 type Error;
106
107 fn read(&self, key: &K) -> Result<Option<V>, Self::Error>;
109
110 fn read_with_proof(&self, key: &K) -> Result<Option<TrieMerkleProof<K, V>>, Self::Error>;
112
113 fn keys_with_prefix(&self, prefix: &[u8]) -> Result<Vec<K>, Self::Error>;
115}
116
117#[derive(Clone, Debug, thiserror::Error, Eq, PartialEq)]
119pub enum CommitError {
120 #[error("Root not found: {0:?}")]
122 RootNotFound(Digest),
123 #[error("Root not found while attempting to read: {0:?}")]
125 ReadRootNotFound(Digest),
126 #[error("Root not found while writing: {0:?}")]
128 WriteRootNotFound(Digest),
129 #[error("Key not found: {0}")]
131 KeyNotFound(Key),
132 #[error(transparent)]
134 TransformError(TransformError),
135 #[error("Trie not found in cache {0}")]
137 TrieNotFoundInCache(Digest),
138}
139
140pub trait ScratchProvider: CommitProvider {
142 fn get_scratch_global_state(&self) -> ScratchGlobalState;
144 fn write_scratch_to_db(
146 &self,
147 state_root_hash: Digest,
148 scratch_global_state: ScratchGlobalState,
149 ) -> Result<Digest, GlobalStateError>;
150 fn prune_keys(&self, state_root_hash: Digest, keys: &[Key]) -> TriePruneResult;
152}
153
154pub trait CommitProvider: StateProvider {
156 fn commit_effects(
159 &self,
160 state_hash: Digest,
161 effects: Effects,
162 ) -> Result<Digest, GlobalStateError>;
163
164 fn commit_values(
166 &self,
167 state_hash: Digest,
168 values_to_write: Vec<(Key, StoredValue)>,
169 keys_to_prune: BTreeSet<Key>,
170 ) -> Result<Digest, GlobalStateError>;
171
172 fn genesis(&self, request: GenesisRequest) -> GenesisResult {
174 let initial_root = self.empty_root();
175 let tc = match self.tracking_copy(initial_root) {
176 Ok(Some(tc)) => Rc::new(RefCell::new(tc)),
177 Ok(None) => return GenesisResult::Fatal("state uninitialized".to_string()),
178 Err(err) => {
179 return GenesisResult::Failure(GenesisError::TrackingCopy(
180 TrackingCopyError::Storage(err),
181 ));
182 }
183 };
184 let chainspec_hash = request.chainspec_hash();
185 let protocol_version = request.protocol_version();
186 let config = request.config();
187
188 let mut genesis_installer: GenesisInstaller<Self> =
189 GenesisInstaller::new(chainspec_hash, protocol_version, config.clone(), tc);
190
191 let chainspec_registry = request.chainspec_registry();
192 if let Err(gen_err) = genesis_installer.install(chainspec_registry.clone()) {
193 return GenesisResult::Failure(*gen_err);
194 }
195
196 let effects = genesis_installer.finalize();
197 match self.commit_effects(initial_root, effects.clone()) {
198 Ok(post_state_hash) => GenesisResult::Success {
199 post_state_hash,
200 effects,
201 },
202 Err(err) => {
203 GenesisResult::Failure(GenesisError::TrackingCopy(TrackingCopyError::Storage(err)))
204 }
205 }
206 }
207
208 fn protocol_upgrade(&self, request: ProtocolUpgradeRequest) -> ProtocolUpgradeResult {
210 let pre_state_hash = request.pre_state_hash();
211 let tc = match self.tracking_copy(pre_state_hash) {
212 Ok(Some(tc)) => tc,
213 Ok(None) => return ProtocolUpgradeResult::RootNotFound,
214 Err(err) => {
215 return ProtocolUpgradeResult::Failure(ProtocolUpgradeError::TrackingCopy(
216 TrackingCopyError::Storage(err),
217 ));
218 }
219 };
220
221 let protocol_upgrader: ProtocolUpgrader<Self> =
222 ProtocolUpgrader::new(request.config().clone(), pre_state_hash, tc);
223
224 let post_upgrade_tc = match protocol_upgrader.upgrade(pre_state_hash) {
225 Err(e) => return e.into(),
226 Ok(tc) => tc,
227 };
228
229 let (writes, prunes, effects) = post_upgrade_tc.destructure();
230
231 match self.commit_values(pre_state_hash, writes, prunes) {
233 Ok(post_state_hash) => ProtocolUpgradeResult::Success {
234 post_state_hash,
235 effects,
236 },
237 Err(err) => ProtocolUpgradeResult::Failure(ProtocolUpgradeError::TrackingCopy(
238 TrackingCopyError::Storage(err),
239 )),
240 }
241 }
242
243 fn prune(&self, request: PruneRequest) -> PruneResult {
245 let pre_state_hash = request.state_hash();
246 let tc = match self.tracking_copy(pre_state_hash) {
247 Ok(Some(tc)) => Rc::new(RefCell::new(tc)),
248 Ok(None) => return PruneResult::RootNotFound,
249 Err(err) => return PruneResult::Failure(TrackingCopyError::Storage(err)),
250 };
251
252 let keys_to_delete = request.keys_to_prune();
253 if keys_to_delete.is_empty() {
254 return PruneResult::Success {
256 post_state_hash: pre_state_hash,
257 effects: Effects::default(),
258 };
259 }
260
261 for key in keys_to_delete {
262 tc.borrow_mut().prune(*key)
263 }
264
265 let effects = tc.borrow().effects();
266
267 match self.commit_effects(pre_state_hash, effects.clone()) {
268 Ok(post_state_hash) => PruneResult::Success {
269 post_state_hash,
270 effects,
271 },
272 Err(tce) => PruneResult::Failure(tce.into()),
273 }
274 }
275
276 fn step(&self, request: StepRequest) -> StepResult {
278 let state_hash = request.state_hash();
279 let tc = match self.tracking_copy(state_hash) {
280 Ok(Some(tc)) => Rc::new(RefCell::new(tc)),
281 Ok(None) => return StepResult::RootNotFound,
282 Err(err) => {
283 return StepResult::Failure(StepError::TrackingCopy(TrackingCopyError::Storage(
284 err,
285 )));
286 }
287 };
288 let protocol_version = request.protocol_version();
289
290 let seed = {
291 let mut bytes = match request.era_end_timestamp_millis().into_bytes() {
293 Ok(bytes) => bytes,
294 Err(bre) => {
295 return StepResult::Failure(StepError::TrackingCopy(
296 TrackingCopyError::BytesRepr(bre),
297 ));
298 }
299 };
300 match &mut protocol_version.into_bytes() {
301 Ok(next) => bytes.append(next),
302 Err(bre) => {
303 return StepResult::Failure(StepError::TrackingCopy(
304 TrackingCopyError::BytesRepr(*bre),
305 ));
306 }
307 };
308 match &mut request.next_era_id().into_bytes() {
309 Ok(next) => bytes.append(next),
310 Err(bre) => {
311 return StepResult::Failure(StepError::TrackingCopy(
312 TrackingCopyError::BytesRepr(*bre),
313 ));
314 }
315 };
316
317 Id::Seed(bytes)
318 };
319
320 let config = request.config();
321 let phase = Phase::Session;
323 let address_generator = AddressGenerator::new(&seed.seed(), phase);
324 let mut runtime = match RuntimeNative::new_system_runtime(
325 config.clone(),
326 protocol_version,
327 seed,
328 Arc::new(RwLock::new(address_generator)),
329 Rc::clone(&tc),
330 phase,
331 ) {
332 Ok(rt) => rt,
333 Err(tce) => return StepResult::Failure(StepError::TrackingCopy(tce)),
334 };
335
336 let slashed_validators: Vec<PublicKey> = request.slashed_validators();
337 if !slashed_validators.is_empty() {
338 if let Err(err) = runtime.slash(slashed_validators) {
339 error!("{}", err);
340 return StepResult::Failure(StepError::SlashingError);
341 }
342 }
343
344 let era_end_timestamp_millis = request.era_end_timestamp_millis();
345 let evicted_validators = request
346 .evict_items()
347 .iter()
348 .map(|item| item.validator_id.clone())
349 .collect::<Vec<PublicKey>>();
350 let max_delegators_per_validator = config.max_delegators_per_validator();
351 let include_credits = config.include_credits();
352 let credit_cap = config.credit_cap();
353 let minimum_bid_amount = config.minimum_bid_amount();
354
355 if let Err(err) = runtime.run_auction(
356 era_end_timestamp_millis,
357 evicted_validators,
358 max_delegators_per_validator,
359 include_credits,
360 credit_cap,
361 minimum_bid_amount,
362 ) {
363 error!("{}", err);
364 return StepResult::Failure(StepError::Auction);
365 }
366
367 let effects = tc.borrow().effects();
368
369 match self.commit_effects(state_hash, effects.clone()) {
370 Ok(post_state_hash) => StepResult::Success {
371 post_state_hash,
372 effects,
373 },
374 Err(gse) => StepResult::Failure(gse.into()),
375 }
376 }
377
378 fn distribute_block_rewards(&self, request: BlockRewardsRequest) -> BlockRewardsResult {
380 let state_hash = request.state_hash();
381 let rewards = request.rewards();
382 if rewards.is_empty() {
383 info!("rewards are empty");
384 return BlockRewardsResult::Success {
386 post_state_hash: state_hash,
387 effects: Effects::new(),
388 };
389 }
390
391 let tc = match self.tracking_copy(state_hash) {
392 Ok(Some(tc)) => Rc::new(RefCell::new(tc)),
393 Ok(None) => return BlockRewardsResult::RootNotFound,
394 Err(err) => {
395 return BlockRewardsResult::Failure(BlockRewardsError::TrackingCopy(
396 TrackingCopyError::Storage(err),
397 ));
398 }
399 };
400
401 let config = request.config();
402 let protocol_version = request.protocol_version();
403 let seed = {
404 let mut bytes = match request.block_time().into_bytes() {
405 Ok(bytes) => bytes,
406 Err(bre) => {
407 return BlockRewardsResult::Failure(BlockRewardsError::TrackingCopy(
408 TrackingCopyError::BytesRepr(bre),
409 ));
410 }
411 };
412 match &mut protocol_version.into_bytes() {
413 Ok(next) => bytes.append(next),
414 Err(bre) => {
415 return BlockRewardsResult::Failure(BlockRewardsError::TrackingCopy(
416 TrackingCopyError::BytesRepr(*bre),
417 ));
418 }
419 };
420
421 Id::Seed(bytes)
422 };
423
424 let phase = Phase::Session;
426 let address_generator = AddressGenerator::new(&seed.seed(), phase);
427
428 let mut runtime = match RuntimeNative::new_system_runtime(
429 config.clone(),
430 protocol_version,
431 seed,
432 Arc::new(RwLock::new(address_generator)),
433 Rc::clone(&tc),
434 phase,
435 ) {
436 Ok(rt) => rt,
437 Err(tce) => {
438 return BlockRewardsResult::Failure(BlockRewardsError::TrackingCopy(tce));
439 }
440 };
441
442 if let Err(auction_error) = runtime.distribute(rewards.clone()) {
443 error!(
444 "distribute block rewards failed due to auction error {:?}",
445 auction_error
446 );
447 return BlockRewardsResult::Failure(BlockRewardsError::Auction(auction_error));
448 } else {
449 debug!("rewards distribution complete");
450 }
451
452 let effects = tc.borrow().effects();
453
454 match self.commit_effects(state_hash, effects.clone()) {
455 Ok(post_state_hash) => {
456 debug!("reward distribution committed");
457 BlockRewardsResult::Success {
458 post_state_hash,
459 effects,
460 }
461 }
462 Err(gse) => BlockRewardsResult::Failure(BlockRewardsError::TrackingCopy(
463 TrackingCopyError::Storage(gse),
464 )),
465 }
466 }
467
468 fn distribute_fees(&self, request: FeeRequest) -> FeeResult {
470 let state_hash = request.state_hash();
471 if !request.should_distribute_fees() {
472 return FeeResult::Success {
474 post_state_hash: state_hash,
475 effects: Effects::new(),
476 transfers: vec![],
477 };
478 }
479
480 let tc = match self.tracking_copy(state_hash) {
481 Ok(Some(tracking_copy)) => Rc::new(RefCell::new(tracking_copy)),
482 Ok(None) => return FeeResult::RootNotFound,
483 Err(gse) => {
484 return FeeResult::Failure(FeeError::TrackingCopy(TrackingCopyError::Storage(gse)));
485 }
486 };
487
488 let config = request.config();
489 let protocol_version = request.protocol_version();
490 let seed = {
491 let mut bytes = match request.block_time().into_bytes() {
492 Ok(bytes) => bytes,
493 Err(bre) => {
494 return FeeResult::Failure(FeeError::TrackingCopy(
495 TrackingCopyError::BytesRepr(bre),
496 ));
497 }
498 };
499 match &mut protocol_version.into_bytes() {
500 Ok(next) => bytes.append(next),
501 Err(bre) => {
502 return FeeResult::Failure(FeeError::TrackingCopy(
503 TrackingCopyError::BytesRepr(*bre),
504 ));
505 }
506 };
507
508 Id::Seed(bytes)
509 };
510
511 let phase = Phase::System;
513 let address_generator = AddressGenerator::new(&seed.seed(), phase);
514 let mut runtime = match RuntimeNative::new_system_runtime(
515 config.clone(),
516 protocol_version,
517 seed,
518 Arc::new(RwLock::new(address_generator)),
519 Rc::clone(&tc),
520 phase,
521 ) {
522 Ok(rt) => rt,
523 Err(tce) => {
524 return FeeResult::Failure(FeeError::TrackingCopy(tce));
525 }
526 };
527
528 let source = BalanceIdentifier::Accumulate;
529 let source_purse = match source.purse_uref(&mut tc.borrow_mut(), protocol_version) {
530 Ok(value) => value,
531 Err(tce) => return FeeResult::Failure(FeeError::TrackingCopy(tce)),
532 };
533 let result = runtime.distribute_accumulated_fees(source_purse, None);
535
536 match result {
537 Ok(_) => {
538 let effects = tc.borrow_mut().effects();
539 let transfers = runtime.into_transfers();
540 let post_state_hash = match self.commit_effects(state_hash, effects.clone()) {
541 Ok(post_state_hash) => post_state_hash,
542 Err(gse) => {
543 return FeeResult::Failure(FeeError::TrackingCopy(
544 TrackingCopyError::Storage(gse),
545 ));
546 }
547 };
548 FeeResult::Success {
549 effects,
550 transfers,
551 post_state_hash,
552 }
553 }
554 Err(hpe) => FeeResult::Failure(FeeError::TrackingCopy(
555 TrackingCopyError::SystemContract(system::Error::HandlePayment(hpe)),
556 )),
557 }
558 }
559
560 fn block_global(&self, request: BlockGlobalRequest) -> BlockGlobalResult {
562 let state_hash = request.state_hash();
563 let tc = match self.tracking_copy(state_hash) {
564 Ok(Some(tracking_copy)) => Rc::new(RefCell::new(tracking_copy)),
565 Ok(None) => return BlockGlobalResult::RootNotFound,
566 Err(gse) => return BlockGlobalResult::Failure(TrackingCopyError::Storage(gse)),
567 };
568
569 match request.block_global_kind() {
571 BlockGlobalKind::BlockTime(block_time) => {
572 let cl_value =
573 match CLValue::from_t(block_time.value()).map_err(TrackingCopyError::CLValue) {
574 Ok(cl_value) => cl_value,
575 Err(tce) => {
576 return BlockGlobalResult::Failure(tce);
577 }
578 };
579 tc.borrow_mut().write(
580 Key::BlockGlobal(BlockGlobalAddr::BlockTime),
581 StoredValue::CLValue(cl_value),
582 );
583 }
584 BlockGlobalKind::MessageCount(count) => {
585 let cl_value = match CLValue::from_t(count).map_err(TrackingCopyError::CLValue) {
586 Ok(cl_value) => cl_value,
587 Err(tce) => {
588 return BlockGlobalResult::Failure(tce);
589 }
590 };
591 tc.borrow_mut().write(
592 Key::BlockGlobal(BlockGlobalAddr::MessageCount),
593 StoredValue::CLValue(cl_value),
594 );
595 }
596 BlockGlobalKind::ProtocolVersion(protocol_version) => {
597 let cl_value = match CLValue::from_t(protocol_version.destructure())
598 .map_err(TrackingCopyError::CLValue)
599 {
600 Ok(cl_value) => cl_value,
601 Err(tce) => {
602 return BlockGlobalResult::Failure(tce);
603 }
604 };
605 tc.borrow_mut().write(
606 Key::BlockGlobal(BlockGlobalAddr::ProtocolVersion),
607 StoredValue::CLValue(cl_value),
608 );
609 }
610 BlockGlobalKind::AddressableEntity(addressable_entity) => {
611 let cl_value =
612 match CLValue::from_t(addressable_entity).map_err(TrackingCopyError::CLValue) {
613 Ok(cl_value) => cl_value,
614 Err(tce) => {
615 return BlockGlobalResult::Failure(tce);
616 }
617 };
618 tc.borrow_mut().write(
619 Key::BlockGlobal(BlockGlobalAddr::AddressableEntity),
620 StoredValue::CLValue(cl_value),
621 );
622 }
623 }
624
625 let effects = tc.borrow_mut().effects();
626
627 let post_state_hash = match self.commit_effects(state_hash, effects.clone()) {
628 Ok(post_state_hash) => post_state_hash,
629 Err(gse) => return BlockGlobalResult::Failure(TrackingCopyError::Storage(gse)),
630 };
631
632 BlockGlobalResult::Success {
633 post_state_hash,
634 effects: Box::new(effects),
635 }
636 }
637}
638
639pub trait StateProvider: Send + Sync + Sized {
641 type Reader: StateReader<Key, StoredValue, Error = GlobalStateError>;
643
644 fn flush(&self, request: FlushRequest) -> FlushResult;
646
647 fn empty_root(&self) -> Digest;
649
650 fn tracking_copy(
652 &self,
653 state_hash: Digest,
654 ) -> Result<Option<TrackingCopy<Self::Reader>>, GlobalStateError>;
655
656 fn checkout(&self, state_hash: Digest) -> Result<Option<Self::Reader>, GlobalStateError>;
658
659 fn query(&self, request: QueryRequest) -> QueryResult {
661 match self.tracking_copy(request.state_hash()) {
662 Ok(Some(tc)) => match tc.query(request.key(), request.path()) {
663 Ok(ret) => ret.into(),
664 Err(err) => QueryResult::Failure(err),
665 },
666 Ok(None) => QueryResult::RootNotFound,
667 Err(err) => QueryResult::Failure(TrackingCopyError::Storage(err)),
668 }
669 }
670
671 fn message_topics(&self, message_topics_request: MessageTopicsRequest) -> MessageTopicsResult {
673 let tc = match self.tracking_copy(message_topics_request.state_hash()) {
674 Ok(Some(tracking_copy)) => tracking_copy,
675 Ok(None) => return MessageTopicsResult::RootNotFound,
676 Err(err) => return MessageTopicsResult::Failure(err.into()),
677 };
678
679 match tc.get_message_topics(message_topics_request.entity_addr()) {
680 Ok(message_topics) => MessageTopicsResult::Success { message_topics },
681 Err(tce) => MessageTopicsResult::Failure(tce),
682 }
683 }
684
685 fn balance_purse(
687 &self,
688 request: BalanceIdentifierPurseRequest,
689 ) -> BalanceIdentifierPurseResult {
690 let mut tc = match self.tracking_copy(request.state_hash()) {
691 Ok(Some(tracking_copy)) => tracking_copy,
692 Ok(None) => return BalanceIdentifierPurseResult::RootNotFound,
693 Err(err) => return TrackingCopyError::Storage(err).into(),
694 };
695 let balance_identifier = request.identifier();
696 let protocol_version = request.protocol_version();
697 match balance_identifier.purse_uref(&mut tc, protocol_version) {
698 Ok(uref) => BalanceIdentifierPurseResult::Success {
699 purse_addr: uref.addr(),
700 },
701 Err(tce) => BalanceIdentifierPurseResult::Failure(tce),
702 }
703 }
704
705 fn balance(&self, request: BalanceRequest) -> BalanceResult {
707 let mut tc = match self.tracking_copy(request.state_hash()) {
708 Ok(Some(tracking_copy)) => tracking_copy,
709 Ok(None) => return BalanceResult::RootNotFound,
710 Err(err) => return TrackingCopyError::Storage(err).into(),
711 };
712 let protocol_version = request.protocol_version();
713 let balance_identifier = request.identifier();
714 let purse_key = match balance_identifier.purse_uref(&mut tc, protocol_version) {
715 Ok(value) => value.into(),
716 Err(tce) => return tce.into(),
717 };
718 let (purse_balance_key, purse_addr) = match tc.get_purse_balance_key(purse_key) {
719 Ok(key @ Key::Balance(addr)) => (key, addr),
720 Ok(key) => return TrackingCopyError::UnexpectedKeyVariant(key).into(),
721 Err(tce) => return tce.into(),
722 };
723
724 let (total_balance, proofs_result) = match request.proof_handling() {
725 ProofHandling::NoProofs => {
726 let total_balance = match tc.read(&purse_balance_key) {
727 Ok(Some(StoredValue::CLValue(cl_value))) => match cl_value.into_t::<U512>() {
728 Ok(val) => val,
729 Err(cve) => return TrackingCopyError::CLValue(cve).into(),
730 },
731 Ok(Some(_)) => return TrackingCopyError::UnexpectedStoredValueVariant.into(),
732 Ok(None) => return TrackingCopyError::KeyNotFound(purse_balance_key).into(),
733 Err(tce) => return tce.into(),
734 };
735 let balance_holds = match request.balance_handling() {
736 BalanceHandling::Total => BTreeMap::new(),
737 BalanceHandling::Available => {
738 match tc.get_balance_hold_config(BalanceHoldAddrTag::Gas) {
739 Ok(Some((block_time, _, interval))) => {
740 match tc.get_balance_holds(purse_addr, block_time, interval) {
741 Ok(holds) => holds,
742 Err(tce) => return tce.into(),
743 }
744 }
745 Ok(None) => BTreeMap::new(),
746 Err(tce) => return tce.into(),
747 }
748 }
749 };
750 (total_balance, ProofsResult::NotRequested { balance_holds })
751 }
752 ProofHandling::Proofs => {
753 let (total_balance, total_balance_proof) =
754 match tc.get_total_balance_with_proof(purse_balance_key) {
755 Ok((balance, proof)) => (balance, Box::new(proof)),
756 Err(tce) => return tce.into(),
757 };
758
759 let balance_holds = match request.balance_handling() {
760 BalanceHandling::Total => BTreeMap::new(),
761 BalanceHandling::Available => {
762 match tc.get_balance_holds_with_proof(purse_addr) {
763 Ok(holds) => holds,
764 Err(tce) => return tce.into(),
765 }
766 }
767 };
768
769 (
770 total_balance,
771 ProofsResult::Proofs {
772 total_balance_proof,
773 balance_holds,
774 },
775 )
776 }
777 };
778
779 let (block_time, gas_hold_handling) = match tc
780 .get_balance_hold_config(BalanceHoldAddrTag::Gas)
781 {
782 Ok(Some((block_time, handling, interval))) => (block_time, (handling, interval).into()),
783 Ok(None) => {
784 return BalanceResult::Success {
785 purse_addr,
786 total_balance,
787 available_balance: total_balance,
788 proofs_result,
789 };
790 }
791 Err(tce) => return tce.into(),
792 };
793
794 let processing_hold_handling =
795 match tc.get_balance_hold_config(BalanceHoldAddrTag::Processing) {
796 Ok(Some((_, handling, interval))) => (handling, interval).into(),
797 Ok(None) => {
798 return BalanceResult::Success {
799 purse_addr,
800 total_balance,
801 available_balance: total_balance,
802 proofs_result,
803 };
804 }
805 Err(tce) => return tce.into(),
806 };
807
808 let available_balance = match &proofs_result.available_balance(
809 block_time,
810 total_balance,
811 gas_hold_handling,
812 processing_hold_handling,
813 ) {
814 Ok(available_balance) => *available_balance,
815 Err(be) => return BalanceResult::Failure(TrackingCopyError::Balance(be.clone())),
816 };
817
818 BalanceResult::Success {
819 purse_addr,
820 total_balance,
821 available_balance,
822 proofs_result,
823 }
824 }
825
826 fn balance_hold(&self, request: BalanceHoldRequest) -> BalanceHoldResult {
828 let mut tc = match self.tracking_copy(request.state_hash()) {
829 Ok(Some(tracking_copy)) => tracking_copy,
830 Ok(None) => return BalanceHoldResult::RootNotFound,
831 Err(err) => {
832 return BalanceHoldResult::Failure(BalanceHoldError::TrackingCopy(
833 TrackingCopyError::Storage(err),
834 ));
835 }
836 };
837 let hold_mode = request.balance_hold_mode();
838 match hold_mode {
839 BalanceHoldMode::Hold {
840 identifier,
841 hold_amount,
842 insufficient_handling,
843 } => {
844 let block_time = match tc.get_block_time() {
845 Ok(Some(block_time)) => block_time,
846 Ok(None) => return BalanceHoldResult::BlockTimeNotFound,
847 Err(tce) => return tce.into(),
848 };
849 let tag = match request.balance_hold_kind() {
850 BalanceHoldKind::All => {
851 return BalanceHoldResult::Failure(
852 BalanceHoldError::UnexpectedWildcardVariant,
853 );
854 }
855 BalanceHoldKind::Tag(tag) => tag,
856 };
857 let balance_request = BalanceRequest::new(
858 request.state_hash(),
859 request.protocol_version(),
860 identifier,
861 BalanceHandling::Available,
862 ProofHandling::NoProofs,
863 );
864 let balance_result = self.balance(balance_request);
865 let (total_balance, remaining_balance, purse_addr) = match balance_result {
866 BalanceResult::RootNotFound => return BalanceHoldResult::RootNotFound,
867 BalanceResult::Failure(be) => return be.into(),
868 BalanceResult::Success {
869 total_balance,
870 available_balance,
871 purse_addr,
872 ..
873 } => (total_balance, available_balance, purse_addr),
874 };
875
876 let held_amount = {
877 if remaining_balance >= hold_amount {
878 hold_amount
880 } else if insufficient_handling == InsufficientBalanceHandling::Noop {
881 return BalanceHoldResult::Failure(BalanceHoldError::InsufficientBalance {
884 remaining_balance,
885 });
886 } else {
887 remaining_balance
897 }
898 };
899
900 let balance_hold_addr = match tag {
901 BalanceHoldAddrTag::Gas => BalanceHoldAddr::Gas {
902 purse_addr,
903 block_time,
904 },
905 BalanceHoldAddrTag::Processing => BalanceHoldAddr::Processing {
906 purse_addr,
907 block_time,
908 },
909 };
910
911 let hold_key = Key::BalanceHold(balance_hold_addr);
912 let hold_value = match tc.get(&hold_key) {
913 Ok(Some(StoredValue::CLValue(cl_value))) => {
914 match cl_value.clone().into_t::<U512>() {
917 Ok(prev_hold) => prev_hold.saturating_add(held_amount),
918 Err(cve) => {
919 return BalanceHoldResult::Failure(BalanceHoldError::TrackingCopy(
920 TrackingCopyError::CLValue(cve),
921 ));
922 }
923 }
924 }
925 Ok(Some(other_value_variant)) => {
926 return BalanceHoldResult::Failure(BalanceHoldError::UnexpectedHoldValue(
927 other_value_variant,
928 ))
929 }
930 Ok(None) => held_amount, Err(tce) => {
932 return BalanceHoldResult::Failure(BalanceHoldError::TrackingCopy(tce));
933 }
934 };
935
936 let hold_cl_value = match CLValue::from_t(hold_value) {
937 Ok(cl_value) => cl_value,
938 Err(cve) => {
939 return BalanceHoldResult::Failure(BalanceHoldError::TrackingCopy(
940 TrackingCopyError::CLValue(cve),
941 ));
942 }
943 };
944 tc.write(hold_key, StoredValue::CLValue(hold_cl_value));
945 let holds = vec![balance_hold_addr];
946
947 let available_balance = remaining_balance.saturating_sub(held_amount);
948 let effects = tc.effects();
949 BalanceHoldResult::success(
950 Some(holds),
951 total_balance,
952 available_balance,
953 hold_amount,
954 held_amount,
955 effects,
956 )
957 }
958 BalanceHoldMode::Clear { identifier } => {
959 let purse_addr = match identifier.purse_uref(&mut tc, request.protocol_version()) {
960 Ok(source_purse) => source_purse.addr(),
961 Err(tce) => {
962 return BalanceHoldResult::Failure(BalanceHoldError::TrackingCopy(tce));
963 }
964 };
965
966 {
967 let hold_kind = request.balance_hold_kind();
969 let mut filter = vec![];
970 let tag = BalanceHoldAddrTag::Processing;
971 if hold_kind.matches(tag) {
972 let (block_time, interval) = match tc.get_balance_hold_config(tag) {
973 Ok(Some((block_time, _, interval))) => (block_time, interval),
974 Ok(None) => {
975 return BalanceHoldResult::BlockTimeNotFound;
976 }
977 Err(tce) => {
978 return BalanceHoldResult::Failure(BalanceHoldError::TrackingCopy(
979 tce,
980 ));
981 }
982 };
983 filter.push((tag, HoldsEpoch::from_millis(block_time.value(), interval)));
984 }
985 let tag = BalanceHoldAddrTag::Gas;
986 if hold_kind.matches(tag) {
987 let (block_time, interval) = match tc.get_balance_hold_config(tag) {
988 Ok(Some((block_time, _, interval))) => (block_time, interval),
989 Ok(None) => {
990 return BalanceHoldResult::BlockTimeNotFound;
991 }
992 Err(tce) => {
993 return BalanceHoldResult::Failure(BalanceHoldError::TrackingCopy(
994 tce,
995 ));
996 }
997 };
998 filter.push((tag, HoldsEpoch::from_millis(block_time.value(), interval)));
999 }
1000 if let Err(tce) = tc.clear_expired_balance_holds(purse_addr, filter) {
1001 return BalanceHoldResult::Failure(BalanceHoldError::TrackingCopy(tce));
1002 }
1003 }
1004
1005 let balance_result = self.balance(BalanceRequest::new(
1007 request.state_hash(),
1008 request.protocol_version(),
1009 identifier,
1010 BalanceHandling::Available,
1011 ProofHandling::NoProofs,
1012 ));
1013 let (total_balance, available_balance) = match balance_result {
1014 BalanceResult::RootNotFound => return BalanceHoldResult::RootNotFound,
1015 BalanceResult::Failure(be) => return be.into(),
1016 BalanceResult::Success {
1017 total_balance,
1018 available_balance,
1019 ..
1020 } => (total_balance, available_balance),
1021 };
1022 let new_hold_addr = None;
1027 let hold = U512::zero();
1028 let held = U512::zero();
1029 let effects = tc.effects();
1030 BalanceHoldResult::success(
1031 new_hold_addr,
1032 total_balance,
1033 available_balance,
1034 hold,
1035 held,
1036 effects,
1037 )
1038 }
1039 }
1040 }
1041
1042 fn era_validators(&self, request: EraValidatorsRequest) -> EraValidatorsResult {
1044 match self.seigniorage_recipients(SeigniorageRecipientsRequest::new(request.state_hash())) {
1045 SeigniorageRecipientsResult::RootNotFound => EraValidatorsResult::RootNotFound,
1046 SeigniorageRecipientsResult::Failure(err) => EraValidatorsResult::Failure(err),
1047 SeigniorageRecipientsResult::ValueNotFound(msg) => {
1048 EraValidatorsResult::ValueNotFound(msg)
1049 }
1050 SeigniorageRecipientsResult::AuctionNotFound => EraValidatorsResult::AuctionNotFound,
1051 SeigniorageRecipientsResult::Success {
1052 seigniorage_recipients,
1053 } => {
1054 let era_validators = match seigniorage_recipients {
1055 SeigniorageRecipientsSnapshot::V1(snapshot) => {
1056 auction::detail::era_validators_from_legacy_snapshot(snapshot)
1057 }
1058 SeigniorageRecipientsSnapshot::V2(snapshot) => {
1059 auction::detail::era_validators_from_snapshot(snapshot)
1060 }
1061 };
1062 EraValidatorsResult::Success { era_validators }
1063 }
1064 }
1065 }
1066
1067 fn seigniorage_recipients(
1069 &self,
1070 request: SeigniorageRecipientsRequest,
1071 ) -> SeigniorageRecipientsResult {
1072 let state_hash = request.state_hash();
1073 let tc = match self.tracking_copy(state_hash) {
1074 Ok(Some(tc)) => tc,
1075 Ok(None) => return SeigniorageRecipientsResult::RootNotFound,
1076 Err(err) => {
1077 return SeigniorageRecipientsResult::Failure(TrackingCopyError::Storage(err))
1078 }
1079 };
1080 let scr = match tc.get_system_entity_registry() {
1081 Ok(scr) => scr,
1082 Err(err) => return SeigniorageRecipientsResult::Failure(err),
1083 };
1084 let enable_addressable_entity = tc.enable_addressable_entity();
1085 match get_snapshot_data(self, &scr, state_hash, enable_addressable_entity) {
1086 not_found @ SeigniorageRecipientsResult::ValueNotFound(_) => {
1087 if enable_addressable_entity {
1088 match get_snapshot_data(self, &scr, state_hash, false) {
1094 SeigniorageRecipientsResult::ValueNotFound(_) => not_found,
1095 other => other,
1096 }
1097 } else {
1098 not_found
1099 }
1100 }
1101 other => other,
1102 }
1103 }
1104
1105 fn bids(&self, request: BidsRequest) -> BidsResult {
1107 let state_hash = request.state_hash();
1108 let mut tc = match self.tracking_copy(state_hash) {
1109 Ok(Some(tc)) => tc,
1110 Ok(None) => return BidsResult::RootNotFound,
1111 Err(err) => return BidsResult::Failure(TrackingCopyError::Storage(err)),
1112 };
1113
1114 let bid_keys = match tc.get_keys(&KeyTag::BidAddr) {
1115 Ok(ret) => ret,
1116 Err(err) => return BidsResult::Failure(err),
1117 };
1118
1119 let mut bids = vec![];
1120 for key in bid_keys.iter() {
1121 match tc.get(key) {
1122 Ok(ret) => match ret {
1123 Some(StoredValue::BidKind(bid_kind)) => {
1124 if !bids.contains(&bid_kind) {
1125 bids.push(bid_kind);
1126 }
1127 }
1128 Some(_) => {
1129 return BidsResult::Failure(
1130 TrackingCopyError::UnexpectedStoredValueVariant,
1131 );
1132 }
1133 None => return BidsResult::Failure(TrackingCopyError::MissingBid(*key)),
1134 },
1135 Err(error) => return BidsResult::Failure(error),
1136 }
1137 }
1138 BidsResult::Success { bids }
1139 }
1140
1141 fn bidding(
1143 &self,
1144 BiddingRequest {
1145 config,
1146 state_hash,
1147 protocol_version,
1148 auction_method,
1149 transaction_hash,
1150 initiator,
1151 authorization_keys,
1152 }: BiddingRequest,
1153 ) -> BiddingResult {
1154 let tc = match self.tracking_copy(state_hash) {
1155 Ok(Some(tc)) => Rc::new(RefCell::new(tc)),
1156 Ok(None) => return BiddingResult::RootNotFound,
1157 Err(err) => return BiddingResult::Failure(TrackingCopyError::Storage(err)),
1158 };
1159
1160 let source_account_hash = initiator.account_hash();
1161 let (entity_addr, mut footprint, mut entity_access_rights) = match tc
1162 .borrow_mut()
1163 .authorized_runtime_footprint_with_access_rights(
1164 protocol_version,
1165 source_account_hash,
1166 &authorization_keys,
1167 &BTreeSet::default(),
1168 ) {
1169 Ok(ret) => ret,
1170 Err(tce) => {
1171 return BiddingResult::Failure(tce);
1172 }
1173 };
1174 let entity_key = Key::AddressableEntity(entity_addr);
1175
1176 match tc
1178 .borrow_mut()
1179 .system_contract_named_key(AUCTION, ERA_END_TIMESTAMP_MILLIS_KEY)
1180 {
1181 Ok(Some(k)) => {
1182 match k.as_uref() {
1183 Some(uref) => entity_access_rights.extend(&[*uref]),
1184 None => {
1185 return BiddingResult::Failure(TrackingCopyError::UnexpectedKeyVariant(k));
1186 }
1187 }
1188 footprint.insert_into_named_keys(ERA_END_TIMESTAMP_MILLIS_KEY.into(), k);
1189 }
1190 Ok(None) => {
1191 return BiddingResult::Failure(TrackingCopyError::NamedKeyNotFound(
1192 ERA_END_TIMESTAMP_MILLIS_KEY.into(),
1193 ));
1194 }
1195 Err(tce) => {
1196 return BiddingResult::Failure(tce);
1197 }
1198 };
1199 match tc
1201 .borrow_mut()
1202 .system_contract_named_key(AUCTION, ERA_ID_KEY)
1203 {
1204 Ok(Some(k)) => {
1205 match k.as_uref() {
1206 Some(uref) => entity_access_rights.extend(&[*uref]),
1207 None => {
1208 return BiddingResult::Failure(TrackingCopyError::UnexpectedKeyVariant(k));
1209 }
1210 }
1211 footprint.insert_into_named_keys(ERA_ID_KEY.into(), k);
1212 }
1213 Ok(None) => {
1214 return BiddingResult::Failure(TrackingCopyError::NamedKeyNotFound(
1215 ERA_ID_KEY.into(),
1216 ));
1217 }
1218 Err(tce) => {
1219 return BiddingResult::Failure(tce);
1220 }
1221 };
1222
1223 let phase = Phase::Session;
1224 let id = Id::Transaction(transaction_hash);
1225 let address_generator = AddressGenerator::new(&id.seed(), phase);
1226 let max_delegators_per_validator = config.max_delegators_per_validator();
1227 let minimum_bid_amount = config.minimum_bid_amount();
1228 let mut runtime = RuntimeNative::new(
1229 config,
1230 protocol_version,
1231 id,
1232 Arc::new(RwLock::new(address_generator)),
1233 Rc::clone(&tc),
1234 source_account_hash,
1235 entity_key,
1236 footprint,
1237 entity_access_rights,
1238 U512::MAX,
1239 phase,
1240 );
1241
1242 let result = match auction_method {
1243 AuctionMethod::ActivateBid { validator } => runtime
1244 .activate_bid(validator, minimum_bid_amount)
1245 .map(|_| AuctionMethodRet::Unit)
1246 .map_err(|auc_err| {
1247 TrackingCopyError::SystemContract(system::Error::Auction(auc_err))
1248 }),
1249 AuctionMethod::AddBid {
1250 public_key,
1251 delegation_rate,
1252 amount,
1253 minimum_delegation_amount,
1254 maximum_delegation_amount,
1255 minimum_bid_amount,
1256 reserved_slots,
1257 } => runtime
1258 .add_bid(
1259 public_key,
1260 delegation_rate,
1261 amount,
1262 minimum_delegation_amount,
1263 maximum_delegation_amount,
1264 minimum_bid_amount,
1265 max_delegators_per_validator,
1266 reserved_slots,
1267 )
1268 .map(AuctionMethodRet::UpdatedAmount)
1269 .map_err(TrackingCopyError::Api),
1270 AuctionMethod::WithdrawBid {
1271 public_key,
1272 amount,
1273 minimum_bid_amount,
1274 } => runtime
1275 .withdraw_bid(public_key, amount, minimum_bid_amount)
1276 .map(AuctionMethodRet::UpdatedAmount)
1277 .map_err(|auc_err| {
1278 TrackingCopyError::SystemContract(system::Error::Auction(auc_err))
1279 }),
1280 AuctionMethod::Delegate {
1281 delegator,
1282 validator,
1283 amount,
1284 max_delegators_per_validator,
1285 } => runtime
1286 .delegate(delegator, validator, amount, max_delegators_per_validator)
1287 .map(AuctionMethodRet::UpdatedAmount)
1288 .map_err(TrackingCopyError::Api),
1289 AuctionMethod::Undelegate {
1290 delegator,
1291 validator,
1292 amount,
1293 } => runtime
1294 .undelegate(delegator, validator, amount)
1295 .map(AuctionMethodRet::UpdatedAmount)
1296 .map_err(|auc_err| {
1297 TrackingCopyError::SystemContract(system::Error::Auction(auc_err))
1298 }),
1299 AuctionMethod::Redelegate {
1300 delegator,
1301 validator,
1302 amount,
1303 new_validator,
1304 } => runtime
1305 .redelegate(delegator, validator, amount, new_validator)
1306 .map(AuctionMethodRet::UpdatedAmount)
1307 .map_err(|auc_err| {
1308 TrackingCopyError::SystemContract(system::Error::Auction(auc_err))
1309 }),
1310 AuctionMethod::ChangeBidPublicKey {
1311 public_key,
1312 new_public_key,
1313 } => runtime
1314 .change_bid_public_key(public_key, new_public_key)
1315 .map(|_| AuctionMethodRet::Unit)
1316 .map_err(|auc_err| {
1317 TrackingCopyError::SystemContract(system::Error::Auction(auc_err))
1318 }),
1319 AuctionMethod::AddReservations { reservations } => runtime
1320 .add_reservations(reservations)
1321 .map(|_| AuctionMethodRet::Unit)
1322 .map_err(|auc_err| {
1323 TrackingCopyError::SystemContract(system::Error::Auction(auc_err))
1324 }),
1325 AuctionMethod::CancelReservations {
1326 validator,
1327 delegators,
1328 max_delegators_per_validator,
1329 } => runtime
1330 .cancel_reservations(validator, delegators, max_delegators_per_validator)
1331 .map(|_| AuctionMethodRet::Unit)
1332 .map_err(|auc_err| {
1333 TrackingCopyError::SystemContract(system::Error::Auction(auc_err))
1334 }),
1335 };
1336
1337 let transfers = runtime.into_transfers();
1338 let effects = tc.borrow_mut().effects();
1339
1340 match result {
1341 Ok(ret) => BiddingResult::Success {
1342 ret,
1343 effects,
1344 transfers,
1345 },
1346 Err(tce) => BiddingResult::Failure(tce),
1347 }
1348 }
1349
1350 fn handle_refund(
1352 &self,
1353 HandleRefundRequest {
1354 config,
1355 state_hash,
1356 protocol_version,
1357 transaction_hash,
1358 refund_mode,
1359 }: HandleRefundRequest,
1360 ) -> HandleRefundResult {
1361 let tc = match self.tracking_copy(state_hash) {
1362 Ok(Some(tc)) => Rc::new(RefCell::new(tc)),
1363 Ok(None) => return HandleRefundResult::RootNotFound,
1364 Err(err) => return HandleRefundResult::Failure(TrackingCopyError::Storage(err)),
1365 };
1366
1367 let id = Id::Transaction(transaction_hash);
1368 let phase = refund_mode.phase();
1369 let address_generator = Arc::new(RwLock::new(AddressGenerator::new(&id.seed(), phase)));
1370 let mut runtime = match phase {
1371 Phase::FinalizePayment => {
1372 match RuntimeNative::new_system_runtime(
1374 config,
1375 protocol_version,
1376 id,
1377 address_generator,
1378 Rc::clone(&tc),
1379 phase,
1380 ) {
1381 Ok(rt) => rt,
1382 Err(tce) => {
1383 return HandleRefundResult::Failure(tce);
1384 }
1385 }
1386 }
1387 Phase::Payment => {
1388 match RuntimeNative::new_system_contract_runtime(
1390 config,
1391 protocol_version,
1392 id,
1393 address_generator,
1394 Rc::clone(&tc),
1395 phase,
1396 HANDLE_PAYMENT,
1397 ) {
1398 Ok(rt) => rt,
1399 Err(tce) => {
1400 return HandleRefundResult::Failure(tce);
1401 }
1402 }
1403 }
1404 Phase::System | Phase::Session => return HandleRefundResult::InvalidPhase,
1405 };
1406
1407 let result = match refund_mode {
1408 HandleRefundMode::CalculateAmount {
1409 limit,
1410 cost,
1411 gas_price,
1412 consumed,
1413 ratio,
1414 source,
1415 } => {
1416 let source_purse = match source.purse_uref(&mut tc.borrow_mut(), protocol_version) {
1417 Ok(value) => value,
1418 Err(tce) => return HandleRefundResult::Failure(tce),
1419 };
1420 let (numer, denom) = ratio.into();
1421 let ratio = Ratio::new_raw(U512::from(numer), U512::from(denom));
1422 let refund_amount = match runtime.calculate_overpayment_and_fee(
1423 limit,
1424 gas_price,
1425 cost,
1426 consumed,
1427 source_purse,
1428 ratio,
1429 ) {
1430 Ok((refund, _)) => Some(refund),
1431 Err(hpe) => {
1432 return HandleRefundResult::Failure(TrackingCopyError::SystemContract(
1433 system::Error::HandlePayment(hpe),
1434 ));
1435 }
1436 };
1437 Ok(refund_amount)
1438 }
1439 HandleRefundMode::Refund {
1440 initiator_addr,
1441 limit,
1442 cost,
1443 gas_price,
1444 consumed,
1445 ratio,
1446 source,
1447 target,
1448 } => {
1449 let source_purse = match source.purse_uref(&mut tc.borrow_mut(), protocol_version) {
1450 Ok(value) => value,
1451 Err(tce) => return HandleRefundResult::Failure(tce),
1452 };
1453 let (numer, denom) = ratio.into();
1454 let ratio = Ratio::new_raw(U512::from(numer), U512::from(denom));
1455 let refund_amount = match runtime.calculate_overpayment_and_fee(
1456 limit,
1457 gas_price,
1458 cost,
1459 consumed,
1460 source_purse,
1461 ratio,
1462 ) {
1463 Ok((refund, _)) => refund,
1464 Err(hpe) => {
1465 return HandleRefundResult::Failure(TrackingCopyError::SystemContract(
1466 system::Error::HandlePayment(hpe),
1467 ));
1468 }
1469 };
1470 let target_purse = match target.purse_uref(&mut tc.borrow_mut(), protocol_version) {
1471 Ok(value) => value,
1472 Err(tce) => return HandleRefundResult::Failure(tce),
1473 };
1474 match runtime
1476 .transfer(
1477 Some(initiator_addr.account_hash()),
1478 source_purse,
1479 target_purse,
1480 refund_amount,
1481 None,
1482 )
1483 .map_err(|mint_err| {
1484 TrackingCopyError::SystemContract(system::Error::Mint(mint_err))
1485 }) {
1486 Ok(_) => Ok(Some(refund_amount)),
1487 Err(err) => Err(err),
1488 }
1489 }
1490 HandleRefundMode::RefundNoFeeCustomPayment {
1491 initiator_addr,
1492 limit,
1493 cost,
1494 gas_price,
1495 } => {
1496 let source = BalanceIdentifier::Payment;
1497 let source_purse = match source.purse_uref(&mut tc.borrow_mut(), protocol_version) {
1498 Ok(value) => value,
1499 Err(tce) => return HandleRefundResult::Failure(tce),
1500 };
1501 let consumed = U512::zero();
1502 let ratio = Ratio::new_raw(U512::one(), U512::one());
1503 let refund_amount = match runtime.calculate_overpayment_and_fee(
1504 limit,
1505 gas_price,
1506 cost,
1507 consumed,
1508 source_purse,
1509 ratio,
1510 ) {
1511 Ok((refund, _)) => refund,
1512 Err(hpe) => {
1513 return HandleRefundResult::Failure(TrackingCopyError::SystemContract(
1514 system::Error::HandlePayment(hpe),
1515 ));
1516 }
1517 };
1518 let target = BalanceIdentifier::Refund;
1519 let target_purse = match target.purse_uref(&mut tc.borrow_mut(), protocol_version) {
1520 Ok(value) => value,
1521 Err(tce) => return HandleRefundResult::Failure(tce),
1522 };
1523 match runtime
1524 .transfer(
1525 Some(initiator_addr.account_hash()),
1526 source_purse,
1527 target_purse,
1528 refund_amount,
1529 None,
1530 )
1531 .map_err(|mint_err| {
1532 TrackingCopyError::SystemContract(system::Error::Mint(mint_err))
1533 }) {
1534 Ok(_) => Ok(Some(U512::zero())), Err(err) => Err(err),
1536 }
1537 }
1538 HandleRefundMode::Burn {
1539 limit,
1540 gas_price,
1541 cost,
1542 consumed,
1543 source,
1544 ratio,
1545 } => {
1546 let source_purse = match source.purse_uref(&mut tc.borrow_mut(), protocol_version) {
1547 Ok(value) => value,
1548 Err(tce) => return HandleRefundResult::Failure(tce),
1549 };
1550 let (numer, denom) = ratio.into();
1551 let ratio = Ratio::new_raw(U512::from(numer), U512::from(denom));
1552 let burn_amount = match runtime.calculate_overpayment_and_fee(
1553 limit,
1554 gas_price,
1555 cost,
1556 consumed,
1557 source_purse,
1558 ratio,
1559 ) {
1560 Ok((amount, _)) => Some(amount),
1561 Err(hpe) => {
1562 return HandleRefundResult::Failure(TrackingCopyError::SystemContract(
1563 system::Error::HandlePayment(hpe),
1564 ));
1565 }
1566 };
1567 match runtime.payment_burn(source_purse, burn_amount) {
1568 Ok(_) => Ok(burn_amount),
1569 Err(hpe) => Err(TrackingCopyError::SystemContract(
1570 system::Error::HandlePayment(hpe),
1571 )),
1572 }
1573 }
1574 HandleRefundMode::SetRefundPurse { target } => {
1575 let target_purse = match target.purse_uref(&mut tc.borrow_mut(), protocol_version) {
1576 Ok(value) => value,
1577 Err(tce) => return HandleRefundResult::Failure(tce),
1578 };
1579 match runtime.set_refund_purse(target_purse) {
1580 Ok(_) => Ok(None),
1581 Err(hpe) => Err(TrackingCopyError::SystemContract(
1582 system::Error::HandlePayment(hpe),
1583 )),
1584 }
1585 }
1586 HandleRefundMode::ClearRefundPurse => match runtime.clear_refund_purse() {
1587 Ok(_) => Ok(None),
1588 Err(hpe) => Err(TrackingCopyError::SystemContract(
1589 system::Error::HandlePayment(hpe),
1590 )),
1591 },
1592 };
1593
1594 let effects = tc.borrow_mut().effects();
1595 let transfers = runtime.into_transfers();
1596
1597 match result {
1598 Ok(amount) => HandleRefundResult::Success {
1599 transfers,
1600 effects,
1601 amount,
1602 },
1603 Err(tce) => HandleRefundResult::Failure(tce),
1604 }
1605 }
1606
1607 fn handle_fee(
1609 &self,
1610 HandleFeeRequest {
1611 config,
1612 state_hash,
1613 protocol_version,
1614 transaction_hash,
1615 handle_fee_mode,
1616 }: HandleFeeRequest,
1617 ) -> HandleFeeResult {
1618 let tc = match self.tracking_copy(state_hash) {
1619 Ok(Some(tc)) => Rc::new(RefCell::new(tc)),
1620 Ok(None) => return HandleFeeResult::RootNotFound,
1621 Err(err) => return HandleFeeResult::Failure(TrackingCopyError::Storage(err)),
1622 };
1623
1624 let id = Id::Transaction(transaction_hash);
1627 let phase = Phase::FinalizePayment;
1628 let address_generator = AddressGenerator::new(&id.seed(), phase);
1629
1630 let mut runtime = match RuntimeNative::new_system_runtime(
1631 config,
1632 protocol_version,
1633 id,
1634 Arc::new(RwLock::new(address_generator)),
1635 Rc::clone(&tc),
1636 phase,
1637 ) {
1638 Ok(rt) => rt,
1639 Err(tce) => {
1640 return HandleFeeResult::Failure(tce);
1641 }
1642 };
1643
1644 let result = match handle_fee_mode {
1645 HandleFeeMode::Credit {
1646 validator,
1647 amount,
1648 era_id,
1649 } => runtime
1650 .write_validator_credit(*validator, era_id, amount)
1651 .map(|_| ())
1652 .map_err(|auction_error| {
1653 TrackingCopyError::SystemContract(system::Error::Auction(auction_error))
1654 }),
1655 HandleFeeMode::Pay {
1656 initiator_addr,
1657 amount,
1658 source,
1659 target,
1660 } => {
1661 let source_purse = match source.purse_uref(&mut tc.borrow_mut(), protocol_version) {
1662 Ok(value) => value,
1663 Err(tce) => return HandleFeeResult::Failure(tce),
1664 };
1665 let target_purse = match target.purse_uref(&mut tc.borrow_mut(), protocol_version) {
1666 Ok(value) => value,
1667 Err(tce) => return HandleFeeResult::Failure(tce),
1668 };
1669 runtime
1670 .transfer(
1671 Some(initiator_addr.account_hash()),
1672 source_purse,
1673 target_purse,
1674 amount,
1675 None,
1676 )
1677 .map_err(|mint_err| {
1678 TrackingCopyError::SystemContract(system::Error::Mint(mint_err))
1679 })
1680 }
1681 HandleFeeMode::Burn { source, amount } => {
1682 let source_purse = match source.purse_uref(&mut tc.borrow_mut(), protocol_version) {
1683 Ok(value) => value,
1684 Err(tce) => return HandleFeeResult::Failure(tce),
1685 };
1686 runtime
1687 .payment_burn(source_purse, amount)
1688 .map_err(|handle_payment_error| {
1689 TrackingCopyError::SystemContract(system::Error::HandlePayment(
1690 handle_payment_error,
1691 ))
1692 })
1693 }
1694 };
1695
1696 let effects = tc.borrow_mut().effects();
1697 let transfers = runtime.into_transfers();
1698
1699 match result {
1700 Ok(_) => HandleFeeResult::Success { transfers, effects },
1701 Err(tce) => HandleFeeResult::Failure(tce),
1702 }
1703 }
1704
1705 fn execution_result_checksum(
1707 &self,
1708 request: ExecutionResultsChecksumRequest,
1709 ) -> ExecutionResultsChecksumResult {
1710 let state_hash = request.state_hash();
1711 let mut tc = match self.tracking_copy(state_hash) {
1712 Ok(Some(tc)) => tc,
1713 Ok(None) => return ExecutionResultsChecksumResult::RootNotFound,
1714 Err(err) => {
1715 return ExecutionResultsChecksumResult::Failure(TrackingCopyError::Storage(err));
1716 }
1717 };
1718 match tc.get_checksum_registry() {
1719 Ok(Some(registry)) => match registry.get(EXECUTION_RESULTS_CHECKSUM_NAME) {
1720 Some(checksum) => ExecutionResultsChecksumResult::Success {
1721 checksum: *checksum,
1722 },
1723 None => ExecutionResultsChecksumResult::ChecksumNotFound,
1724 },
1725 Ok(None) => ExecutionResultsChecksumResult::RegistryNotFound,
1726 Err(err) => ExecutionResultsChecksumResult::Failure(err),
1727 }
1728 }
1729
1730 fn addressable_entity(&self, request: AddressableEntityRequest) -> AddressableEntityResult {
1732 let key = request.key();
1733 let query_key = match key {
1734 Key::Account(_) => {
1735 let query_request = QueryRequest::new(request.state_hash(), key, vec![]);
1736 match self.query(query_request) {
1737 QueryResult::RootNotFound => return AddressableEntityResult::RootNotFound,
1738 QueryResult::ValueNotFound(msg) => {
1739 return AddressableEntityResult::ValueNotFound(msg);
1740 }
1741 QueryResult::Failure(err) => return AddressableEntityResult::Failure(err),
1742 QueryResult::Success { value, .. } => {
1743 if let StoredValue::Account(account) = *value {
1744 let entity = AddressableEntity::from(account);
1746 return AddressableEntityResult::Success { entity };
1747 }
1748 if let StoredValue::CLValue(cl_value) = &*value {
1749 match cl_value.clone().into_t::<Key>() {
1751 Ok(entity_key @ Key::AddressableEntity(_)) => entity_key,
1752 Ok(invalid_key) => {
1753 warn!(
1754 %key,
1755 %invalid_key,
1756 type_name = %value.type_name(),
1757 "expected a Key::AddressableEntity to be stored under account hash"
1758 );
1759 return AddressableEntityResult::Failure(
1760 TrackingCopyError::UnexpectedStoredValueVariant,
1761 );
1762 }
1763 Err(error) => {
1764 error!(%key, %error, "expected a CLValue::Key to be stored under account hash");
1765 return AddressableEntityResult::Failure(
1766 TrackingCopyError::CLValue(error),
1767 );
1768 }
1769 }
1770 } else {
1771 warn!(
1772 %key,
1773 type_name = %value.type_name(),
1774 "expected a CLValue::Key or Account to be stored under account hash"
1775 );
1776 return AddressableEntityResult::Failure(
1777 TrackingCopyError::UnexpectedStoredValueVariant,
1778 );
1779 }
1780 }
1781 }
1782 }
1783 Key::Hash(contract_hash) => {
1784 let query_request = QueryRequest::new(request.state_hash(), key, vec![]);
1785 match self.query(query_request) {
1786 QueryResult::RootNotFound => return AddressableEntityResult::RootNotFound,
1787 QueryResult::ValueNotFound(msg) => {
1788 return AddressableEntityResult::ValueNotFound(msg);
1789 }
1790 QueryResult::Failure(err) => return AddressableEntityResult::Failure(err),
1791 QueryResult::Success { value, .. } => {
1792 if let StoredValue::Contract(contract) = *value {
1793 let entity = AddressableEntity::from(contract);
1795 return AddressableEntityResult::Success { entity };
1796 }
1797 Key::AddressableEntity(EntityAddr::SmartContract(contract_hash))
1798 }
1799 }
1800 }
1801 Key::AddressableEntity(_) => key,
1802 _ => {
1803 return AddressableEntityResult::Failure(TrackingCopyError::UnexpectedKeyVariant(
1804 key,
1805 ));
1806 }
1807 };
1808
1809 let query_request = QueryRequest::new(request.state_hash(), query_key, vec![]);
1810 match self.query(query_request) {
1811 QueryResult::RootNotFound => AddressableEntityResult::RootNotFound,
1812 QueryResult::ValueNotFound(msg) => AddressableEntityResult::ValueNotFound(msg),
1813 QueryResult::Success { value, .. } => {
1814 let entity = match value.as_addressable_entity() {
1815 Some(entity) => entity.clone(),
1816 None => {
1817 return AddressableEntityResult::Failure(
1818 TrackingCopyError::UnexpectedStoredValueVariant,
1819 );
1820 }
1821 };
1822 AddressableEntityResult::Success { entity }
1823 }
1824 QueryResult::Failure(err) => AddressableEntityResult::Failure(err),
1825 }
1826 }
1827
1828 fn system_entity_registry(
1830 &self,
1831 request: SystemEntityRegistryRequest,
1832 ) -> SystemEntityRegistryResult {
1833 let state_hash = request.state_hash();
1834 let tc = match self.tracking_copy(state_hash) {
1835 Ok(Some(tc)) => tc,
1836 Ok(None) => return SystemEntityRegistryResult::RootNotFound,
1837 Err(err) => {
1838 return SystemEntityRegistryResult::Failure(TrackingCopyError::Storage(err));
1839 }
1840 };
1841
1842 let reg = match tc.get_system_entity_registry() {
1843 Ok(reg) => reg,
1844 Err(tce) => {
1845 return SystemEntityRegistryResult::Failure(tce);
1846 }
1847 };
1848
1849 let selector = request.selector();
1850 match selector {
1851 SystemEntityRegistrySelector::All => SystemEntityRegistryResult::Success {
1852 selected: selector.clone(),
1853 payload: SystemEntityRegistryPayload::All(reg),
1854 },
1855 SystemEntityRegistrySelector::ByName(name) => match reg.get(name).copied() {
1856 Some(entity_hash) => {
1857 let key = if !request.enable_addressable_entity() {
1858 Key::Hash(entity_hash)
1859 } else {
1860 Key::AddressableEntity(EntityAddr::System(entity_hash))
1861 };
1862 SystemEntityRegistryResult::Success {
1863 selected: selector.clone(),
1864 payload: SystemEntityRegistryPayload::EntityKey(key),
1865 }
1866 }
1867 None => {
1868 error!("unexpected query failure; mint not found");
1869 SystemEntityRegistryResult::NamedEntityNotFound(name.clone())
1870 }
1871 },
1872 }
1873 }
1874
1875 fn entry_point(&self, request: EntryPointRequest) -> EntryPointResult {
1877 let state_root_hash = request.state_hash();
1878 let contract_hash = request.contract_hash();
1879 let entry_point_name = request.entry_point_name();
1880 match EntryPointAddr::new_v1_entry_point_addr(
1881 EntityAddr::SmartContract(contract_hash),
1882 entry_point_name,
1883 ) {
1884 Ok(entry_point_addr) => {
1885 let key = Key::EntryPoint(entry_point_addr);
1886 let query_request = QueryRequest::new(request.state_hash(), key, vec![]);
1887 match self.query(query_request) {
1889 QueryResult::RootNotFound => EntryPointResult::RootNotFound,
1890 QueryResult::ValueNotFound(query_result_not_found_msg) => {
1891 let contract_key = Key::Hash(contract_hash);
1894 let contract_request = ContractRequest::new(state_root_hash, contract_key);
1895 match self.contract(contract_request) {
1896 ContractResult::Failure(tce) => EntryPointResult::Failure(tce),
1897 ContractResult::ValueNotFound(_) => {
1898 EntryPointResult::ValueNotFound(query_result_not_found_msg)
1899 }
1900 ContractResult::RootNotFound => EntryPointResult::RootNotFound,
1901 ContractResult::Success { contract } => {
1902 match contract.entry_points().get(entry_point_name) {
1903 Some(contract_entry_point) => EntryPointResult::Success {
1904 entry_point: EntryPointValue::V1CasperVm(
1905 EntityEntryPoint::from(contract_entry_point),
1906 ),
1907 },
1908 None => {
1909 EntryPointResult::ValueNotFound(query_result_not_found_msg)
1910 }
1911 }
1912 }
1913 }
1914 }
1915 QueryResult::Failure(tce) => EntryPointResult::Failure(tce),
1916 QueryResult::Success { value, .. } => {
1917 if let StoredValue::EntryPoint(entry_point) = *value {
1918 EntryPointResult::Success { entry_point }
1919 } else {
1920 error!("Expected to get entry point value received other variant");
1921 EntryPointResult::Failure(
1922 TrackingCopyError::UnexpectedStoredValueVariant,
1923 )
1924 }
1925 }
1926 }
1927 }
1928 Err(_) => EntryPointResult::Failure(
1929 TrackingCopyError::ValueNotFound("Entry point not found".to_string()),
1931 ),
1932 }
1933 }
1934
1935 fn contract(&self, request: ContractRequest) -> ContractResult {
1937 let query_request = QueryRequest::new(request.state_hash(), request.key(), vec![]);
1938
1939 match self.query(query_request) {
1940 QueryResult::RootNotFound => ContractResult::RootNotFound,
1941 QueryResult::ValueNotFound(msg) => ContractResult::ValueNotFound(msg),
1942 QueryResult::Failure(tce) => ContractResult::Failure(tce),
1943 QueryResult::Success { value, .. } => {
1944 if let StoredValue::Contract(contract) = *value {
1945 ContractResult::Success { contract }
1946 } else {
1947 error!("Expected to get contract value received other variant");
1948 ContractResult::Failure(TrackingCopyError::UnexpectedStoredValueVariant)
1949 }
1950 }
1951 }
1952 }
1953
1954 fn entry_point_exists(&self, request: EntryPointExistsRequest) -> EntryPointExistsResult {
1956 match self.entry_point(request.into()) {
1957 EntryPointResult::RootNotFound => EntryPointExistsResult::RootNotFound,
1958 EntryPointResult::ValueNotFound(msg) => EntryPointExistsResult::ValueNotFound(msg),
1959 EntryPointResult::Success { .. } => EntryPointExistsResult::Success,
1960 EntryPointResult::Failure(error) => EntryPointExistsResult::Failure(error),
1961 }
1962 }
1963
1964 fn total_supply(&self, request: TotalSupplyRequest) -> TotalSupplyResult {
1966 let state_hash = request.state_hash();
1967 let tc = match self.tracking_copy(state_hash) {
1968 Ok(Some(tc)) => tc,
1969 Ok(None) => return TotalSupplyResult::RootNotFound,
1970 Err(err) => return TotalSupplyResult::Failure(TrackingCopyError::Storage(err)),
1971 };
1972 let scr = match tc.get_system_entity_registry() {
1973 Ok(scr) => scr,
1974 Err(err) => return TotalSupplyResult::Failure(err),
1975 };
1976 let enable_addressable_entity = tc.enable_addressable_entity();
1977 match get_total_supply_data(self, &scr, state_hash, enable_addressable_entity) {
1978 not_found @ TotalSupplyResult::ValueNotFound(_) => {
1979 if enable_addressable_entity {
1980 match get_total_supply_data(self, &scr, state_hash, false) {
1986 TotalSupplyResult::ValueNotFound(_) => not_found,
1987 other => other,
1988 }
1989 } else {
1990 not_found
1991 }
1992 }
1993 other => other,
1994 }
1995 }
1996
1997 fn round_seigniorage_rate(
1999 &self,
2000 request: RoundSeigniorageRateRequest,
2001 ) -> RoundSeigniorageRateResult {
2002 let state_hash = request.state_hash();
2003 let tc = match self.tracking_copy(state_hash) {
2004 Ok(Some(tc)) => tc,
2005 Ok(None) => return RoundSeigniorageRateResult::RootNotFound,
2006 Err(err) => {
2007 return RoundSeigniorageRateResult::Failure(TrackingCopyError::Storage(err));
2008 }
2009 };
2010 let scr = match tc.get_system_entity_registry() {
2011 Ok(scr) => scr,
2012 Err(err) => return RoundSeigniorageRateResult::Failure(err),
2013 };
2014 let enable_addressable_entity = tc.enable_addressable_entity();
2015 match get_round_seigniorage_rate_data(self, &scr, state_hash, enable_addressable_entity) {
2016 not_found @ RoundSeigniorageRateResult::ValueNotFound(_) => {
2017 if enable_addressable_entity {
2018 match get_round_seigniorage_rate_data(self, &scr, state_hash, false) {
2024 RoundSeigniorageRateResult::ValueNotFound(_) => not_found,
2025 other => other,
2026 }
2027 } else {
2028 not_found
2029 }
2030 }
2031 other => other,
2032 }
2033 }
2034
2035 fn transfer(&self, request: TransferRequest) -> TransferResult {
2037 let state_hash = request.state_hash();
2038 let tc = match self.tracking_copy(state_hash) {
2039 Ok(Some(tc)) => Rc::new(RefCell::new(tc)),
2040 Ok(None) => return TransferResult::RootNotFound,
2041 Err(err) => {
2042 return TransferResult::Failure(TransferError::TrackingCopy(
2043 TrackingCopyError::Storage(err),
2044 ));
2045 }
2046 };
2047
2048 let source_account_hash = request.initiator().account_hash();
2049 let protocol_version = request.protocol_version();
2050 if let Err(tce) = tc
2051 .borrow_mut()
2052 .migrate_account(source_account_hash, protocol_version)
2053 {
2054 return TransferResult::Failure(tce.into());
2055 }
2056
2057 let authorization_keys = request.authorization_keys();
2058
2059 let config = request.config();
2060 let transfer_config = config.transfer_config();
2061 let administrative_accounts = transfer_config.administrative_accounts();
2062
2063 let runtime_args = match request.args() {
2064 TransferRequestArgs::Raw(runtime_args) => runtime_args.clone(),
2065 TransferRequestArgs::Explicit(transfer_args) => {
2066 match RuntimeArgs::try_from(*transfer_args) {
2067 Ok(runtime_args) => runtime_args,
2068 Err(cve) => return TransferResult::Failure(TransferError::CLValue(cve)),
2069 }
2070 }
2071 TransferRequestArgs::Indirect(bita) => {
2072 let source_uref = match bita
2073 .source()
2074 .purse_uref(&mut tc.borrow_mut(), protocol_version)
2075 {
2076 Ok(source_uref) => source_uref,
2077 Err(tce) => return TransferResult::Failure(TransferError::TrackingCopy(tce)),
2078 };
2079 let target_uref = match bita
2080 .target()
2081 .purse_uref(&mut tc.borrow_mut(), protocol_version)
2082 {
2083 Ok(target_uref) => target_uref,
2084 Err(tce) => return TransferResult::Failure(TransferError::TrackingCopy(tce)),
2085 };
2086 let transfer_args = TransferArgs::new(
2087 bita.to(),
2088 source_uref,
2089 target_uref,
2090 bita.amount(),
2091 bita.arg_id(),
2092 );
2093 match RuntimeArgs::try_from(transfer_args) {
2094 Ok(runtime_args) => runtime_args,
2095 Err(cve) => return TransferResult::Failure(TransferError::CLValue(cve)),
2096 }
2097 }
2098 };
2099
2100 let remaining_spending_limit = match runtime_args.try_get_number(ARG_AMOUNT) {
2101 Ok(amount) => amount,
2102 Err(cve) => {
2103 debug!("failed to derive remaining_spending_limit");
2104 return TransferResult::Failure(TransferError::CLValue(cve));
2105 }
2106 };
2107
2108 let mut runtime_args_builder = TransferRuntimeArgsBuilder::new(runtime_args);
2109
2110 let transfer_target_mode = match runtime_args_builder
2111 .resolve_transfer_target_mode(protocol_version, Rc::clone(&tc))
2112 {
2113 Ok(transfer_target_mode) => transfer_target_mode,
2114 Err(error) => return TransferResult::Failure(error),
2115 };
2116
2117 if transfer_config.enforce_transfer_restrictions(&source_account_hash) {
2121 match transfer_target_mode.target_account_hash() {
2126 Some(target_account_hash) => {
2127 let is_target_system_account =
2128 target_account_hash == PublicKey::System.to_account_hash();
2129 let is_target_administrator =
2130 transfer_config.is_administrator(&target_account_hash);
2131 if !(is_target_system_account || is_target_administrator) {
2132 return TransferResult::Failure(TransferError::RestrictedTransferAttempted);
2134 }
2135 }
2136 None => {
2137 return TransferResult::Failure(TransferError::UnableToVerifyTargetIsAdmin);
2139 }
2140 }
2141 }
2142
2143 let (entity_addr, runtime_footprint, entity_access_rights) = match tc
2144 .borrow_mut()
2145 .authorized_runtime_footprint_with_access_rights(
2146 protocol_version,
2147 source_account_hash,
2148 authorization_keys,
2149 &administrative_accounts,
2150 ) {
2151 Ok(ret) => ret,
2152 Err(tce) => {
2153 return TransferResult::Failure(TransferError::TrackingCopy(tce));
2154 }
2155 };
2156 let entity_key = if config.enable_addressable_entity() {
2157 Key::AddressableEntity(entity_addr)
2158 } else {
2159 match entity_addr {
2160 EntityAddr::System(hash) | EntityAddr::SmartContract(hash) => Key::Hash(hash),
2161 EntityAddr::Account(hash) => Key::Account(AccountHash::new(hash)),
2162 }
2163 };
2164 let id = Id::Transaction(request.transaction_hash());
2165 let phase = Phase::Session;
2166 let address_generator = AddressGenerator::new(&id.seed(), phase);
2167 let mut runtime = RuntimeNative::new(
2169 config.clone(),
2170 protocol_version,
2171 id,
2172 Arc::new(RwLock::new(address_generator)),
2173 Rc::clone(&tc),
2174 source_account_hash,
2175 entity_key,
2176 runtime_footprint.clone(),
2177 entity_access_rights,
2178 remaining_spending_limit,
2179 phase,
2180 );
2181
2182 match transfer_target_mode {
2183 TransferTargetMode::ExistingAccount { .. } | TransferTargetMode::PurseExists { .. } => {
2184 }
2186 TransferTargetMode::CreateAccount(account_hash) => {
2187 let main_purse = match runtime.mint(U512::zero()) {
2188 Ok(uref) => uref,
2189 Err(mint_error) => {
2190 return TransferResult::Failure(TransferError::Mint(mint_error));
2191 }
2192 };
2193
2194 let account = Account::create(account_hash, NamedKeys::new(), main_purse);
2195 if let Err(tce) = tc
2196 .borrow_mut()
2197 .create_addressable_entity_from_account(account, protocol_version)
2198 {
2199 return TransferResult::Failure(tce.into());
2200 }
2201 }
2202 }
2203 let transfer_args = match runtime_args_builder.build(
2204 &runtime_footprint,
2205 protocol_version,
2206 Rc::clone(&tc),
2207 ) {
2208 Ok(transfer_args) => transfer_args,
2209 Err(error) => return TransferResult::Failure(error),
2210 };
2211 if let Err(mint_error) = runtime.transfer(
2212 transfer_args.to(),
2213 transfer_args.source(),
2214 transfer_args.target(),
2215 transfer_args.amount(),
2216 transfer_args.arg_id(),
2217 ) {
2218 return TransferResult::Failure(TransferError::Mint(mint_error));
2219 }
2220
2221 let transfers = runtime.into_transfers();
2222
2223 let effects = tc.borrow_mut().effects();
2224 let cache = tc.borrow_mut().cache();
2225
2226 TransferResult::Success {
2227 transfers,
2228 effects,
2229 cache,
2230 }
2231 }
2232
2233 fn burn(&self, request: BurnRequest) -> BurnResult {
2235 let state_hash = request.state_hash();
2236 let tc = match self.tracking_copy(state_hash) {
2237 Ok(Some(tc)) => Rc::new(RefCell::new(tc)),
2238 Ok(None) => return BurnResult::RootNotFound,
2239 Err(err) => {
2240 return BurnResult::Failure(BurnError::TrackingCopy(TrackingCopyError::Storage(
2241 err,
2242 )));
2243 }
2244 };
2245
2246 let source_account_hash = request.initiator().account_hash();
2247 let protocol_version = request.protocol_version();
2248 if let Err(tce) = tc
2249 .borrow_mut()
2250 .migrate_account(source_account_hash, protocol_version)
2251 {
2252 return BurnResult::Failure(tce.into());
2253 }
2254
2255 let authorization_keys = request.authorization_keys();
2256
2257 let config = request.config();
2258
2259 let runtime_args = match request.args() {
2260 BurnRequestArgs::Raw(runtime_args) => runtime_args.clone(),
2261 BurnRequestArgs::Explicit(transfer_args) => {
2262 match RuntimeArgs::try_from(*transfer_args) {
2263 Ok(runtime_args) => runtime_args,
2264 Err(cve) => return BurnResult::Failure(BurnError::CLValue(cve)),
2265 }
2266 }
2267 };
2268
2269 let runtime_args_builder = BurnRuntimeArgsBuilder::new(runtime_args);
2270
2271 let (entity_addr, mut footprint, mut entity_access_rights) = match tc
2272 .borrow_mut()
2273 .authorized_runtime_footprint_with_access_rights(
2274 protocol_version,
2275 source_account_hash,
2276 authorization_keys,
2277 &BTreeSet::default(),
2278 ) {
2279 Ok(ret) => ret,
2280 Err(tce) => {
2281 return BurnResult::Failure(BurnError::TrackingCopy(tce));
2282 }
2283 };
2284 let entity_key = if config.enable_addressable_entity() {
2285 Key::AddressableEntity(entity_addr)
2286 } else {
2287 match entity_addr {
2288 EntityAddr::System(hash) | EntityAddr::SmartContract(hash) => Key::Hash(hash),
2289 EntityAddr::Account(hash) => Key::Account(AccountHash::new(hash)),
2290 }
2291 };
2292
2293 match tc
2295 .borrow_mut()
2296 .system_contract_named_key(MINT, TOTAL_SUPPLY_KEY)
2297 {
2298 Ok(Some(k)) => {
2299 match k.as_uref() {
2300 Some(uref) => entity_access_rights.extend(&[*uref]),
2301 None => {
2302 return BurnResult::Failure(BurnError::TrackingCopy(
2303 TrackingCopyError::UnexpectedKeyVariant(k),
2304 ));
2305 }
2306 }
2307 footprint.insert_into_named_keys(TOTAL_SUPPLY_KEY.into(), k);
2308 }
2309 Ok(None) => {
2310 return BurnResult::Failure(BurnError::TrackingCopy(
2311 TrackingCopyError::NamedKeyNotFound(TOTAL_SUPPLY_KEY.into()),
2312 ));
2313 }
2314 Err(tce) => {
2315 return BurnResult::Failure(BurnError::TrackingCopy(tce));
2316 }
2317 };
2318 let id = Id::Transaction(request.transaction_hash());
2319 let phase = Phase::Session;
2320 let address_generator = AddressGenerator::new(&id.seed(), phase);
2321 let burn_args = match runtime_args_builder.build(&footprint, Rc::clone(&tc)) {
2322 Ok(burn_args) => burn_args,
2323 Err(error) => return BurnResult::Failure(error),
2324 };
2325
2326 let mut runtime = RuntimeNative::new(
2328 config.clone(),
2329 protocol_version,
2330 id,
2331 Arc::new(RwLock::new(address_generator)),
2332 Rc::clone(&tc),
2333 source_account_hash,
2334 entity_key,
2335 footprint.clone(),
2336 entity_access_rights,
2337 burn_args.amount(),
2338 phase,
2339 );
2340
2341 if let Err(mint_error) = runtime.burn(burn_args.source(), burn_args.amount()) {
2342 return BurnResult::Failure(BurnError::Mint(mint_error));
2343 }
2344
2345 let effects = tc.borrow_mut().effects();
2346 let cache = tc.borrow_mut().cache();
2347
2348 BurnResult::Success { effects, cache }
2349 }
2350
2351 fn tagged_values(&self, request: TaggedValuesRequest) -> TaggedValuesResult {
2353 let state_hash = request.state_hash();
2354 let mut tc = match self.tracking_copy(state_hash) {
2355 Ok(Some(tc)) => tc,
2356 Ok(None) => return TaggedValuesResult::RootNotFound,
2357 Err(gse) => return TaggedValuesResult::Failure(TrackingCopyError::Storage(gse)),
2358 };
2359
2360 let key_tag = request.key_tag();
2361 let keys = match tc.get_keys(&key_tag) {
2362 Ok(keys) => keys,
2363 Err(tce) => return TaggedValuesResult::Failure(tce),
2364 };
2365
2366 let mut values = vec![];
2367 for key in keys {
2368 match tc.get(&key) {
2369 Ok(Some(value)) => {
2370 values.push(value);
2371 }
2372 Ok(None) => {}
2373 Err(error) => return TaggedValuesResult::Failure(error),
2374 }
2375 }
2376
2377 TaggedValuesResult::Success {
2378 values,
2379 selection: request.selection(),
2380 }
2381 }
2382
2383 fn prefixed_values(&self, request: PrefixedValuesRequest) -> PrefixedValuesResult {
2386 let mut tc = match self.tracking_copy(request.state_hash()) {
2387 Ok(Some(tc)) => tc,
2388 Ok(None) => return PrefixedValuesResult::RootNotFound,
2389 Err(err) => return PrefixedValuesResult::Failure(TrackingCopyError::Storage(err)),
2390 };
2391 match tc.get_keys_by_prefix(request.key_prefix()) {
2392 Ok(keys) => {
2393 let mut values = Vec::with_capacity(keys.len());
2394 for key in keys {
2395 match tc.get(&key) {
2396 Ok(Some(value)) => values.push(value),
2397 Ok(None) => {}
2398 Err(error) => return PrefixedValuesResult::Failure(error),
2399 }
2400 }
2401 PrefixedValuesResult::Success {
2402 values,
2403 key_prefix: request.key_prefix().clone(),
2404 }
2405 }
2406 Err(error) => PrefixedValuesResult::Failure(error),
2407 }
2408 }
2409
2410 fn trie(&self, request: TrieRequest) -> TrieResult;
2412
2413 fn put_trie(&self, request: PutTrieRequest) -> PutTrieResult;
2415
2416 fn missing_children(&self, trie_raw: &[u8]) -> Result<Vec<Digest>, GlobalStateError>;
2418
2419 fn enable_entity(&self) -> bool;
2421}
2422
2423fn get_round_seigniorage_rate_data<T: StateProvider>(
2424 state_provider: &T,
2425 scr: &SystemHashRegistry,
2426 state_hash: Digest,
2427 enable_addressable_entity: bool,
2428) -> RoundSeigniorageRateResult {
2429 let query_request = match scr.get(MINT).copied() {
2430 Some(mint_hash) => {
2431 let key = if !enable_addressable_entity {
2432 Key::Hash(mint_hash)
2433 } else {
2434 Key::AddressableEntity(EntityAddr::System(mint_hash))
2435 };
2436 QueryRequest::new(
2437 state_hash,
2438 key,
2439 vec![ROUND_SEIGNIORAGE_RATE_KEY.to_string()],
2440 )
2441 }
2442 None => {
2443 error!("unexpected query failure; mint not found");
2444 return RoundSeigniorageRateResult::MintNotFound;
2445 }
2446 };
2447
2448 match state_provider.query(query_request) {
2449 QueryResult::RootNotFound => RoundSeigniorageRateResult::RootNotFound,
2450 QueryResult::ValueNotFound(msg) => RoundSeigniorageRateResult::ValueNotFound(msg),
2451 QueryResult::Failure(tce) => RoundSeigniorageRateResult::Failure(tce),
2452 QueryResult::Success { value, proofs: _ } => {
2453 let cl_value = match value.into_cl_value() {
2454 Some(cl_value) => cl_value,
2455 None => {
2456 error!("unexpected query failure; total supply is not a CLValue");
2457 return RoundSeigniorageRateResult::Failure(
2458 TrackingCopyError::UnexpectedStoredValueVariant,
2459 );
2460 }
2461 };
2462
2463 match cl_value.into_t() {
2464 Ok(rate) => RoundSeigniorageRateResult::Success { rate },
2465 Err(cve) => RoundSeigniorageRateResult::Failure(TrackingCopyError::CLValue(cve)),
2466 }
2467 }
2468 }
2469}
2470
2471fn get_total_supply_data<T: StateProvider>(
2472 state_provider: &T,
2473 scr: &SystemHashRegistry,
2474 state_hash: Digest,
2475 enable_addressable_entity: bool,
2476) -> TotalSupplyResult {
2477 let query_request = match scr.get(MINT).copied() {
2478 Some(mint_hash) => {
2479 let key = if !enable_addressable_entity {
2480 Key::Hash(mint_hash)
2481 } else {
2482 Key::AddressableEntity(EntityAddr::System(mint_hash))
2483 };
2484 QueryRequest::new(state_hash, key, vec![TOTAL_SUPPLY_KEY.to_string()])
2485 }
2486 None => {
2487 error!("unexpected query failure; mint not found");
2488 return TotalSupplyResult::MintNotFound;
2489 }
2490 };
2491 match state_provider.query(query_request) {
2492 QueryResult::RootNotFound => TotalSupplyResult::RootNotFound,
2493 QueryResult::ValueNotFound(msg) => TotalSupplyResult::ValueNotFound(msg),
2494 QueryResult::Failure(tce) => TotalSupplyResult::Failure(tce),
2495 QueryResult::Success { value, proofs: _ } => {
2496 let cl_value = match value.into_cl_value() {
2497 Some(cl_value) => cl_value,
2498 None => {
2499 error!("unexpected query failure; total supply is not a CLValue");
2500 return TotalSupplyResult::Failure(
2501 TrackingCopyError::UnexpectedStoredValueVariant,
2502 );
2503 }
2504 };
2505
2506 match cl_value.into_t() {
2507 Ok(total_supply) => TotalSupplyResult::Success { total_supply },
2508 Err(cve) => TotalSupplyResult::Failure(TrackingCopyError::CLValue(cve)),
2509 }
2510 }
2511 }
2512}
2513
2514fn get_snapshot_data<T: StateProvider>(
2515 state_provider: &T,
2516 scr: &SystemHashRegistry,
2517 state_hash: Digest,
2518 enable_addressable_entity: bool,
2519) -> SeigniorageRecipientsResult {
2520 let (snapshot_query_request, snapshot_version_query_request) =
2521 match build_query_requests(scr, state_hash, enable_addressable_entity) {
2522 Ok(res) => res,
2523 Err(res) => return res,
2524 };
2525
2526 let snapshot_version: Option<u8> =
2528 match query_snapshot_version(state_provider, snapshot_version_query_request) {
2529 Ok(value) => value,
2530 Err(value) => return value,
2531 };
2532
2533 let snapshot = match query_snapshot(state_provider, snapshot_version, snapshot_query_request) {
2534 Ok(snapshot) => snapshot,
2535 Err(value) => return value,
2536 };
2537
2538 SeigniorageRecipientsResult::Success {
2539 seigniorage_recipients: snapshot,
2540 }
2541}
2542
2543fn query_snapshot<T: StateProvider>(
2544 state_provider: &T,
2545 snapshot_version: Option<u8>,
2546 snapshot_query_request: QueryRequest,
2547) -> Result<SeigniorageRecipientsSnapshot, SeigniorageRecipientsResult> {
2548 match state_provider.query(snapshot_query_request) {
2549 QueryResult::RootNotFound => Err(SeigniorageRecipientsResult::RootNotFound),
2550 QueryResult::Failure(error) => {
2551 error!(?error, "unexpected tracking copy error");
2552 Err(SeigniorageRecipientsResult::Failure(error))
2553 }
2554 QueryResult::ValueNotFound(msg) => {
2555 error!(%msg, "value not found");
2556 Err(SeigniorageRecipientsResult::ValueNotFound(msg))
2557 }
2558 QueryResult::Success { value, proofs: _ } => {
2559 let cl_value = match value.into_cl_value() {
2560 Some(snapshot_cl_value) => snapshot_cl_value,
2561 None => {
2562 error!("unexpected query failure; seigniorage recipients snapshot is not a CLValue");
2563 return Err(SeigniorageRecipientsResult::Failure(
2564 TrackingCopyError::UnexpectedStoredValueVariant,
2565 ));
2566 }
2567 };
2568
2569 match snapshot_version {
2570 Some(_) => {
2571 let snapshot = match cl_value.into_t() {
2572 Ok(snapshot) => snapshot,
2573 Err(cve) => {
2574 error!("Failed to convert snapshot from CLValue");
2575 return Err(SeigniorageRecipientsResult::Failure(
2576 TrackingCopyError::CLValue(cve),
2577 ));
2578 }
2579 };
2580 Ok(SeigniorageRecipientsSnapshot::V2(snapshot))
2581 }
2582 None => {
2583 let snapshot = match cl_value.into_t() {
2584 Ok(snapshot) => snapshot,
2585 Err(cve) => {
2586 error!("Failed to convert snapshot from CLValue");
2587 return Err(SeigniorageRecipientsResult::Failure(
2588 TrackingCopyError::CLValue(cve),
2589 ));
2590 }
2591 };
2592 Ok(SeigniorageRecipientsSnapshot::V1(snapshot))
2593 }
2594 }
2595 }
2596 }
2597}
2598
2599fn query_snapshot_version<T: StateProvider>(
2600 state_provider: &T,
2601 snapshot_version_query_request: QueryRequest,
2602) -> Result<Option<u8>, SeigniorageRecipientsResult> {
2603 match state_provider.query(snapshot_version_query_request) {
2604 QueryResult::RootNotFound => Err(SeigniorageRecipientsResult::RootNotFound),
2605 QueryResult::Failure(error) => {
2606 error!(?error, "unexpected tracking copy error");
2607 Err(SeigniorageRecipientsResult::Failure(error))
2608 }
2609 QueryResult::ValueNotFound(_msg) => Ok(None),
2610 QueryResult::Success { value, proofs: _ } => {
2611 let cl_value = match value.into_cl_value() {
2612 Some(snapshot_version_cl_value) => snapshot_version_cl_value,
2613 None => {
2614 error!("unexpected query failure; seigniorage recipients snapshot version is not a CLValue");
2615 return Err(SeigniorageRecipientsResult::Failure(
2616 TrackingCopyError::UnexpectedStoredValueVariant,
2617 ));
2618 }
2619 };
2620 match cl_value.into_t() {
2621 Ok(snapshot_version) => Ok(Some(snapshot_version)),
2622 Err(cve) => Err(SeigniorageRecipientsResult::Failure(
2623 TrackingCopyError::CLValue(cve),
2624 )),
2625 }
2626 }
2627 }
2628}
2629
2630fn build_query_requests(
2631 scr: &SystemHashRegistry,
2632 state_hash: Digest,
2633 enable_addressable_entity: bool,
2634) -> Result<(QueryRequest, QueryRequest), SeigniorageRecipientsResult> {
2635 match scr.get(AUCTION).copied() {
2636 Some(auction_hash) => {
2637 let key = if !enable_addressable_entity {
2638 Key::Hash(auction_hash)
2639 } else {
2640 Key::AddressableEntity(EntityAddr::System(auction_hash))
2641 };
2642 Ok((
2643 QueryRequest::new(
2644 state_hash,
2645 key,
2646 vec![SEIGNIORAGE_RECIPIENTS_SNAPSHOT_KEY.to_string()],
2647 ),
2648 QueryRequest::new(
2649 state_hash,
2650 key,
2651 vec![SEIGNIORAGE_RECIPIENTS_SNAPSHOT_VERSION_KEY.to_string()],
2652 ),
2653 ))
2654 }
2655 None => Err(SeigniorageRecipientsResult::AuctionNotFound),
2656 }
2657}
2658
2659pub fn put_stored_values<'a, R, S, E>(
2661 environment: &'a R,
2662 store: &S,
2663 prestate_hash: Digest,
2664 stored_values: Vec<(Key, StoredValue)>,
2665) -> Result<Digest, E>
2666where
2667 R: TransactionSource<'a, Handle = S::Handle>,
2668 S: TrieStore<Key, StoredValue>,
2669 S::Error: From<R::Error>,
2670 E: From<R::Error>
2671 + From<S::Error>
2672 + From<bytesrepr::Error>
2673 + From<CommitError>
2674 + From<TrieStoreCacheError>,
2675{
2676 let mut txn = environment.create_read_write_txn()?;
2677 let state_root = prestate_hash;
2678 let maybe_root: Option<Trie<Key, StoredValue>> = store.get(&txn, &state_root)?;
2679 if maybe_root.is_none() {
2680 return Err(CommitError::RootNotFound(prestate_hash).into());
2681 };
2682
2683 let state_root =
2684 batch_write::<_, _, _, _, _, E>(&mut txn, store, &state_root, stored_values.into_iter())?;
2685 txn.commit()?;
2686 Ok(state_root)
2687}
2688
2689pub fn commit<'a, R, S, E>(
2691 environment: &'a R,
2692 store: &S,
2693 prestate_hash: Digest,
2694 effects: Effects,
2695) -> Result<Digest, E>
2696where
2697 R: TransactionSource<'a, Handle = S::Handle>,
2698 S: TrieStore<Key, StoredValue>,
2699 S::Error: From<R::Error>,
2700 E: From<R::Error>
2701 + From<S::Error>
2702 + From<bytesrepr::Error>
2703 + From<CommitError>
2704 + From<GlobalStateError>, {
2707 let mut txn = environment.create_read_write_txn()?;
2708 let mut state_root = prestate_hash;
2709
2710 let maybe_root: Option<Trie<Key, StoredValue>> = store.get(&txn, &state_root)?;
2711
2712 if maybe_root.is_none() {
2713 return Err(CommitError::RootNotFound(prestate_hash).into());
2714 };
2715
2716 for (key, kind) in effects.value().into_iter().map(TransformV2::destructure) {
2717 let read_result = read::<_, _, _, _, E>(&txn, store, &state_root, &key)?;
2718
2719 let instruction = match (read_result, kind) {
2720 (_, TransformKindV2::Identity) => {
2721 continue;
2723 }
2724 (ReadResult::NotFound, TransformKindV2::Write(new_value)) => {
2725 TransformInstruction::store(new_value)
2726 }
2727 (ReadResult::NotFound, TransformKindV2::Prune(key)) => {
2728 debug!(
2730 ?state_root,
2731 ?key,
2732 "commit: attempt to prune nonexistent record; this may happen if a key is both added and pruned in the same commit."
2733 );
2734 continue;
2735 }
2736 (ReadResult::NotFound, transform_kind) => {
2737 error!(
2738 ?state_root,
2739 ?key,
2740 ?transform_kind,
2741 "commit: key not found while attempting to apply transform"
2742 );
2743 return Err(CommitError::KeyNotFound(key).into());
2744 }
2745 (ReadResult::Found(current_value), transform_kind) => {
2746 match transform_kind.apply(current_value) {
2747 Ok(instruction) => instruction,
2748 Err(err) => {
2749 error!(
2750 ?state_root,
2751 ?key,
2752 ?err,
2753 "commit: key found, but could not apply transform"
2754 );
2755 return Err(CommitError::TransformError(err).into());
2756 }
2757 }
2758 }
2759 (ReadResult::RootNotFound, transform_kind) => {
2760 error!(
2761 ?state_root,
2762 ?key,
2763 ?transform_kind,
2764 "commit: failed to read state root while processing transform"
2765 );
2766 return Err(CommitError::ReadRootNotFound(state_root).into());
2767 }
2768 };
2769
2770 match instruction {
2771 TransformInstruction::Store(value) => {
2772 let write_result =
2773 write::<_, _, _, _, E>(&mut txn, store, &state_root, &key, &value)?;
2774
2775 match write_result {
2776 WriteResult::Written(root_hash) => {
2777 state_root = root_hash;
2778 }
2779 WriteResult::AlreadyExists => (),
2780 WriteResult::RootNotFound => {
2781 error!(?state_root, ?key, ?value, "commit: root not found");
2782 return Err(CommitError::WriteRootNotFound(state_root).into());
2783 }
2784 }
2785 }
2786 TransformInstruction::Prune(key) => {
2787 let prune_result = prune::<_, _, _, _, E>(&mut txn, store, &state_root, &key)?;
2788
2789 match prune_result {
2790 TriePruneResult::Pruned(root_hash) => {
2791 state_root = root_hash;
2792 }
2793 TriePruneResult::MissingKey => {
2794 warn!("commit: pruning attempt failed for {}", key);
2795 }
2796 TriePruneResult::RootNotFound => {
2797 error!(?state_root, ?key, "commit: root not found");
2798 return Err(CommitError::WriteRootNotFound(state_root).into());
2799 }
2800 TriePruneResult::Failure(gse) => {
2801 return Err(gse.into()); }
2803 }
2804 }
2805 }
2806 }
2807
2808 txn.commit()?;
2809
2810 Ok(state_root)
2811}