casper_storage/global_state/state/
mod.rs

1//! Global state.
2
3/// Lmdb implementation of global state.
4pub mod lmdb;
5
6/// Lmdb implementation of global state with cache.
7pub 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
105/// A trait expressing the reading of state. This trait is used to abstract the underlying store.
106pub trait StateReader<K = Key, V = StoredValue>: Sized + Send + Sync {
107    /// An error which occurs when reading state
108    type Error;
109
110    /// Returns the state value from the corresponding key
111    fn read(&self, key: &K) -> Result<Option<V>, Self::Error>;
112
113    /// Returns the merkle proof of the state value from the corresponding key
114    fn read_with_proof(&self, key: &K) -> Result<Option<TrieMerkleProof<K, V>>, Self::Error>;
115
116    /// Returns the keys in the trie matching `prefix`.
117    fn keys_with_prefix(&self, prefix: &[u8]) -> Result<Vec<K>, Self::Error>;
118}
119
120/// An error emitted by the execution engine on commit
121#[derive(Clone, Debug, thiserror::Error, Eq, PartialEq)]
122pub enum CommitError {
123    /// Root not found.
124    #[error("Root not found: {0:?}")]
125    RootNotFound(Digest),
126    /// Root not found while attempting to read.
127    #[error("Root not found while attempting to read: {0:?}")]
128    ReadRootNotFound(Digest),
129    /// Root not found while attempting to write.
130    #[error("Root not found while writing: {0:?}")]
131    WriteRootNotFound(Digest),
132    /// Key not found.
133    #[error("Key not found: {0}")]
134    KeyNotFound(Key),
135    /// Transform error.
136    #[error(transparent)]
137    TransformError(TransformError),
138    /// Trie not found while attempting to validate cache write.
139    #[error("Trie not found in cache {0}")]
140    TrieNotFoundInCache(Digest),
141}
142
143/// Scratch provider.
144pub trait ScratchProvider: CommitProvider {
145    /// Get scratch state to db.
146    fn get_scratch_global_state(&self) -> ScratchGlobalState;
147    /// Write scratch state to db.
148    fn write_scratch_to_db(
149        &self,
150        state_root_hash: Digest,
151        scratch_global_state: ScratchGlobalState,
152    ) -> Result<Digest, GlobalStateError>;
153    /// Prune items for imputed keys.
154    fn prune_keys(&self, state_root_hash: Digest, keys: &[Key]) -> TriePruneResult;
155}
156
157/// Provides `commit` method.
158pub trait CommitProvider: StateProvider {
159    /// Applies changes and returns a new post state hash.
160    /// block_hash is used for computing a deterministic and unique keys.
161    fn commit_effects(
162        &self,
163        state_hash: Digest,
164        effects: Effects,
165    ) -> Result<Digest, GlobalStateError>;
166
167    /// Commit values to global state.
168    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    /// Runs and commits the genesis process, once per network.
176    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    /// Runs and commits the protocol upgrade process.
212    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        // commit
235        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    /// Safely prune specified keys from global state, using a tracking copy.
247    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            // effectively a noop
258            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    /// Step auction state at era end.
280    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            // seeds address generator w/ era_end_timestamp_millis
295            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        // this runtime uses the system's context
325        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    /// Distribute block rewards.
382    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            // if there are no rewards to distribute, this is effectively a noop
388            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        // this runtime uses the system's context
428        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    /// Distribute fees, if relevant to the chainspec configured behavior.
472    fn distribute_fees(&self, request: FeeRequest) -> FeeResult {
473        let state_hash = request.state_hash();
474        if !request.should_distribute_fees() {
475            // effectively noop
476            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        // this runtime uses the system's context
515        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        // amount = None will distribute the full current balance of the accumulation purse
537        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    /// Forcibly unbonds delegator bids which fall outside configured delegation limits.
564    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        // this runtime uses the system's context
601        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    /// Gets block global data.
639    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
648        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
717/// A trait expressing operations over the trie.
718pub trait StateProvider: Send + Sync + Sized {
719    /// Associated reader type for `StateProvider`.
720    type Reader: StateReader<Key, StoredValue, Error = GlobalStateError>;
721
722    /// Flush the state provider.
723    fn flush(&self, request: FlushRequest) -> FlushResult;
724
725    /// Returns an empty root hash.
726    fn empty_root(&self) -> Digest;
727
728    /// Get a tracking copy.
729    fn tracking_copy(
730        &self,
731        state_hash: Digest,
732    ) -> Result<Option<TrackingCopy<Self::Reader>>, GlobalStateError>;
733
734    /// Checkouts a slice of initial state using root state hash.
735    fn checkout(&self, state_hash: Digest) -> Result<Option<Self::Reader>, GlobalStateError>;
736
737    /// Query state.
738    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    /// Message topics request.
750    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    /// Provides the underlying addr for the imputed balance identifier.
764    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    /// Balance inquiry.
784    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    /// Balance hold.
905    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                        // the purse has sufficient balance to fully cover the hold
957                        hold_amount
958                    } else if insufficient_handling == InsufficientBalanceHandling::Noop {
959                        // the purse has insufficient balance and the insufficient
960                        // balance handling mode is noop, so get out
961                        return BalanceHoldResult::Failure(BalanceHoldError::InsufficientBalance {
962                            remaining_balance,
963                        });
964                    } else {
965                        // currently this is always the default HoldRemaining variant.
966                        // the purse holder has insufficient balance to cover the hold,
967                        // but the system will put a hold on whatever balance remains.
968                        // this is basically punitive to block an edge case resource consumption
969                        // attack whereby a malicious purse holder drains a balance to not-zero
970                        // but not-enough-to-cover-holds and then spams a bunch of transactions
971                        // knowing that they will fail due to insufficient funds, but only
972                        // after making the system do the work of processing the balance
973                        // check without penalty to themselves.
974                        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                        // There was a previous hold on this balance. We need to add the new hold to
993                        // the old one.
994                        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, // There was no previous hold.
1009                    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                    // clear holds
1046                    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                // get updated balance
1084                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                // note that hold & held in this context does not refer to remaining holds,
1101                // but rather to the requested hold amount and the resulting held amount for
1102                // this execution. as calls to this variant clears holds and does not create
1103                // new holds, hold & held are zero and no new hold address exists.
1104                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    /// Get the requested era validators.
1121    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    /// Get the requested seigniorage recipients.
1146    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                    //There is a chance that, when looking for systemic data, we could be using a
1167                    // state root hash from before the AddressableEntity
1168                    // migration boundary. In such a case, we should attempt to look up the data
1169                    // under the Account/Contract model instead; e.g. Key::Hash instead of
1170                    // Key::AddressableEntity
1171                    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    /// Gets the bids.
1184    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    /// Direct auction interaction for all variations of bid management.
1218    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        // extend named keys with era end timestamp
1253        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        // extend named keys with era id
1276        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    /// Handle refund.
1427    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                // this runtime uses the system's context
1449                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                // this runtime uses the handle payment contract's context
1465                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                // pay amount from source to target
1551                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())), // return 0 in this mode
1611                    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    /// Handle payment.
1684    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        // this runtime uses the system's context
1701
1702        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    /// Gets the execution result checksum.
1782    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    /// Gets an addressable entity.
1807    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                            // legacy account that has not been migrated
1821                            let entity = AddressableEntity::from(account);
1822                            return AddressableEntityResult::Success { entity };
1823                        }
1824                        if let StoredValue::CLValue(cl_value) = &*value {
1825                            // the corresponding entity key should be under the account's key
1826                            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                            // legacy contract that has not been migrated
1870                            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    /// Returns the system entity registry or the key for a system entity registered within it.
1905    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    /// Gets an entry point value.
1952    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                //We first check if the entry point exists as a stand alone 2.x entity
1964                match self.query(query_request) {
1965                    QueryResult::RootNotFound => EntryPointResult::RootNotFound,
1966                    QueryResult::ValueNotFound(query_result_not_found_msg) => {
1967                        //If the entry point was not found as a 2.x entity, we check if it exists
1968                        // as part of a 1.x contract
1969                        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                //TODO maybe we can have a better error type here
2006                TrackingCopyError::ValueNotFound("Entry point not found".to_string()),
2007            ),
2008        }
2009    }
2010
2011    /// Gets a contract value.
2012    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    /// Gets an entry point value.
2031    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    /// Gets total supply.
2041    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                    //There is a chance that, when looking for systemic data, we could be using a
2057                    // state root hash from before the AddressableEntity
2058                    // migration boundary. In such a case, we should attempt to look up the data
2059                    // under the Account/Contract model instead; e.g. Key::Hash instead of
2060                    // Key::AddressableEntity
2061                    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    /// Gets the current round seigniorage rate.
2074    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                    //There is a chance that, when looking for systemic data, we could be using a
2095                    // state root hash from before the AddressableEntity
2096                    // migration boundary. In such a case, we should attempt to look up the data
2097                    // under the Account/Contract model instead; e.g. Key::Hash instead of
2098                    // Key::AddressableEntity
2099                    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    /// Direct transfer.
2112    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        // On some private networks, transfers are restricted.
2194        // This means that they must either the source or target are an admin account.
2195        // This behavior is not used on public networks.
2196        if transfer_config.enforce_transfer_restrictions(&source_account_hash) {
2197            // if the source is an admin, enforce_transfer_restrictions == false
2198            // if the source is not an admin, enforce_transfer_restrictions == true,
2199            // and we must check to see if the target is an admin.
2200            // if the target is also not an admin, this transfer is not permitted.
2201            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                        // Transferring from normal account to a purse doesn't work.
2209                        return TransferResult::Failure(TransferError::RestrictedTransferAttempted);
2210                    }
2211                }
2212                None => {
2213                    // can't allow this transfer because we are not sure if the target is an admin.
2214                    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        // IMPORTANT: this runtime _must_ use the payer's context.
2244        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                // Noop
2261            }
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    /// Direct burn.
2310    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        // extend named keys with total supply
2370        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        // IMPORTANT: this runtime _must_ use the payer's context.
2403        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    /// Gets all values under a given key tag.
2428    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    /// Gets all values under a given key prefix.
2460    /// Currently, this ignores the cache and only provides values from the trie.
2461    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    /// Reads a `Trie` from the state if it is present
2487    fn trie(&self, request: TrieRequest) -> TrieResult;
2488
2489    /// Persists a trie element.
2490    fn put_trie(&self, request: PutTrieRequest) -> PutTrieResult;
2491
2492    /// Finds all the children of `trie_raw` which aren't present in the state.
2493    fn missing_children(&self, trie_raw: &[u8]) -> Result<Vec<Digest>, GlobalStateError>;
2494
2495    /// Gets the value of enable entity flag.
2496    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    // check if snapshot version flag is present
2603    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
2735/// Write multiple key/stored value pairs to the store in a single rw transaction.
2736pub 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
2765/// Commit `effects` to the store.
2766pub 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>, /* even tho E is currently always GSE, this is required to
2781                                   * satisfy the compiler */
2782{
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                // effectively a noop.
2798                continue;
2799            }
2800            (ReadResult::NotFound, TransformKindV2::Write(new_value)) => {
2801                TransformInstruction::store(new_value)
2802            }
2803            (ReadResult::NotFound, TransformKindV2::Prune(key)) => {
2804                // effectively a noop.
2805                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()); // currently this is always reflexive
2878                    }
2879                }
2880            }
2881        }
2882    }
2883
2884    txn.commit()?;
2885
2886    Ok(state_root)
2887}