casper_storage/system/auction/
auction_native.rs

1use crate::{
2    global_state::{error::Error as GlobalStateError, state::StateReader},
3    system::{
4        auction::{
5            providers::{AccountProvider, MintProvider, RuntimeProvider, StorageProvider},
6            Auction,
7        },
8        mint::Mint,
9        runtime_native::RuntimeNative,
10    },
11    tracking_copy::{TrackingCopyEntityExt, TrackingCopyError},
12};
13use casper_types::{
14    account::AccountHash,
15    bytesrepr::{FromBytes, ToBytes},
16    system::{
17        auction::{BidAddr, BidKind, EraInfo, Error, Unbond, UnbondEra, UnbondKind},
18        mint,
19    },
20    AccessRights, CLTyped, CLValue, Key, KeyTag, PublicKey, StoredValue, URef, U512,
21};
22use std::collections::BTreeSet;
23use tracing::{debug, error};
24
25impl<S> RuntimeProvider for RuntimeNative<S>
26where
27    S: StateReader<Key, StoredValue, Error = GlobalStateError>,
28{
29    fn get_caller(&self) -> AccountHash {
30        self.address()
31    }
32
33    fn is_allowed_session_caller(&self, account_hash: &AccountHash) -> bool {
34        if self.get_caller() == PublicKey::System.to_account_hash() {
35            return true;
36        }
37
38        account_hash == &self.address()
39    }
40
41    fn is_valid_uref(&self, uref: URef) -> bool {
42        self.access_rights().has_access_rights_to_uref(&uref)
43    }
44
45    fn named_keys_get(&self, name: &str) -> Option<Key> {
46        self.named_keys().get(name).cloned()
47    }
48
49    fn get_keys(&mut self, key_tag: &KeyTag) -> Result<BTreeSet<Key>, Error> {
50        self.tracking_copy()
51            .borrow_mut()
52            .get_keys(key_tag)
53            .map_err(|error| {
54                error!(%key_tag, "RuntimeProvider::get_keys: {:?}", error);
55                Error::Storage
56            })
57    }
58
59    fn get_keys_by_prefix(&mut self, prefix: &[u8]) -> Result<Vec<Key>, Error> {
60        self.tracking_copy()
61            .borrow_mut()
62            .reader()
63            .keys_with_prefix(prefix)
64            .map_err(|error| {
65                error!("RuntimeProvider::get_keys_by_prefix: {:?}", error);
66                Error::Storage
67            })
68    }
69
70    fn delegator_count(&mut self, bid_addr: &BidAddr) -> Result<usize, Error> {
71        let delegated_accounts = {
72            let prefix = bid_addr.delegated_account_prefix()?;
73            let keys = self.get_keys_by_prefix(&prefix).map_err(|err| {
74                error!("RuntimeProvider::delegator_count {:?}", err);
75                Error::Storage
76            })?;
77            keys.len()
78        };
79        let delegated_purses = {
80            let prefix = bid_addr.delegated_purse_prefix()?;
81            let keys = self.get_keys_by_prefix(&prefix).map_err(|err| {
82                error!("RuntimeProvider::delegator_count {:?}", err);
83                Error::Storage
84            })?;
85            keys.len()
86        };
87        Ok(delegated_accounts.saturating_add(delegated_purses))
88    }
89
90    fn reservation_count(&mut self, bid_addr: &BidAddr) -> Result<usize, Error> {
91        let reserved_accounts = {
92            let reservation_prefix = bid_addr.reserved_account_prefix()?;
93            let reservation_keys = self
94                .get_keys_by_prefix(&reservation_prefix)
95                .map_err(|err| {
96                    error!("RuntimeProvider::reservation_count {:?}", err);
97                    Error::Storage
98                })?;
99            reservation_keys.len()
100        };
101        let reserved_purses = {
102            let reservation_prefix = bid_addr.reserved_purse_prefix()?;
103            let reservation_keys = self
104                .get_keys_by_prefix(&reservation_prefix)
105                .map_err(|err| {
106                    error!("RuntimeProvider::reservation_count {:?}", err);
107                    Error::Storage
108                })?;
109            reservation_keys.len()
110        };
111        Ok(reserved_accounts.saturating_add(reserved_purses))
112    }
113
114    fn used_reservation_count(&mut self, bid_addr: &BidAddr) -> Result<usize, Error> {
115        let reservation_account_prefix = bid_addr.reserved_account_prefix()?;
116        let reservation_purse_prefix = bid_addr.reserved_purse_prefix()?;
117
118        let mut reservation_keys = self
119            .get_keys_by_prefix(&reservation_account_prefix)
120            .map_err(|exec_error| {
121                error!("RuntimeProvider::reservation_count {:?}", exec_error);
122                <Option<Error>>::from(exec_error).unwrap_or(Error::Storage)
123            })?;
124
125        let more = self
126            .get_keys_by_prefix(&reservation_purse_prefix)
127            .map_err(|exec_error| {
128                error!("RuntimeProvider::reservation_count {:?}", exec_error);
129                <Option<Error>>::from(exec_error).unwrap_or(Error::Storage)
130            })?;
131
132        reservation_keys.extend(more);
133
134        let mut used = 0;
135        for reservation_key in reservation_keys {
136            if let Key::BidAddr(BidAddr::ReservedDelegationAccount {
137                validator,
138                delegator,
139            }) = reservation_key
140            {
141                let key_to_check = Key::BidAddr(BidAddr::DelegatedAccount {
142                    validator,
143                    delegator,
144                });
145                if let Ok(Some(_)) = self.read_bid(&key_to_check) {
146                    used += 1;
147                }
148            }
149            if let Key::BidAddr(BidAddr::ReservedDelegationPurse {
150                validator,
151                delegator,
152            }) = reservation_key
153            {
154                let key_to_check = Key::BidAddr(BidAddr::DelegatedPurse {
155                    validator,
156                    delegator,
157                });
158                if let Ok(Some(_)) = self.read_bid(&key_to_check) {
159                    used += 1;
160                }
161            }
162        }
163        Ok(used)
164    }
165
166    fn vesting_schedule_period_millis(&self) -> u64 {
167        self.vesting_schedule_period_millis()
168    }
169
170    fn allow_auction_bids(&self) -> bool {
171        self.allow_auction_bids()
172    }
173
174    fn should_compute_rewards(&self) -> bool {
175        self.compute_rewards()
176    }
177}
178
179impl<S> StorageProvider for RuntimeNative<S>
180where
181    S: StateReader<Key, StoredValue, Error = GlobalStateError>,
182{
183    fn read<T: FromBytes + CLTyped>(&mut self, uref: URef) -> Result<Option<T>, Error> {
184        // check access rights on uref
185        if !self.access_rights().has_access_rights_to_uref(&uref) {
186            return Err(Error::ForgedReference);
187        }
188        let key = &Key::URef(uref);
189        let stored_value = match self.tracking_copy().borrow_mut().read(key) {
190            Ok(Some(stored_value)) => stored_value,
191            Ok(None) => return Ok(None),
192            Err(_) => return Err(Error::Storage),
193        };
194        // by convention, we only store CLValues under Key::URef
195        if let StoredValue::CLValue(value) = stored_value {
196            // Only CLTyped instances should be stored as a CLValue.
197            let value = CLValue::into_t(value).map_err(|_| Error::CLValue)?;
198            Ok(Some(value))
199        } else {
200            Err(Error::CLValue)
201        }
202    }
203
204    fn write<T: ToBytes + CLTyped>(&mut self, uref: URef, value: T) -> Result<(), Error> {
205        let cl_value = CLValue::from_t(value).map_err(|_| Error::CLValue)?;
206        // is the uref writeable?
207        if !uref.is_writeable() {
208            error!("uref not writeable {}", uref);
209            return Err(Error::Storage);
210        }
211        // check access rights on uref
212        if !self.access_rights().has_access_rights_to_uref(&uref) {
213            return Err(Error::ForgedReference);
214        }
215        self.tracking_copy()
216            .borrow_mut()
217            .write(Key::URef(uref), StoredValue::CLValue(cl_value));
218        Ok(())
219    }
220
221    fn read_bid(&mut self, key: &Key) -> Result<Option<BidKind>, Error> {
222        match self.tracking_copy().borrow_mut().read(key) {
223            Ok(Some(StoredValue::BidKind(bid_kind))) => Ok(Some(bid_kind)),
224            Ok(Some(_)) => {
225                error!("StorageProvider::read_bid: unexpected StoredValue variant");
226                Err(Error::Storage)
227            }
228            Ok(None) => Ok(None),
229            Err(TrackingCopyError::BytesRepr(_)) => Err(Error::Serialization),
230            Err(err) => {
231                error!("StorageProvider::read_bid: {:?}", err);
232                Err(Error::Storage)
233            }
234        }
235    }
236
237    fn write_bid(&mut self, key: Key, bid_kind: BidKind) -> Result<(), Error> {
238        let stored_value = StoredValue::BidKind(bid_kind);
239
240        // Charge for amount as measured by serialized length
241        // let bytes_count = stored_value.serialized_length();
242        // self.charge_gas_storage(bytes_count)?;
243
244        self.tracking_copy().borrow_mut().write(key, stored_value);
245        Ok(())
246    }
247
248    fn read_unbond(&mut self, bid_addr: BidAddr) -> Result<Option<Unbond>, Error> {
249        match self
250            .tracking_copy()
251            .borrow_mut()
252            .read(&Key::BidAddr(bid_addr))
253        {
254            Ok(Some(StoredValue::BidKind(BidKind::Unbond(unbond)))) => Ok(Some(*unbond)),
255            Ok(Some(_)) => {
256                error!("StorageProvider::read_unbonds: unexpected StoredValue variant");
257                Err(Error::Storage)
258            }
259            Ok(None) => Ok(None),
260            Err(TrackingCopyError::BytesRepr(_)) => Err(Error::Serialization),
261            Err(err) => {
262                error!("StorageProvider::read_unbonds: {:?}", err);
263                Err(Error::Storage)
264            }
265        }
266    }
267
268    fn write_unbond(&mut self, bid_addr: BidAddr, unbond: Option<Unbond>) -> Result<(), Error> {
269        let unbond_key = Key::BidAddr(bid_addr);
270        match unbond {
271            Some(unbond) => {
272                self.tracking_copy().borrow_mut().write(
273                    unbond_key,
274                    StoredValue::BidKind(BidKind::Unbond(Box::new(unbond))),
275                );
276            }
277            None => {
278                self.tracking_copy().borrow_mut().prune(unbond_key);
279            }
280        }
281        Ok(())
282    }
283
284    fn record_era_info(&mut self, era_info: EraInfo) -> Result<(), Error> {
285        if self.get_caller() != PublicKey::System.to_account_hash() {
286            return Err(Error::InvalidContext);
287        }
288        self.tracking_copy()
289            .borrow_mut()
290            .write(Key::EraSummary, StoredValue::EraInfo(era_info));
291        Ok(())
292    }
293
294    fn prune_bid(&mut self, bid_addr: BidAddr) {
295        self.tracking_copy().borrow_mut().prune(bid_addr.into());
296    }
297}
298
299impl<S> MintProvider for RuntimeNative<S>
300where
301    S: StateReader<Key, StoredValue, Error = GlobalStateError>,
302{
303    fn unbond(&mut self, unbond_kind: &UnbondKind, unbond_era: &UnbondEra) -> Result<(), Error> {
304        let (purse, maybe_account_hash) = match unbond_kind {
305            UnbondKind::Validator(pk) | UnbondKind::DelegatedPublicKey(pk) => {
306                let account_hash = pk.to_account_hash();
307                // Do a migration if the account hasn't been migrated yet. This is just a read if it
308                // has been migrated already.
309                self.tracking_copy()
310                    .borrow_mut()
311                    .migrate_account(account_hash, self.protocol_version())
312                    .map_err(|error| {
313                        error!(
314                            "MintProvider::unbond: couldn't migrate account: {:?}",
315                            error
316                        );
317                        Error::Storage
318                    })?;
319
320                let maybe_value = self
321                    .tracking_copy()
322                    .borrow_mut()
323                    .read(&Key::Account(account_hash))
324                    .map_err(|error| {
325                        error!("MintProvider::unbond: {:?}", error);
326                        Error::Storage
327                    })?;
328
329                match maybe_value {
330                    Some(StoredValue::Account(account)) => {
331                        (account.main_purse(), Some(account_hash))
332                    }
333                    Some(StoredValue::CLValue(cl_value)) => {
334                        let entity_key: Key = cl_value.into_t().map_err(|_| Error::CLValue)?;
335                        let maybe_value = self
336                            .tracking_copy()
337                            .borrow_mut()
338                            .read(&entity_key)
339                            .map_err(|error| {
340                                error!("MintProvider::unbond: {:?}", error);
341                                Error::Storage
342                            })?;
343                        match maybe_value {
344                            Some(StoredValue::AddressableEntity(entity)) => {
345                                (entity.main_purse(), Some(account_hash))
346                            }
347                            Some(_cl_value) => return Err(Error::CLValue),
348                            None => return Err(Error::InvalidPublicKey),
349                        }
350                    }
351                    Some(_cl_value) => return Err(Error::CLValue),
352                    None => return Err(Error::InvalidPublicKey),
353                }
354            }
355            UnbondKind::DelegatedPurse(addr) => {
356                let purse = URef::new(*addr, AccessRights::READ_ADD_WRITE);
357                match self.balance(purse) {
358                    Ok(Some(_)) => (purse, None),
359                    Ok(None) => return Err(Error::MissingPurse),
360                    Err(err) => {
361                        error!("MintProvider::unbond: {:?}", err);
362                        return Err(Error::Unbonding);
363                    }
364                }
365            }
366        };
367
368        self.mint_transfer_direct(
369            maybe_account_hash,
370            *unbond_era.bonding_purse(),
371            purse,
372            *unbond_era.amount(),
373            None,
374        )
375        .map_err(|_| Error::Transfer)?
376        .map_err(|_| Error::Transfer)?;
377        Ok(())
378    }
379
380    fn mint_transfer_direct(
381        &mut self,
382        to: Option<AccountHash>,
383        source: URef,
384        target: URef,
385        amount: U512,
386        id: Option<u64>,
387    ) -> Result<Result<(), mint::Error>, Error> {
388        let addr = if let Some(uref) = self.runtime_footprint().main_purse() {
389            uref.addr()
390        } else {
391            return Err(Error::InvalidContext);
392        };
393        if !(addr == source.addr() || self.get_caller() == PublicKey::System.to_account_hash()) {
394            return Err(Error::InvalidCaller);
395        }
396
397        // let gas_counter = self.gas_counter();
398        self.extend_access_rights(&[source, target.into_add()]);
399
400        match self.transfer(to, source, target, amount, id) {
401            Ok(ret) => {
402                // self.set_gas_counter(gas_counter);
403                Ok(Ok(ret))
404            }
405            Err(err) => {
406                error!("{}", err);
407                Err(Error::Transfer)
408            }
409        }
410    }
411
412    fn mint_into_existing_purse(
413        &mut self,
414        amount: U512,
415        existing_purse: URef,
416    ) -> Result<(), Error> {
417        if self.get_caller() != PublicKey::System.to_account_hash() {
418            return Err(Error::InvalidCaller);
419        }
420
421        match <Self as Mint>::mint_into_existing_purse(self, existing_purse, amount) {
422            Ok(ret) => Ok(ret),
423            Err(err) => {
424                error!("{}", err);
425                Err(Error::MintError)
426            }
427        }
428    }
429
430    fn create_purse(&mut self) -> Result<URef, Error> {
431        let initial_balance = U512::zero();
432        match <Self as Mint>::mint(self, initial_balance) {
433            Ok(ret) => Ok(ret),
434            Err(err) => {
435                error!("{}", err);
436                Err(Error::CreatePurseFailed)
437            }
438        }
439    }
440
441    fn available_balance(&mut self, purse: URef) -> Result<Option<U512>, Error> {
442        match <Self as Mint>::balance(self, purse) {
443            Ok(ret) => Ok(ret),
444            Err(err) => {
445                error!("{}", err);
446                Err(Error::GetBalance)
447            }
448        }
449    }
450
451    fn read_base_round_reward(&mut self) -> Result<U512, Error> {
452        match <Self as Mint>::read_base_round_reward(self) {
453            Ok(ret) => Ok(ret),
454            Err(err) => {
455                error!("{}", err);
456                Err(Error::MissingValue)
457            }
458        }
459    }
460
461    fn mint(&mut self, amount: U512) -> Result<URef, Error> {
462        match <Self as Mint>::mint(self, amount) {
463            Ok(ret) => Ok(ret),
464            Err(err) => {
465                error!("{}", err);
466                Err(Error::MintReward)
467            }
468        }
469    }
470
471    fn reduce_total_supply(&mut self, amount: U512) -> Result<(), Error> {
472        match <Self as Mint>::reduce_total_supply(self, amount) {
473            Ok(ret) => Ok(ret),
474            Err(err) => {
475                error!("{}", err);
476                Err(Error::MintReduceTotalSupply)
477            }
478        }
479    }
480}
481
482impl<S> AccountProvider for RuntimeNative<S>
483where
484    S: StateReader<Key, StoredValue, Error = GlobalStateError>,
485{
486    fn get_main_purse(&self) -> Result<URef, Error> {
487        // NOTE: this is used by the system and is not (and should not be made to be) accessible
488        // from userland.
489        match self.runtime_footprint().main_purse() {
490            None => {
491                debug!("runtime_native attempt to access non-existent main purse");
492                Err(Error::InvalidContext)
493            }
494            Some(purse) => Ok(purse),
495        }
496    }
497
498    /// Set main purse.
499    fn set_main_purse(&mut self, purse: URef) {
500        self.runtime_footprint_mut().set_main_purse(purse);
501    }
502}
503
504impl<S> Auction for RuntimeNative<S> where S: StateReader<Key, StoredValue, Error = GlobalStateError>
505{}