sui_core/accumulators/
coin_reservations.rs1use std::sync::Arc;
5
6use moka::sync::Cache as MokaCache;
7use move_core_types::language_storage::TypeTag;
8use sui_types::{
9 base_types::{ObjectID, SequenceNumber, SuiAddress},
10 coin_reservation::{
11 CoinReservationResolver, CoinReservationResolverTrait, ParsedObjectRefWithdrawal,
12 },
13 error::{UserInputError, UserInputResult},
14 storage::ChildObjectResolver,
15 transaction::FundsWithdrawalArg,
16};
17
18pub struct CachingCoinReservationResolver {
21 inner: CoinReservationResolver,
22 cache: MokaCache<ObjectID, Result<(SuiAddress, TypeTag), UserInputError>>,
23}
24
25impl CachingCoinReservationResolver {
26 pub fn new(child_object_resolver: Arc<dyn ChildObjectResolver + Send + Sync>) -> Self {
27 Self {
28 inner: CoinReservationResolver::new(child_object_resolver),
29 cache: MokaCache::builder().max_capacity(1000).build(),
30 }
31 }
32
33 fn get_owner_and_type_cached(
34 &self,
35 object_id: ObjectID,
36 accumulator_version: Option<SequenceNumber>,
37 ) -> UserInputResult<(SuiAddress, TypeTag)> {
38 self.cache.get_with(object_id, || {
41 self.inner
42 .get_owner_and_type_for_object(object_id, accumulator_version)
43 })
44 }
45
46 pub fn resolve_funds_withdrawal(
47 &self,
48 sender: SuiAddress,
49 coin_reservation: ParsedObjectRefWithdrawal,
50 accumulator_version: Option<SequenceNumber>,
51 ) -> UserInputResult<FundsWithdrawalArg> {
52 let (owner, type_tag) = self
53 .get_owner_and_type_cached(coin_reservation.unmasked_object_id, accumulator_version)?;
54
55 if sender != owner {
56 return Err(UserInputError::InvalidWithdrawReservation {
57 error: format!(
58 "coin reservation object id {} is owned by {}, not sender {}",
59 coin_reservation.unmasked_object_id, owner, sender
60 ),
61 });
62 }
63
64 Ok(FundsWithdrawalArg::balance_from_sender(
65 coin_reservation.reservation_amount(),
66 type_tag,
67 ))
68 }
69}
70
71impl CoinReservationResolverTrait for CachingCoinReservationResolver {
72 fn resolve_funds_withdrawal(
73 &self,
74 sender: SuiAddress,
75 coin_reservation: ParsedObjectRefWithdrawal,
76 accumulator_version: Option<SequenceNumber>,
77 ) -> UserInputResult<FundsWithdrawalArg> {
78 CachingCoinReservationResolver::resolve_funds_withdrawal(
79 self,
80 sender,
81 coin_reservation,
82 accumulator_version,
83 )
84 }
85}
86
87impl CoinReservationResolverTrait for &'_ CachingCoinReservationResolver {
88 fn resolve_funds_withdrawal(
89 &self,
90 sender: SuiAddress,
91 coin_reservation: ParsedObjectRefWithdrawal,
92 accumulator_version: Option<SequenceNumber>,
93 ) -> UserInputResult<FundsWithdrawalArg> {
94 CachingCoinReservationResolver::resolve_funds_withdrawal(
95 self,
96 sender,
97 coin_reservation,
98 accumulator_version,
99 )
100 }
101}