casper_execution_engine/runtime/
handle_payment_internal.rs1use casper_storage::global_state::{error::Error as GlobalStateError, state::StateReader};
2use std::collections::BTreeSet;
3
4use casper_types::{
5 account::AccountHash, addressable_entity::NamedKeyAddr, system::handle_payment::Error, Account,
6 CLValue, Contract, FeeHandling, Key, Phase, RefundHandling, StoredValue, TransferredTo, URef,
7 U512,
8};
9
10use casper_storage::system::handle_payment::{
11 mint_provider::MintProvider, runtime_provider::RuntimeProvider,
12 storage_provider::StorageProvider, HandlePayment,
13};
14
15use crate::{execution::ExecError, runtime::Runtime};
16
17impl From<ExecError> for Option<Error> {
18 fn from(exec_error: ExecError) -> Self {
19 match exec_error {
20 ExecError::GasLimit => Some(Error::GasLimit),
24 _ => None,
26 }
27 }
28}
29
30impl<R> MintProvider for Runtime<'_, R>
31where
32 R: StateReader<Key, StoredValue, Error = GlobalStateError>,
33{
34 fn transfer_purse_to_account(
35 &mut self,
36 source: URef,
37 target: AccountHash,
38 amount: U512,
39 ) -> Result<TransferredTo, Error> {
40 match self.transfer_from_purse_to_account_hash(source, target, amount, None) {
41 Ok(Ok(transferred_to)) => Ok(transferred_to),
42 Ok(Err(_mint_error)) => Err(Error::Transfer),
43 Err(exec_error) => Err(<Option<Error>>::from(exec_error).unwrap_or(Error::Transfer)),
44 }
45 }
46
47 fn transfer_purse_to_purse(
48 &mut self,
49 source: URef,
50 target: URef,
51 amount: U512,
52 ) -> Result<(), Error> {
53 let contract_hash = match self.get_mint_hash() {
54 Ok(mint_hash) => mint_hash,
55 Err(exec_error) => {
56 return Err(<Option<Error>>::from(exec_error).unwrap_or(Error::Transfer));
57 }
58 };
59 match self.mint_transfer(contract_hash, None, source, target, amount, None) {
60 Ok(Ok(_)) => Ok(()),
61 Ok(Err(_mint_error)) => Err(Error::Transfer),
62 Err(exec_error) => Err(<Option<Error>>::from(exec_error).unwrap_or(Error::Transfer)),
63 }
64 }
65
66 fn available_balance(&mut self, purse: URef) -> Result<Option<U512>, Error> {
67 Runtime::available_balance(self, purse)
68 .map_err(|exec_error| <Option<Error>>::from(exec_error).unwrap_or(Error::GetBalance))
69 }
70
71 fn reduce_total_supply(&mut self, amount: U512) -> Result<(), Error> {
72 let contract_hash = match self.get_mint_hash() {
73 Ok(mint_hash) => mint_hash,
74 Err(exec_error) => {
75 return Err(<Option<Error>>::from(exec_error).unwrap_or(Error::Transfer));
76 }
77 };
78 if let Err(exec_error) = self.mint_reduce_total_supply(contract_hash, amount) {
79 Err(<Option<Error>>::from(exec_error).unwrap_or(Error::ReduceTotalSupply))
80 } else {
81 Ok(())
82 }
83 }
84}
85
86impl<R> RuntimeProvider for Runtime<'_, R>
87where
88 R: StateReader<Key, StoredValue, Error = GlobalStateError>,
89{
90 fn get_key(&mut self, name: &str) -> Option<Key> {
91 match self.context.named_keys_get(name).cloned() {
92 None => match self.context.get_context_key() {
93 Key::AddressableEntity(entity_addr) => {
94 let key = if let Ok(addr) =
95 NamedKeyAddr::new_from_string(entity_addr, name.to_string())
96 {
97 Key::NamedKey(addr)
98 } else {
99 return None;
100 };
101 if let Ok(Some(StoredValue::NamedKey(value))) = self.context.read_gs(&key) {
102 value.get_key().ok()
103 } else {
104 None
105 }
106 }
107 Key::Hash(_) => {
108 match self
109 .context
110 .read_gs_typed::<Contract>(&self.context.get_context_key())
111 {
112 Ok(contract) => contract.named_keys().get(name).copied(),
113 Err(_) => None,
114 }
115 }
116 Key::Account(_) => {
117 match self
118 .context
119 .read_gs_typed::<Account>(&self.context.get_context_key())
120 {
121 Ok(account) => account.named_keys().get(name).copied(),
122 Err(_) => None,
123 }
124 }
125 _ => None,
126 },
127 Some(key) => Some(key),
128 }
129 }
130
131 fn put_key(&mut self, name: &str, key: Key) -> Result<(), Error> {
132 self.context
133 .put_key(name.to_string(), key)
134 .map_err(|exec_error| <Option<Error>>::from(exec_error).unwrap_or(Error::PutKey))
135 }
136
137 fn remove_key(&mut self, name: &str) -> Result<(), Error> {
138 self.context
139 .remove_key(name)
140 .map_err(|exec_error| <Option<Error>>::from(exec_error).unwrap_or(Error::RemoveKey))
141 }
142
143 fn get_phase(&self) -> Phase {
144 self.context.phase()
145 }
146
147 fn get_caller(&self) -> AccountHash {
148 self.context.get_initiator()
149 }
150
151 fn refund_handling(&self) -> RefundHandling {
152 self.context.engine_config().refund_handling()
153 }
154
155 fn fee_handling(&self) -> FeeHandling {
156 self.context.engine_config().fee_handling()
157 }
158
159 fn administrative_accounts(&self) -> BTreeSet<AccountHash> {
160 self.context
161 .engine_config()
162 .administrative_accounts()
163 .clone()
164 }
165}
166
167impl<R> StorageProvider for Runtime<'_, R>
168where
169 R: StateReader<Key, StoredValue, Error = GlobalStateError>,
170{
171 fn write_balance(&mut self, purse_uref: URef, amount: U512) -> Result<(), Error> {
172 let cl_amount = CLValue::from_t(amount).map_err(|_| Error::Storage)?;
173 self.context
174 .metered_write_gs_unsafe(Key::Balance(purse_uref.addr()), cl_amount)
175 .map_err(|exec_error| <Option<Error>>::from(exec_error).unwrap_or(Error::Storage))?;
176 Ok(())
177 }
178}
179
180impl<R> HandlePayment for Runtime<'_, R> where
181 R: StateReader<Key, StoredValue, Error = GlobalStateError>
182{
183}