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