cfx_executor/state/state_object/
sponsor.rs1use cfx_parameters::internal_contract_addresses::SPONSOR_WHITELIST_CONTROL_CONTRACT_ADDRESS;
2use cfx_statedb::{
3 access_mode,
4 global_params::{ConvertedStoragePoints, TotalIssued},
5 Result as DbResult,
6};
7use cfx_types::{
8 maybe_address, Address, AddressSpaceUtil, AddressWithSpace, U256,
9};
10use primitives::{SponsorInfo, StorageKey};
11
12use super::{State, Substate};
13use crate::{return_if, try_loaded};
14
15lazy_static! {
16 static ref COMMISSION_PRIVILEGE_STORAGE_VALUE: U256 = U256::one();
17 pub static ref COMMISSION_PRIVILEGE_SPECIAL_KEY: Address = Address::zero();
19}
20
21impl State {
22 pub fn sponsor_info(
23 &self, address: &Address,
24 ) -> DbResult<Option<SponsorInfo>> {
25 let acc = try_loaded!(self.read_native_account_lock(address));
26 Ok(Some(acc.sponsor_info().clone()))
27 }
28
29 pub fn sponsor_for_gas(
32 &self, address: &Address,
33 ) -> DbResult<Option<Address>> {
34 let acc = try_loaded!(self.read_native_account_lock(address));
35 Ok(maybe_address(&acc.sponsor_info().sponsor_for_gas))
36 }
37
38 pub fn set_sponsor_for_gas(
39 &self, address: &Address, sponsor: &Address, sponsor_balance: &U256,
40 upper_bound: &U256,
41 ) -> DbResult<()> {
42 let sponsor_not_change =
43 *sponsor == self.sponsor_for_gas(address)?.unwrap_or_default();
44 let balance_not_change =
45 *sponsor_balance == self.sponsor_balance_for_gas(address)?;
46 return_if!(sponsor_not_change && balance_not_change);
47
48 self.write_native_account_lock(&address)?
49 .set_sponsor_for_gas(sponsor, sponsor_balance, upper_bound);
50 Ok(())
51 }
52
53 pub fn sponsor_balance_for_gas(&self, address: &Address) -> DbResult<U256> {
56 let acc = try_loaded!(self.read_native_account_lock(address));
57 Ok(acc.sponsor_info().sponsor_balance_for_gas)
58 }
59
60 pub fn add_sponsor_balance_for_gas(
61 &mut self, address: &Address, by: &U256,
62 ) -> DbResult<()> {
63 return_if!(by.is_zero());
64
65 self.write_native_account_lock(&address)?
66 .add_sponsor_balance_for_gas(by);
67 Ok(())
68 }
69
70 pub fn sub_sponsor_balance_for_gas(
71 &mut self, address: &Address, by: &U256,
72 ) -> DbResult<()> {
73 return_if!(by.is_zero());
74
75 self.write_native_account_lock(&address)?
76 .sub_sponsor_balance_for_gas(by);
77 Ok(())
78 }
79
80 pub fn sponsor_gas_bound(&self, address: &Address) -> DbResult<U256> {
83 let acc = try_loaded!(self.read_native_account_lock(address));
84 Ok(acc.sponsor_info().sponsor_gas_bound)
85 }
86
87 pub fn sponsor_for_collateral(
90 &self, address: &Address,
91 ) -> DbResult<Option<Address>> {
92 let acc = try_loaded!(self.read_native_account_lock(address));
93 Ok(maybe_address(&acc.sponsor_info().sponsor_for_collateral))
94 }
95
96 pub fn set_sponsor_for_collateral(
97 &mut self, address: &Address, sponsor: &Address,
98 sponsor_balance: &U256, is_cip107: bool,
99 ) -> DbResult<U256> {
100 let sponsor_not_change = *sponsor
101 == self.sponsor_for_collateral(address)?.unwrap_or_default();
102 let balance_not_change =
103 *sponsor_balance == self.sponsor_balance_for_collateral(address)?;
104 return_if!(sponsor_not_change && balance_not_change);
105
106 let prop = if is_cip107 {
107 self.storage_point_prop()?
108 } else {
109 U256::zero()
110 };
111
112 let converted_storage_points = self
113 .write_native_account_lock(&address)?
114 .set_sponsor_for_collateral(sponsor, sponsor_balance, prop);
115
116 *self.global_stat.val::<TotalIssued>() -= converted_storage_points;
117 *self.global_stat.val::<ConvertedStoragePoints>() +=
118 converted_storage_points;
119 Ok(converted_storage_points)
120 }
121
122 pub fn sponsor_balance_for_collateral(
125 &self, address: &Address,
126 ) -> DbResult<U256> {
127 let acc = try_loaded!(self.read_native_account_lock(address));
128 Ok(acc.sponsor_info().sponsor_balance_for_collateral)
129 }
130
131 pub fn add_sponsor_balance_for_collateral(
132 &mut self, address: &Address, by: &U256,
133 ) -> DbResult<()> {
134 return_if!(by.is_zero());
135
136 self.write_native_account_lock(&address)?
137 .add_sponsor_balance_for_collateral(by);
138 Ok(())
139 }
140
141 pub fn sub_sponsor_balance_for_collateral(
142 &mut self, address: &Address, by: &U256,
143 ) -> DbResult<()> {
144 return_if!(by.is_zero());
145
146 self.write_native_account_lock(&address)?
147 .sub_sponsor_balance_for_collateral(by);
148
149 Ok(())
150 }
151
152 pub fn check_contract_whitelist(
155 &self, contract_address: &Address, user: &Address,
156 ) -> DbResult<bool> {
157 let special_value = self.storage_at(
158 &sponsor_address(),
159 &special_sponsor_key(&contract_address),
160 )?;
161 if !special_value.is_zero() {
162 Ok(true)
163 } else {
164 self.storage_at(
165 &sponsor_address(),
166 &sponsor_key(contract_address, user),
167 )
168 .map(|x| !x.is_zero())
169 }
170 }
171
172 pub fn add_to_contract_whitelist(
173 &mut self, contract_address: Address, storage_owner: Address,
174 user: Address, substate: &mut Substate,
175 ) -> DbResult<()> {
176 info!(
177 "add_commission_privilege contract_address: {:?}, user: {:?}",
178 contract_address, user
179 );
180
181 self.set_storage(
182 &sponsor_address(),
183 sponsor_key(&contract_address, &user),
184 COMMISSION_PRIVILEGE_STORAGE_VALUE.clone(),
185 storage_owner,
186 substate,
187 )?;
188
189 Ok(())
190 }
191
192 pub fn remove_from_contract_whitelist(
193 &mut self, contract_address: Address, storage_owner: Address,
194 user: Address, substate: &mut Substate,
195 ) -> DbResult<()> {
196 self.set_storage(
197 &sponsor_address(),
198 sponsor_key(&contract_address, &user),
199 U256::zero(),
200 storage_owner,
201 substate,
202 )?;
203
204 Ok(())
205 }
206
207 pub fn record_storage_and_whitelist_entries_release(
208 &mut self, address: &Address, substate: &mut Substate, cip131: bool,
209 ) -> DbResult<()> {
210 if !cip131 {
211 storage_range_deletion_for_account(
212 self,
213 &SPONSOR_WHITELIST_CONTROL_CONTRACT_ADDRESS,
214 address.as_ref(),
215 substate,
216 )?;
217 }
218 storage_range_deletion_for_account(self, address, &vec![], substate)?;
219 Ok(())
220 }
221
222 #[cfg(test)]
223 pub fn clear_contract_whitelist(
224 &mut self, address: &Address, substate: &mut Substate,
225 ) -> DbResult<()> {
226 storage_range_deletion_for_account(
227 self,
228 &SPONSOR_WHITELIST_CONTROL_CONTRACT_ADDRESS,
229 address.as_ref(),
230 substate,
231 )?;
232 Ok(())
233 }
234}
235
236#[inline]
237fn sponsor_address() -> AddressWithSpace {
238 SPONSOR_WHITELIST_CONTROL_CONTRACT_ADDRESS.with_native_space()
239}
240
241#[inline]
242fn sponsor_key(contract: &Address, user: &Address) -> Vec<u8> {
243 let mut key = Vec::with_capacity(Address::len_bytes() * 2);
244 key.extend_from_slice(contract.as_bytes());
245 key.extend_from_slice(user.as_bytes());
246 key
247}
248
249fn special_sponsor_key(contract: &Address) -> Vec<u8> {
250 let mut key = Vec::with_capacity(Address::len_bytes() * 2);
251 key.extend_from_slice(contract.as_bytes());
252 key.extend_from_slice(COMMISSION_PRIVILEGE_SPECIAL_KEY.as_bytes());
253 key
254}
255
256fn storage_range_deletion_for_account(
257 state: &mut State, address: &Address, key_prefix: &[u8],
258 substate: &mut Substate,
259) -> DbResult<()> {
260 let delete_all = key_prefix.is_empty();
261
262 let storage_key_prefix = if delete_all {
263 StorageKey::new_storage_root_key(&address)
264 } else {
265 StorageKey::new_storage_key(&address, key_prefix)
266 }
267 .with_native_space();
268 let db_deletion_log = state
269 .db
270 .delete_all::<access_mode::Read>(storage_key_prefix, None)?
271 .into_iter();
272 state
273 .write_native_account_lock(address)?
274 .delete_storage_range(db_deletion_log, key_prefix, substate)?;
275 Ok(())
276}