1use std::rc::Rc;
2
3use crate::host_object::{MemHostObjectType, MuxedScAddress};
4use crate::{
5 budget::{AsBudget, DepthLimiter},
6 crypto::metered_scalar::MeteredScalar,
7 err,
8 host::metered_clone::{
9 charge_shallow_copy, MeteredAlloc, MeteredClone, MeteredContainer, MeteredIterator,
10 },
11 host_object::{HostMap, HostObject, HostVec},
12 num::{i256_from_pieces, i256_into_pieces, u256_from_pieces, u256_into_pieces},
13 xdr::{
14 self, int128_helpers, AccountId, ContractCostType, ContractDataDurability, Hash,
15 Int128Parts, Int256Parts, LedgerKey, LedgerKeyContractData, ScAddress, ScBytes,
16 ScErrorCode, ScErrorType, ScMap, ScMapEntry, ScSymbol, ScVal, ScVec, UInt128Parts,
17 UInt256Parts, Uint256, VecM,
18 },
19 AddressObject, BytesObject, Convert, Host, HostError, Object, ScValObjRef, ScValObject, Symbol,
20 SymbolObject, TryFromVal, TryIntoVal, U256Val, U32Val, Val, VecObject,
21};
22
23use super::ErrorHandler;
24
25impl Host {
26 pub(crate) fn usize_to_u32(&self, u: usize) -> Result<u32, HostError> {
28 match u32::try_from(u) {
29 Ok(v) => Ok(v),
30 Err(_) => Err(self.err(
31 ScErrorType::Value,
32 ScErrorCode::ArithDomain,
33 "provided usize does not fit in u32",
34 &[],
35 )),
36 }
37 }
38
39 pub(crate) fn usize_to_u32val(&self, u: usize) -> Result<U32Val, HostError> {
41 self.usize_to_u32(u).map(|v| v.into())
42 }
43
44 pub(crate) fn u256_from_account(&self, account_id: &AccountId) -> Result<Uint256, HostError> {
45 let crate::xdr::PublicKey::PublicKeyTypeEd25519(ed25519) =
46 account_id.metered_clone(self)?.0;
47 Ok(ed25519)
48 }
49
50 pub(crate) fn u8_from_u32val_input(
52 &self,
53 name: &'static str,
54 r: U32Val,
55 ) -> Result<u8, HostError> {
56 let u: u32 = r.into();
57 match u8::try_from(u) {
58 Ok(v) => Ok(v),
59 Err(_) => Err(self.err(
60 ScErrorType::Value,
61 ScErrorCode::ArithDomain,
62 "expecting U32Val less than 256",
63 &[r.to_val(), name.try_into_val(self)?],
64 )),
65 }
66 }
67
68 pub(crate) fn hash_from_bytesobj_input(
69 &self,
70 name: &'static str,
71 hash: BytesObject,
72 ) -> Result<Hash, HostError> {
73 static_assertions::assert_eq_size!([u8; 32], Hash);
74 self.fixed_length_bytes_from_bytesobj_input::<Hash, 32>(name, hash)
75 }
76
77 pub(crate) fn u256_from_bytesobj_input(
78 &self,
79 name: &'static str,
80 u256: BytesObject,
81 ) -> Result<Uint256, HostError> {
82 static_assertions::assert_eq_size!([u8; 32], Uint256);
83 self.fixed_length_bytes_from_bytesobj_input::<Uint256, 32>(name, u256)
84 }
85
86 pub(crate) fn fixed_length_bytes_from_slice<T, const N: usize>(
87 &self,
88 name: &'static str,
89 bytes_arr: &[u8],
90 ) -> Result<T, HostError>
91 where
92 T: From<[u8; N]>,
93 {
94 match <[u8; N]>::try_from(bytes_arr) {
95 Ok(arr) => {
96 self.charge_budget(ContractCostType::MemCpy, Some(N as u64))?;
97 Ok(arr.into())
98 }
99 Err(_) => Err(err!(
100 self,
101 (ScErrorType::Object, ScErrorCode::UnexpectedSize),
102 "expected fixed-length bytes slice, got slice with different size",
103 name,
104 N,
105 bytes_arr.len()
106 )),
107 }
108 }
109
110 pub(crate) fn fixed_length_bytes_from_bytesobj_input<T, const N: usize>(
111 &self,
112 name: &'static str,
113 obj: BytesObject,
114 ) -> Result<T, HostError>
115 where
116 T: From<[u8; N]>,
117 {
118 self.visit_obj(obj, |bytes: &ScBytes| {
119 self.fixed_length_bytes_from_slice(name, bytes.as_slice())
120 })
121 }
122
123 pub(crate) fn account_id_from_bytesobj(&self, k: BytesObject) -> Result<AccountId, HostError> {
124 self.visit_obj(k, |bytes: &ScBytes| {
125 Ok(AccountId(xdr::PublicKey::PublicKeyTypeEd25519(
126 self.fixed_length_bytes_from_slice("account_id", bytes.as_slice())?,
127 )))
128 })
129 }
130
131 pub(crate) fn storage_key_for_address(
132 &self,
133 contract: ScAddress,
134 key: ScVal,
135 durability: ContractDataDurability,
136 ) -> Result<Rc<LedgerKey>, HostError> {
137 Rc::metered_new(
138 LedgerKey::ContractData(LedgerKeyContractData {
139 contract,
140 key,
141 durability,
142 }),
143 self,
144 )
145 }
146
147 pub(crate) fn storage_key_from_scval(
148 &self,
149 key: ScVal,
150 durability: ContractDataDurability,
151 ) -> Result<Rc<LedgerKey>, HostError> {
152 let contract_id = self.get_current_contract_id_internal()?;
153 self.storage_key_for_address(ScAddress::Contract(contract_id), key, durability)
154 }
155
156 pub(crate) fn storage_key_from_val(
160 &self,
161 k: Val,
162 durability: ContractDataDurability,
163 ) -> Result<Rc<LedgerKey>, HostError> {
164 let key_scval = self.from_host_val_for_storage(k)?;
165 self.storage_key_from_scval(key_scval, durability)
166 }
167
168 pub(crate) fn u64_from_binary_search_result(
177 &self,
178 res: Result<usize, usize>,
179 ) -> Result<u64, HostError> {
180 match res {
181 Ok(u) => {
182 let v = self.usize_to_u32(u)?;
183 Ok(u64::from(v) | (1_u64 << u32::BITS))
184 }
185 Err(u) => {
186 let v = self.usize_to_u32(u)?;
187 Ok(u64::from(v))
188 }
189 }
190 }
191
192 pub(crate) fn call_args_from_obj(&self, args: VecObject) -> Result<Vec<Val>, HostError> {
193 self.visit_obj(args, |hv: &HostVec| hv.to_vec(self.as_budget()))
194 }
195
196 pub(crate) fn vecobject_to_scval_vec(&self, args: VecObject) -> Result<VecM<ScVal>, HostError> {
198 self.visit_obj(args, |hv: &HostVec| self.vals_to_scval_vec(hv.as_slice()))
199 }
200
201 pub(crate) fn vals_to_scval_vec(&self, vals: &[Val]) -> Result<VecM<ScVal>, HostError> {
202 vals.iter()
203 .map(|v| self.from_host_val(*v))
204 .metered_collect::<Result<Vec<ScVal>, HostError>>(self)??
205 .try_into()
206 .map_err(|_| {
207 err!(
208 self,
209 (ScErrorType::Object, ScErrorCode::ExceededLimit),
210 "vector size limit exceeded",
211 vals.len()
212 )
213 })
214 }
215
216 pub(crate) fn scvals_to_val_vec(&self, scvals: &[ScVal]) -> Result<Vec<Val>, HostError> {
217 scvals
218 .iter()
219 .map(|scv| self.to_host_val(scv))
220 .metered_collect::<Result<Vec<Val>, HostError>>(self)?
221 }
222
223 pub(crate) fn bytesobj_from_internal_contract_id(
224 &self,
225 ) -> Result<Option<BytesObject>, HostError> {
226 if let Some(id) = self.get_current_contract_id_opt_internal()? {
227 let obj = self.add_host_object::<ScBytes>(
228 self.metered_slice_to_vec(id.0.as_slice())?.try_into()?,
229 )?;
230 Ok(Some(obj))
231 } else {
232 Ok(None)
233 }
234 }
235
236 pub(crate) fn scbytes_from_vec(&self, v: Vec<u8>) -> Result<ScBytes, HostError> {
237 Ok(ScBytes(v.try_into()?))
238 }
239
240 pub(crate) fn metered_slice_to_vec(&self, s: &[u8]) -> Result<Vec<u8>, HostError> {
241 Vec::<u8>::charge_bulk_init_cpy(s.len() as u64, self)?;
242 Ok(s.to_vec())
243 }
244
245 pub(crate) fn scbytes_from_slice(&self, s: &[u8]) -> Result<ScBytes, HostError> {
247 self.scbytes_from_vec(self.metered_slice_to_vec(s)?)
248 }
249
250 pub(crate) fn scbytes_from_hash(&self, hash: &Hash) -> Result<ScBytes, HostError> {
251 self.scbytes_from_slice(hash.as_slice())
252 }
253
254 pub fn scaddress_from_address(&self, address: AddressObject) -> Result<ScAddress, HostError> {
255 self.visit_obj(address, |addr: &ScAddress| addr.metered_clone(self))
256 }
257
258 pub(crate) fn scsymbol_from_symbol(&self, symbol: Symbol) -> Result<ScSymbol, HostError> {
259 if let Ok(sobj) = SymbolObject::try_from(symbol) {
260 self.visit_obj(sobj, |sym: &ScSymbol| sym.metered_clone(self))
261 } else {
262 self.map_err(ScSymbol::try_from_val(self, &symbol))
263 }
264 }
265
266 pub(crate) fn host_map_to_scmap(&self, map: &HostMap) -> Result<ScMap, HostError> {
267 let mut mv = Vec::<ScMapEntry>::with_metered_capacity(map.len(), self)?;
268 for (k, v) in map.iter(self)? {
269 let key = self.from_host_val(*k)?;
270 let val = self.from_host_val(*v)?;
271 mv.push(ScMapEntry { key, val });
272 }
273 Ok(ScMap(self.map_err(mv.try_into())?))
274 }
275
276 pub(crate) fn instance_storage_map_to_scmap(&self, map: &HostMap) -> Result<ScMap, HostError> {
279 let mut mv = Vec::<ScMapEntry>::with_metered_capacity(map.len(), self)?;
280 for (k, v) in map.iter(self)? {
281 let key = self.from_host_val_for_storage(*k)?;
285 let val = self.from_host_val(*v)?;
286 mv.push(ScMapEntry { key, val });
287 }
288 Ok(ScMap(self.map_err(mv.try_into())?))
289 }
290
291 pub(crate) fn metered_scalar_vec_from_vecobj<S>(
293 &self,
294 vp: VecObject,
295 ) -> Result<Vec<S>, HostError>
296 where
297 S: MeteredScalar,
298 {
299 self.visit_obj(vp, |hv: &HostVec| {
300 let mut scalars: Vec<S> = Vec::with_metered_capacity(hv.len(), self)?;
301 for val in hv.iter() {
302 let u256_val = U256Val::try_from(*val).map_err(|_| {
303 self.err(
304 ScErrorType::Crypto,
305 ScErrorCode::InvalidInput,
306 "element must be U256Val",
307 std::slice::from_ref(val),
308 )
309 })?;
310 let scalar = S::from_u256val(self, u256_val)?;
311 scalars.push(scalar);
312 }
313 Ok(scalars)
314 })
315 }
316
317 pub(crate) fn metered_scalar_vec_to_vecobj<S>(
319 &self,
320 scalars: Vec<S>,
321 ) -> Result<VecObject, HostError>
322 where
323 S: MeteredScalar,
324 {
325 let vals = scalars
326 .into_iter()
327 .map(|s| s.into_u256val(self))
328 .metered_collect::<Result<Vec<_>, HostError>>(self)??;
329
330 let host_vec =
331 HostVec::from_exact_iter(vals.into_iter().map(|v| v.to_val()), self.budget_ref())?;
332
333 self.add_host_object(host_vec)
334 }
335
336 pub(crate) fn metered_scalar_vec_of_vec_from_vecobj<S>(
338 &self,
339 vp: VecObject,
340 ) -> Result<Vec<Vec<S>>, HostError>
341 where
342 S: MeteredScalar,
343 {
344 self.visit_obj(vp, |hv: &HostVec| {
345 let n_rows = hv.len();
346 let mut result = Vec::with_metered_capacity(n_rows, self)?;
347 for row_val in hv.iter() {
348 let row_obj = VecObject::try_from(*row_val).map_err(|_| {
349 self.err(
350 ScErrorType::Crypto,
351 ScErrorCode::InvalidInput,
352 "poseidon_permutation: row must be a vector",
353 std::slice::from_ref(row_val),
354 )
355 })?;
356
357 let row_vec = self.metered_scalar_vec_from_vecobj::<S>(row_obj)?;
358 result.push(row_vec);
359 }
360 Ok(result)
361 })
362 }
363}
364
365impl Convert<&Object, ScValObject> for Host {
366 type Error = HostError;
367 fn convert(&self, ob: &Object) -> Result<ScValObject, Self::Error> {
368 self.from_host_obj(*ob)
369 }
370}
371
372impl Convert<Object, ScValObject> for Host {
373 type Error = HostError;
374 fn convert(&self, ob: Object) -> Result<ScValObject, Self::Error> {
375 self.from_host_obj(ob)
376 }
377}
378
379impl<'a> Convert<&ScValObjRef<'a>, Object> for Host {
380 type Error = HostError;
381 fn convert(&self, ob: &ScValObjRef<'a>) -> Result<Object, Self::Error> {
382 self.to_host_obj(ob)
383 }
384}
385
386impl<'a> Convert<ScValObjRef<'a>, Object> for Host {
387 type Error = HostError;
388 fn convert(&self, ob: ScValObjRef<'a>) -> Result<Object, Self::Error> {
389 self.to_host_obj(&ob)
390 }
391}
392
393impl Host {
394 pub(crate) fn check_val_representable_scval(&self, scval: &ScVal) -> Result<(), HostError> {
395 if Val::can_represent_scval(&scval) {
396 Ok(())
397 } else {
398 Err(self.err(
399 ScErrorType::Value,
400 ScErrorCode::InternalError,
401 "unexpected non-Val-representable ScVal type",
402 &[Val::from_u32(scval.discriminant() as u32).into()],
403 ))
404 }
405 }
406
407 pub(crate) fn from_host_val(&self, val: Val) -> Result<ScVal, HostError> {
408 let _span = tracy_span!("Val to ScVal");
412 let scval = self.budget_cloned().with_limited_depth(|_| {
413 ScVal::try_from_val(self, &val)
414 .map_err(|cerr| self.error(cerr, "failed to convert host value to ScVal", &[val]))
415 })?;
416 self.check_val_representable_scval(&scval)?;
419 Ok(scval)
420 }
421
422 pub(crate) fn from_host_val_for_storage(&self, val: Val) -> Result<ScVal, HostError> {
423 let _span = tracy_span!("Val to ScVal");
424 *self.try_borrow_storage_key_conversion_active_mut()? = true;
425 let scval = self.budget_cloned().with_limited_depth(|_| {
426 ScVal::try_from_val(self, &val)
427 .map_err(|cerr| self.error(cerr, "failed to convert host value to ScVal", &[val]))
428 })?;
429 *self.try_borrow_storage_key_conversion_active_mut()? = false;
430 self.check_val_representable_scval(&scval)?;
431 Ok(scval)
432 }
433
434 pub(crate) fn to_host_val(&self, v: &ScVal) -> Result<Val, HostError> {
435 let _span = tracy_span!("ScVal to Val");
436 self.budget_cloned().with_limited_depth(|_| {
440 v.try_into_val(self)
441 .map_err(|cerr| self.error(cerr, "failed to convert ScVal to host value", &[]))
442 })
443 }
444
445 pub(crate) fn to_valid_host_val(&self, v: &ScVal) -> Result<Val, HostError> {
448 self.to_host_val(v).map_err(|e| {
449 if e.error.is_type(ScErrorType::Budget) {
450 e
451 } else {
452 self.err(
453 ScErrorType::Value,
454 ScErrorCode::InternalError,
455 "unexpected non-Val-representable ScVal in internal conversion",
456 &[],
457 )
458 }
459 })
460 }
461
462 pub(crate) fn from_host_obj(&self, ob: impl Into<Object>) -> Result<ScValObject, HostError> {
463 unsafe {
464 let objref: Object = ob.into();
465 self.visit_obj_untyped(objref, |ho| {
466 let val = match ho {
467 HostObject::Vec(vv) => {
468 Vec::<ScVal>::charge_bulk_init_cpy(vv.len() as u64, self)?;
469 let sv = vv.iter().map(|e| self.from_host_val(*e)).collect::<Result<
470 Vec<ScVal>,
471 HostError,
472 >>(
473 )?;
474 ScVal::Vec(Some(ScVec(self.map_err(sv.try_into())?)))
475 }
476 HostObject::Map(mm) => ScVal::Map(Some(self.host_map_to_scmap(mm)?)),
477 HostObject::U64(u) => {
478 charge_shallow_copy::<u64>(1, self)?;
479 ScVal::U64(*u)
480 }
481 HostObject::I64(i) => {
482 charge_shallow_copy::<i64>(1, self)?;
483 ScVal::I64(*i)
484 }
485 HostObject::TimePoint(tp) => ScVal::Timepoint(tp.metered_clone(self)?),
486 HostObject::Duration(d) => ScVal::Duration(d.metered_clone(self)?),
487 HostObject::U128(u) => {
488 charge_shallow_copy::<u128>(1, self)?;
489 ScVal::U128(UInt128Parts {
490 hi: int128_helpers::u128_hi(*u),
491 lo: int128_helpers::u128_lo(*u),
492 })
493 }
494 HostObject::I128(i) => {
495 charge_shallow_copy::<i128>(1, self)?;
496 ScVal::I128(Int128Parts {
497 hi: int128_helpers::i128_hi(*i),
498 lo: int128_helpers::i128_lo(*i),
499 })
500 }
501 HostObject::U256(u) => {
502 charge_shallow_copy::<u128>(2, self)?;
503 let (hi_hi, hi_lo, lo_hi, lo_lo) = u256_into_pieces(*u);
504 ScVal::U256(UInt256Parts {
505 hi_hi,
506 hi_lo,
507 lo_hi,
508 lo_lo,
509 })
510 }
511 HostObject::I256(i) => {
512 charge_shallow_copy::<i128>(2, self)?;
513 let (hi_hi, hi_lo, lo_hi, lo_lo) = i256_into_pieces(*i);
514 ScVal::I256(Int256Parts {
515 hi_hi,
516 hi_lo,
517 lo_hi,
518 lo_lo,
519 })
520 }
521 HostObject::Bytes(b) => ScVal::Bytes(b.metered_clone(self)?),
522 HostObject::String(s) => ScVal::String(s.metered_clone(self)?),
523 HostObject::Symbol(s) => ScVal::Symbol(s.metered_clone(self)?),
524 HostObject::Address(addr) => ScVal::Address(addr.metered_clone(self)?),
525 HostObject::MuxedAddress(addr) => {
526 if *self.try_borrow_storage_key_conversion_active()? {
527 return Err(self.err(
528 ScErrorType::Storage,
529 ScErrorCode::InvalidInput,
530 "muxed addresses should not be used in the storage keys",
531 &[objref.to_val()],
532 ));
533 }
534 ScVal::Address(addr.0.metered_clone(self)?)
535 }
536 };
537 Ok(ScValObject::unchecked_from_val(val))
538 })
539 }
540 }
541
542 pub(crate) fn to_host_obj(&self, ob: &ScValObjRef<'_>) -> Result<Object, HostError> {
543 let val: &ScVal = (*ob).into();
544 match val {
545 ScVal::Vec(Some(v)) => {
549 let mut vv = Vec::<Val>::with_metered_capacity(v.len(), self)?;
550 for e in v.iter() {
551 vv.push(self.to_host_val(e)?)
552 }
553 Ok(self.add_host_object(HostVec::from_vec(vv)?)?.into())
554 }
555 ScVal::Map(Some(m)) => {
556 let mut mm = Vec::<(Val, Val)>::with_metered_capacity(m.len(), self)?;
557 for pair in m.iter() {
558 let k = self.to_host_val(&pair.key)?;
559 let v = self.to_host_val(&pair.val)?;
560 mm.push((k, v))
561 }
562 Ok(self
563 .add_host_object(HostMap::from_map_with_host(mm, self)?)?
564 .into())
565 }
566 ScVal::Vec(None) => Err(self.err(
567 ScErrorType::Value,
568 ScErrorCode::InvalidInput,
569 "ScVal::Vec body missing",
570 &[],
571 )),
572 ScVal::Map(None) => Err(self.err(
573 ScErrorType::Value,
574 ScErrorCode::InvalidInput,
575 "ScVal::Map body missing",
576 &[],
577 )),
578 ScVal::U64(u) => {
579 charge_shallow_copy::<u64>(1, self)?;
580 Ok(self.add_host_object(*u)?.into())
581 }
582 ScVal::I64(i) => {
583 charge_shallow_copy::<i64>(1, self)?;
584 Ok(self.add_host_object(*i)?.into())
585 }
586 ScVal::Timepoint(t) => Ok(self.add_host_object(t.metered_clone(self)?)?.into()),
587 ScVal::Duration(d) => Ok(self.add_host_object(d.metered_clone(self)?)?.into()),
588 ScVal::U128(u) => {
589 charge_shallow_copy::<u128>(1, self)?;
590 Ok(self
591 .add_host_object(int128_helpers::u128_from_pieces(u.hi, u.lo))?
592 .into())
593 }
594 ScVal::I128(i) => {
595 charge_shallow_copy::<i128>(1, self)?;
596 Ok(self
597 .add_host_object(int128_helpers::i128_from_pieces(i.hi, i.lo))?
598 .into())
599 }
600 ScVal::U256(u) => {
601 charge_shallow_copy::<u128>(2, self)?;
602 Ok(self
603 .add_host_object(u256_from_pieces(u.hi_hi, u.hi_lo, u.lo_hi, u.lo_lo))?
604 .into())
605 }
606 ScVal::I256(i) => {
607 charge_shallow_copy::<i128>(2, self)?;
608 Ok(self
609 .add_host_object(i256_from_pieces(i.hi_hi, i.hi_lo, i.lo_hi, i.lo_lo))?
610 .into())
611 }
612 ScVal::Bytes(b) => Ok(self.add_host_object(b.metered_clone(self)?)?.into()),
613 ScVal::String(s) => Ok(self.add_host_object(s.metered_clone(self)?)?.into()),
614 ScVal::Symbol(s) => Ok(self
617 .add_host_object(ScSymbol::try_from_bytes(
618 self,
619 s.0.metered_clone(self.as_budget())?.into(),
620 )?)?
621 .into()),
622
623 ScVal::Address(addr) => {
624 match addr {
625 ScAddress::Account(_) | ScAddress::Contract(_) => {
626 Ok(self.add_host_object(addr.metered_clone(self)?)?.into())
627 }
628 ScAddress::MuxedAccount(_) => Ok(self
629 .add_host_object(MuxedScAddress(addr.metered_clone(self)?))?
630 .into()),
631 _ => Err(self.err(
632 ScErrorType::Object,
633 ScErrorCode::UnexpectedType,
634 "encountered unsupported ScAddress type",
635 &[],
636 )),
637 }
638 }
640
641 ScVal::Bool(_)
644 | ScVal::Void
645 | ScVal::Error(_)
646 | ScVal::U32(_)
647 | ScVal::I32(_)
648 | ScVal::LedgerKeyNonce(_)
649 | ScVal::ContractInstance(_)
650 | ScVal::LedgerKeyContractInstance => Err(self.err(
651 ScErrorType::Value,
652 ScErrorCode::InternalError,
653 "converting ScValObjRef on non-object ScVal type",
654 &[],
655 )),
656 }
657 }
658}