casper_execution_engine/runtime/
mint_internal.rs1use tracing::error;
2
3use casper_storage::{
4 global_state::{error::Error as GlobalStateError, state::StateReader},
5 system::{
6 error::ProviderError,
7 mint::{
8 runtime_provider::RuntimeProvider, storage_provider::StorageProvider,
9 system_provider::SystemProvider, Mint,
10 },
11 },
12};
13use casper_types::{
14 account::AccountHash,
15 bytesrepr::{FromBytes, ToBytes},
16 system::{mint::Error, Caller},
17 CLTyped, CLValue, Key, Phase, RuntimeFootprint, StoredValue, SystemHashRegistry, URef, U512,
18};
19
20use super::Runtime;
21use crate::execution::ExecError;
22
23impl From<ExecError> for Option<Error> {
24 fn from(exec_error: ExecError) -> Self {
25 match exec_error {
26 ExecError::GasLimit => Some(Error::GasLimit),
29 ExecError::ForgedReference(_) => Some(Error::ForgedReference),
30 _ => None,
32 }
33 }
34}
35
36impl<R> RuntimeProvider for Runtime<'_, R>
37where
38 R: StateReader<Key, StoredValue, Error = GlobalStateError>,
39{
40 fn get_caller(&self) -> AccountHash {
41 self.context.get_initiator()
42 }
43
44 fn get_immediate_caller(&self) -> Option<Caller> {
45 Runtime::<'_, R>::get_immediate_caller(self).cloned()
46 }
47
48 fn is_called_from_standard_payment(&self) -> bool {
49 self.context.phase() == Phase::Payment && self.module.is_none()
50 }
51
52 fn get_system_entity_registry(&self) -> Result<SystemHashRegistry, ProviderError> {
53 self.context.system_entity_registry().map_err(|err| {
54 error!(%err, "unable to obtain system entity registry during transfer");
55 ProviderError::SystemEntityRegistry
56 })
57 }
58
59 fn runtime_footprint_by_account_hash(
60 &mut self,
61 account_hash: AccountHash,
62 ) -> Result<Option<RuntimeFootprint>, ProviderError> {
63 self.context
64 .runtime_footprint_by_account_hash(account_hash)
65 .map_err(|err| {
66 error!(%err, "error getting runtime footprint by account hash");
67 ProviderError::AccountHash(account_hash)
68 })
69 }
70
71 fn get_phase(&self) -> Phase {
72 self.context.phase()
73 }
74
75 fn get_key(&self, name: &str) -> Option<Key> {
76 self.context.named_keys_get(name).cloned()
77 }
78
79 fn get_approved_spending_limit(&self) -> U512 {
80 self.context.remaining_spending_limit()
81 }
82
83 fn sub_approved_spending_limit(&mut self, transferred: U512) {
84 self.context.subtract_amount_spent(transferred);
87 }
88
89 fn get_main_purse(&self) -> Option<URef> {
90 self.context.runtime_footprint().borrow().main_purse()
91 }
92
93 fn is_administrator(&self, account_hash: &AccountHash) -> bool {
94 self.context.engine_config().is_administrator(account_hash)
95 }
96
97 fn allow_unrestricted_transfers(&self) -> bool {
98 self.context.engine_config().allow_unrestricted_transfers()
99 }
100
101 fn is_valid_uref(&self, uref: &URef) -> bool {
103 self.context.access_rights().has_access_rights_to_uref(uref)
104 }
105}
106
107impl<R> StorageProvider for Runtime<'_, R>
108where
109 R: StateReader<Key, StoredValue, Error = GlobalStateError>,
110{
111 fn new_uref<T: CLTyped + ToBytes>(&mut self, init: T) -> Result<URef, Error> {
112 let cl_value: CLValue = CLValue::from_t(init).map_err(|_| Error::CLValue)?;
113 self.context
114 .new_uref(StoredValue::CLValue(cl_value))
115 .map_err(|exec_error| <Option<Error>>::from(exec_error).unwrap_or(Error::NewURef))
116 }
117
118 fn read<T: CLTyped + FromBytes>(&mut self, uref: URef) -> Result<Option<T>, Error> {
119 let maybe_value = self
120 .context
121 .read_gs(&Key::URef(uref))
122 .map_err(|exec_error| <Option<Error>>::from(exec_error).unwrap_or(Error::Storage))?;
123 match maybe_value {
124 Some(StoredValue::CLValue(value)) => {
125 let value = CLValue::into_t(value).map_err(|_| Error::CLValue)?;
126 Ok(Some(value))
127 }
128 Some(_cl_value) => Err(Error::CLValue),
129 None => Ok(None),
130 }
131 }
132
133 fn write_amount(&mut self, uref: URef, amount: U512) -> Result<(), Error> {
134 let cl_value = CLValue::from_t(amount).map_err(|_| Error::CLValue)?;
135 self.context
136 .metered_write_gs(Key::URef(uref), StoredValue::CLValue(cl_value))
137 .map_err(|exec_error| <Option<Error>>::from(exec_error).unwrap_or(Error::Storage))
138 }
139
140 fn add<T: CLTyped + ToBytes>(&mut self, uref: URef, value: T) -> Result<(), Error> {
141 let cl_value = CLValue::from_t(value).map_err(|_| Error::CLValue)?;
142 self.context
143 .metered_add_gs(uref, cl_value)
144 .map_err(|exec_error| <Option<Error>>::from(exec_error).unwrap_or(Error::Storage))
145 }
146
147 fn total_balance(&mut self, purse: URef) -> Result<U512, Error> {
148 Runtime::total_balance(self, purse)
149 .map_err(|exec_error| <Option<Error>>::from(exec_error).unwrap_or(Error::Storage))
150 }
151
152 fn available_balance(&mut self, purse: URef) -> Result<Option<U512>, Error> {
153 Runtime::available_balance(self, purse)
154 .map_err(|exec_error| <Option<Error>>::from(exec_error).unwrap_or(Error::Storage))
155 }
156
157 fn write_balance(&mut self, uref: URef, balance: U512) -> Result<(), Error> {
158 let cl_value = CLValue::from_t(balance).map_err(|_| Error::CLValue)?;
159 self.context
160 .metered_write_gs_unsafe(Key::Balance(uref.addr()), StoredValue::CLValue(cl_value))
161 .map_err(|exec_error| <Option<Error>>::from(exec_error).unwrap_or(Error::Storage))
162 }
163
164 fn add_balance(&mut self, uref: URef, value: U512) -> Result<(), Error> {
165 let cl_value = CLValue::from_t(value).map_err(|_| Error::CLValue)?;
166 self.context
167 .metered_add_gs_unsafe(Key::Balance(uref.addr()), StoredValue::CLValue(cl_value))
168 .map_err(|exec_error| <Option<Error>>::from(exec_error).unwrap_or(Error::Storage))
169 }
170}
171
172impl<R> SystemProvider for Runtime<'_, R>
173where
174 R: StateReader<Key, StoredValue, Error = GlobalStateError>,
175{
176 fn record_transfer(
177 &mut self,
178 maybe_to: Option<AccountHash>,
179 source: URef,
180 target: URef,
181 amount: U512,
182 id: Option<u64>,
183 ) -> Result<(), Error> {
184 let result = Runtime::record_transfer(self, maybe_to, source, target, amount, id);
185 result.map_err(|exec_error| {
186 <Option<Error>>::from(exec_error).unwrap_or(Error::RecordTransferFailure)
187 })
188 }
189}
190
191impl<R> Mint for Runtime<'_, R>
192where
193 R: StateReader<Key, StoredValue, Error = GlobalStateError>,
194{
195 fn purse_exists(&mut self, uref: URef) -> Result<bool, Error> {
196 let maybe_value = self
197 .context
198 .read_gs(&Key::Balance(uref.addr()))
199 .map_err(|exec_error| <Option<Error>>::from(exec_error).unwrap_or(Error::Storage))?;
200 match maybe_value {
201 Some(StoredValue::CLValue(value)) => Ok(*value.cl_type() == U512::cl_type()),
202 Some(_non_cl_value) => Err(Error::CLValue),
203 None => Ok(false),
204 }
205 }
206}