1use crate::args::EntrypointArgument;
2use crate::call_def::CallDef;
3use crate::casper_types::bytesrepr::{deserialize_from_slice, Bytes, FromBytes, ToBytes};
4use crate::casper_types::crypto::PublicKey;
5use crate::casper_types::{CLTyped, CLValue, BLAKE2B_DIGEST_LENGTH, U512};
6use crate::module::Revertible;
7use crate::validator::ValidatorInfo;
8pub use crate::ContractContext;
9use crate::VmError::{Serialization, TypeMismatch};
10use crate::{consts, prelude::*, utils};
11use casper_event_standard::{EventInstance, Schema, Schemas, EVENTS_SCHEMA};
12use casper_types::CLValueError;
13use rand_chacha::rand_core::{RngCore, SeedableRng};
14use rand_chacha::ChaCha8Rng;
15
16const INDEX_SIZE: usize = 4;
17const KEY_LEN: usize = 64;
18pub(crate) type StorageKey = [u8; KEY_LEN];
19
20pub trait ContractRef {
22 fn new(env: Rc<ContractEnv>, address: Address) -> Self;
24 fn address(&self) -> &Address;
26 fn with_tokens(&self, tokens: U512) -> Self;
31}
32
33#[derive(Clone)]
40pub struct ContractEnv {
41 index: u32,
42 mapping_data: Vec<u8>,
43 backend: Rc<RefCell<dyn ContractContext>>
44}
45
46impl Revertible for ContractEnv {
47 fn revert<E: Into<OdraError>>(&self, e: E) -> ! {
48 self.revert(e)
49 }
50}
51
52impl ContractEnv {
53 pub const fn new(index: u32, backend: Rc<RefCell<dyn ContractContext>>) -> Self {
55 Self {
56 index,
57 mapping_data: Vec::new(),
58 backend
59 }
60 }
61
62 pub(crate) fn current_key(&self) -> StorageKey {
64 let mut result = [0u8; KEY_LEN];
65 let mut key = Vec::with_capacity(INDEX_SIZE + self.mapping_data.len());
66 key.extend_from_slice(self.index.to_be_bytes().as_ref());
67 key.extend_from_slice(&self.mapping_data);
68 let hashed_key = self.backend.borrow().hash(key.as_slice());
69 utils::hex_to_slice(&hashed_key, &mut result);
70 result
71 }
72
73 pub(crate) fn add_to_mapping_data(&mut self, data: &[u8]) {
75 self.mapping_data.extend_from_slice(data);
76 }
77
78 pub(crate) fn child(&self, index: u8) -> Self {
80 Self {
81 index: (self.index << 4) + index as u32,
82 mapping_data: self.mapping_data.clone(),
83 backend: self.backend.clone()
84 }
85 }
86
87 pub fn get_value<T: FromBytes>(&self, key: &[u8]) -> Option<T> {
93 self.backend
94 .borrow()
95 .get_value(key)
96 .map(|bytes| deserialize_from_slice(bytes).unwrap_or_revert(self))
97 }
98
99 pub fn set_value<T: ToBytes + CLTyped>(&self, key: &[u8], value: T) {
101 let result = value.to_bytes().map_err(ExecutionError::from);
102 let bytes = result.unwrap_or_revert(self);
103 self.backend.borrow().set_value(key, bytes.into());
104 }
105
106 pub fn get_named_value<T: FromBytes + CLTyped, U: AsRef<str>>(&self, name: U) -> Option<T> {
108 let key = name.as_ref();
109 let bytes = self.backend.borrow().get_named_value(key);
110 bytes.map(|b| deserialize_from_slice(b).unwrap_or_revert(self))
111 }
112
113 pub fn set_named_value<T: CLTyped + ToBytes, U: AsRef<str>>(&self, name: U, value: T) {
115 let key = name.as_ref();
116 let cl_value = CLValue::from_t(value)
117 .map_err(|e| match e {
118 CLValueError::Serialization(_) => OdraError::VmError(Serialization),
119 CLValueError::Type(e) => OdraError::VmError(TypeMismatch {
120 found: e.found,
121 expected: e.expected
122 })
123 })
124 .unwrap_or_revert(self);
125 self.backend.borrow().set_named_value(key, cl_value);
126 }
127
128 pub fn get_dictionary_value<T: FromBytes + CLTyped, U: AsRef<str>>(
130 &self,
131 dictionary_name: U,
132 key: &[u8]
133 ) -> Option<T> {
134 let dictionary_name = dictionary_name.as_ref();
135 let bytes = self
136 .backend
137 .borrow()
138 .get_dictionary_value(dictionary_name, key);
139 bytes.map(|b| {
140 deserialize_from_slice(b)
141 .map_err(|_| ExecutionError::Formatting)
142 .unwrap_or_revert(self)
143 })
144 }
145
146 pub fn set_dictionary_value<T: CLTyped + ToBytes, U: AsRef<str>>(
148 &self,
149 dictionary_name: U,
150 key: &[u8],
151 value: T
152 ) {
153 let dictionary_name = dictionary_name.as_ref();
154 let cl_value = CLValue::from_t(value)
155 .map_err(|_| ExecutionError::Formatting)
156 .unwrap_or_revert(self);
157 self.backend
158 .borrow()
159 .set_dictionary_value(dictionary_name, key, cl_value);
160 }
161
162 pub fn remove_dictionary<U: AsRef<str>>(&self, dictionary_name: U) {
164 let dictionary_name = dictionary_name.as_ref();
165 self.backend.borrow().remove_dictionary(dictionary_name);
166 }
167
168 pub fn init_dictionary<U: AsRef<str>>(&self, dictionary_name: U) {
170 let dictionary_name = dictionary_name.as_ref();
171 self.backend.borrow().init_dictionary(dictionary_name);
172 }
173
174 pub fn caller(&self) -> Address {
176 let backend = self.backend.borrow();
177 backend.caller()
178 }
179
180 pub fn call_contract<T: FromBytes>(&self, address: Address, call: CallDef) -> T {
186 let backend = self.backend.borrow();
187 let bytes = backend.call_contract(address, call);
188 deserialize_from_slice(bytes).unwrap_or_revert(self)
189 }
190
191 pub fn self_address(&self) -> Address {
193 let backend = self.backend.borrow();
194 backend.self_address()
195 }
196
197 pub fn transfer_tokens(&self, to: &Address, amount: &U512) {
199 let backend = self.backend.borrow();
200 backend.transfer_tokens(to, amount)
201 }
202
203 pub fn get_block_time(&self) -> u64 {
205 let backend = self.backend.borrow();
206 backend.get_block_time()
207 }
208
209 pub fn get_block_time_millis(&self) -> u64 {
211 let backend = self.backend.borrow();
212 backend.get_block_time()
213 }
214
215 pub fn get_block_time_secs(&self) -> u64 {
217 let backend = self.backend.borrow();
218 backend.get_block_time().checked_div(1000).unwrap()
219 }
220
221 pub fn attached_value(&self) -> U512 {
223 let backend = self.backend.borrow();
224 backend.attached_value()
225 }
226
227 pub fn self_balance(&self) -> U512 {
229 let backend = self.backend.borrow();
230 backend.self_balance()
231 }
232
233 pub fn revert<E: Into<OdraError>>(&self, error: E) -> ! {
235 let backend = self.backend.borrow();
236 backend.revert(error.into())
237 }
238
239 pub fn emit_event<T: ToBytes + EventInstance>(&self, event: T) {
241 let backend = self.backend.borrow();
242 let result = event.to_bytes().map_err(ExecutionError::from);
243 let bytes = result.unwrap_or_revert(self);
244 backend.emit_event(&bytes.into())
245 }
246
247 pub fn emit_native_event<T: ToBytes + EventInstance>(&self, event: T) {
249 let backend = self.backend.borrow();
250 let result = event.to_bytes().map_err(ExecutionError::from);
251 let bytes = result.unwrap_or_revert(self);
252 backend.emit_native_event(&bytes.into())
253 }
254
255 pub fn verify_signature(
267 &self,
268 message: &Bytes,
269 signature: &Bytes,
270 public_key: &PublicKey
271 ) -> bool {
272 let (signature, _) = casper_types::crypto::Signature::from_bytes(signature.as_slice())
273 .unwrap_or_else(|_| self.revert(ExecutionError::CouldNotDeserializeSignature));
274 casper_types::crypto::verify(message.as_slice(), &signature, public_key).is_ok()
275 }
276
277 pub fn hash<T: AsRef<[u8]>>(&self, value: T) -> [u8; BLAKE2B_DIGEST_LENGTH] {
283 self.backend.borrow().hash(value.as_ref())
284 }
285
286 pub fn delegate(&self, validator: PublicKey, amount: U512) {
293 self.backend.borrow().delegate(validator, amount)
294 }
295
296 pub fn undelegate(&self, validator: PublicKey, amount: U512) {
303 self.backend.borrow().undelegate(validator, amount)
304 }
305
306 pub fn delegated_amount(&self, validator: PublicKey) -> U512 {
316 self.backend.borrow().delegated_amount(validator)
317 }
318
319 pub fn get_validator_info(&self, validator: PublicKey) -> Option<ValidatorInfo> {
327 self.backend.borrow().get_validator_info(validator)
328 }
329
330 pub fn pseudorandom_bytes(&self, size: usize) -> Vec<u8> {
333 let seed_bytes = self.backend.borrow().pseudorandom_bytes();
334
335 if size <= seed_bytes.len() {
336 return seed_bytes[..size].to_vec();
337 }
338
339 let mut result = seed_bytes.to_vec();
341 let mut rng = ChaCha8Rng::from_seed(seed_bytes);
342 let additional_bytes = size - result.len();
343 let mut extra = vec![0u8; additional_bytes];
344 rng.fill_bytes(&mut extra);
345 result.extend_from_slice(&extra);
346
347 result
348 }
349
350 pub fn pseudorandom_number(&self, high: U512) -> U512 {
352 let seed_bytes = self.backend.borrow().pseudorandom_bytes();
353 let mut rng = ChaCha8Rng::from_seed(seed_bytes);
354 let bits = high.bits();
355 let bytes_len = bits.div_ceil(8);
356 let max = U512::from(1u64) << bits; let limit = max - (max % high);
358 loop {
359 let mut bytes = vec![0u8; bytes_len];
360 rng.fill_bytes(&mut bytes);
361 let candidate = U512::from_big_endian(&bytes);
362
363 if candidate < limit {
364 return candidate % high;
365 }
366 }
368 }
369}
370
371pub struct ExecutionEnv {
376 env: Rc<ContractEnv>
377}
378
379impl Revertible for ExecutionEnv {
380 fn revert<E: Into<OdraError>>(&self, e: E) -> ! {
381 self.env.revert(e)
382 }
383}
384
385impl ExecutionEnv {
386 pub fn new(env: Rc<ContractEnv>) -> Self {
388 Self { env }
389 }
390
391 pub fn non_reentrant_before(&self) {
393 let status: bool = self
395 .env
396 .get_value(consts::REENTRANCY_GUARD.as_slice())
397 .unwrap_or_default();
398 if status {
399 self.env.revert(ExecutionError::ReentrantCall);
401 }
402 self.env
404 .set_value(consts::REENTRANCY_GUARD.as_slice(), true);
405 }
406
407 pub fn non_reentrant_after(&self) {
409 self.env
411 .set_value(consts::REENTRANCY_GUARD.as_slice(), false);
412 }
413
414 pub fn handle_attached_value(&self) {
416 self.env.backend.borrow().handle_attached_value();
417 }
418
419 pub fn clear_attached_value(&self) {
421 self.env.backend.borrow().clear_attached_value();
422 }
423
424 pub fn get_named_arg<T: FromBytes + EntrypointArgument>(&self, name: &str) -> T {
431 if T::is_required() {
432 let result = self.env.backend.borrow().get_named_arg_bytes(name);
433 match result {
434 Ok(bytes) => deserialize_from_slice(bytes).unwrap_or_revert(self),
435 Err(err) => self.env.revert(err)
436 }
437 } else {
438 let bytes = self.env.backend.borrow().get_opt_named_arg_bytes(name);
439 let result = bytes.map(|bytes| deserialize_from_slice(bytes).unwrap_or_revert(self));
440 T::unwrap(result, &self.env)
441 }
442 }
443
444 pub fn migrate_schemas(&self, new_schemas: BTreeMap<String, Schema>) {
446 let mut old_schemas: Schemas = self.env.get_named_value(EVENTS_SCHEMA).unwrap_or_default();
447
448 for (name, new_schema) in new_schemas.iter() {
449 match old_schemas.0.get(name) {
450 None => {
452 old_schemas.0.insert(name.clone(), new_schema.clone());
453 }
454 Some(old_schema) => {
456 if old_schema != new_schema {
457 self.env.revert(ExecutionError::SchemaMismatch);
458 }
459 }
460 }
461 }
462
463 self.env.set_named_value(EVENTS_SCHEMA, old_schemas);
465 }
466}