1use std::rc::Rc;
2
3use crate::host_object::MemHostObjectType;
4use crate::{
5 budget::{AsBudget, DepthLimiter},
6 err,
7 host::metered_clone::{
8 charge_shallow_copy, MeteredAlloc, MeteredClone, MeteredContainer, MeteredIterator,
9 },
10 host_object::{HostMap, HostObject, HostVec},
11 num::{i256_from_pieces, i256_into_pieces, u256_from_pieces, u256_into_pieces},
12 xdr::{
13 self, int128_helpers, AccountId, ContractCostType, ContractDataDurability, Hash,
14 Int128Parts, Int256Parts, LedgerKey, LedgerKeyContractData, ScAddress, ScBytes,
15 ScErrorCode, ScErrorType, ScMap, ScMapEntry, ScSymbol, ScVal, ScVec, UInt128Parts,
16 UInt256Parts, Uint256, VecM,
17 },
18 AddressObject, BytesObject, Convert, Host, HostError, Object, ScValObjRef, ScValObject, Symbol,
19 SymbolObject, TryFromVal, TryIntoVal, U32Val, Val, VecObject,
20};
21
22impl Host {
23 pub(crate) fn usize_to_u32(&self, u: usize) -> Result<u32, HostError> {
25 match u32::try_from(u) {
26 Ok(v) => Ok(v),
27 Err(_) => Err(self.err(
28 ScErrorType::Value,
29 ScErrorCode::ArithDomain,
30 "provided usize does not fit in u32",
31 &[],
32 )),
33 }
34 }
35
36 pub(crate) fn usize_to_u32val(&self, u: usize) -> Result<U32Val, HostError> {
38 self.usize_to_u32(u).map(|v| v.into())
39 }
40
41 pub(crate) fn u256_from_account(&self, account_id: &AccountId) -> Result<Uint256, HostError> {
42 let crate::xdr::PublicKey::PublicKeyTypeEd25519(ed25519) =
43 account_id.metered_clone(self)?.0;
44 Ok(ed25519)
45 }
46
47 pub(crate) fn u8_from_u32val_input(
49 &self,
50 name: &'static str,
51 r: U32Val,
52 ) -> Result<u8, HostError> {
53 let u: u32 = r.into();
54 match u8::try_from(u) {
55 Ok(v) => Ok(v),
56 Err(_) => Err(self.err(
57 ScErrorType::Value,
58 ScErrorCode::ArithDomain,
59 "expecting U32Val less than 256",
60 &[r.to_val(), name.try_into_val(self)?],
61 )),
62 }
63 }
64
65 pub(crate) fn hash_from_bytesobj_input(
66 &self,
67 name: &'static str,
68 hash: BytesObject,
69 ) -> Result<Hash, HostError> {
70 static_assertions::assert_eq_size!([u8; 32], Hash);
71 self.fixed_length_bytes_from_bytesobj_input::<Hash, 32>(name, hash)
72 }
73
74 pub(crate) fn u256_from_bytesobj_input(
75 &self,
76 name: &'static str,
77 u256: BytesObject,
78 ) -> Result<Uint256, HostError> {
79 static_assertions::assert_eq_size!([u8; 32], Uint256);
80 self.fixed_length_bytes_from_bytesobj_input::<Uint256, 32>(name, u256)
81 }
82
83 pub(crate) fn fixed_length_bytes_from_slice<T, const N: usize>(
84 &self,
85 name: &'static str,
86 bytes_arr: &[u8],
87 ) -> Result<T, HostError>
88 where
89 T: From<[u8; N]>,
90 {
91 match <[u8; N]>::try_from(bytes_arr) {
92 Ok(arr) => {
93 self.charge_budget(ContractCostType::MemCpy, Some(N as u64))?;
94 Ok(arr.into())
95 }
96 Err(_) => Err(err!(
97 self,
98 (ScErrorType::Object, ScErrorCode::UnexpectedSize),
99 "expected fixed-length bytes slice, got slice with different size",
100 name,
101 N,
102 bytes_arr.len()
103 )),
104 }
105 }
106
107 pub(crate) fn fixed_length_bytes_from_bytesobj_input<T, const N: usize>(
108 &self,
109 name: &'static str,
110 obj: BytesObject,
111 ) -> Result<T, HostError>
112 where
113 T: From<[u8; N]>,
114 {
115 self.visit_obj(obj, |bytes: &ScBytes| {
116 self.fixed_length_bytes_from_slice(name, bytes.as_slice())
117 })
118 }
119
120 pub(crate) fn account_id_from_bytesobj(&self, k: BytesObject) -> Result<AccountId, HostError> {
121 self.visit_obj(k, |bytes: &ScBytes| {
122 Ok(AccountId(xdr::PublicKey::PublicKeyTypeEd25519(
123 self.fixed_length_bytes_from_slice("account_id", bytes.as_slice())?,
124 )))
125 })
126 }
127
128 pub(crate) fn storage_key_for_address(
129 &self,
130 contract: ScAddress,
131 key: ScVal,
132 durability: ContractDataDurability,
133 ) -> Result<Rc<LedgerKey>, HostError> {
134 Rc::metered_new(
135 LedgerKey::ContractData(LedgerKeyContractData {
136 contract,
137 key,
138 durability,
139 }),
140 self,
141 )
142 }
143
144 pub(crate) fn storage_key_from_scval(
145 &self,
146 key: ScVal,
147 durability: ContractDataDurability,
148 ) -> Result<Rc<LedgerKey>, HostError> {
149 let contract_id = self.get_current_contract_id_internal()?;
150 self.storage_key_for_address(ScAddress::Contract(contract_id), key, durability)
151 }
152
153 pub(crate) fn storage_key_from_val(
157 &self,
158 k: Val,
159 durability: ContractDataDurability,
160 ) -> Result<Rc<LedgerKey>, HostError> {
161 let key_scval = self.from_host_val(k)?;
162 self.storage_key_from_scval(key_scval, durability)
163 }
164
165 pub(crate) fn u64_from_binary_search_result(
174 &self,
175 res: Result<usize, usize>,
176 ) -> Result<u64, HostError> {
177 match res {
178 Ok(u) => {
179 let v = self.usize_to_u32(u)?;
180 Ok(u64::from(v) | (1_u64 << u32::BITS))
181 }
182 Err(u) => {
183 let v = self.usize_to_u32(u)?;
184 Ok(u64::from(v))
185 }
186 }
187 }
188
189 pub(crate) fn call_args_from_obj(&self, args: VecObject) -> Result<Vec<Val>, HostError> {
190 self.visit_obj(args, |hv: &HostVec| hv.to_vec(self.as_budget()))
191 }
192
193 pub(crate) fn vecobject_to_scval_vec(&self, args: VecObject) -> Result<VecM<ScVal>, HostError> {
195 self.visit_obj(args, |hv: &HostVec| self.vals_to_scval_vec(hv.as_slice()))
196 }
197
198 pub(crate) fn vals_to_scval_vec(&self, vals: &[Val]) -> Result<VecM<ScVal>, HostError> {
199 vals.iter()
200 .map(|v| self.from_host_val(*v))
201 .metered_collect::<Result<Vec<ScVal>, HostError>>(self)??
202 .try_into()
203 .map_err(|_| {
204 err!(
205 self,
206 (ScErrorType::Object, ScErrorCode::ExceededLimit),
207 "vector size limit exceeded",
208 vals.len()
209 )
210 })
211 }
212
213 pub(crate) fn scvals_to_val_vec(&self, scvals: &[ScVal]) -> Result<Vec<Val>, HostError> {
214 scvals
215 .iter()
216 .map(|scv| self.to_host_val(scv))
217 .metered_collect::<Result<Vec<Val>, HostError>>(self)?
218 }
219
220 pub(crate) fn bytesobj_from_internal_contract_id(
221 &self,
222 ) -> Result<Option<BytesObject>, HostError> {
223 if let Some(id) = self.get_current_contract_id_opt_internal()? {
224 let obj = self.add_host_object::<ScBytes>(
225 self.metered_slice_to_vec(id.as_slice())?.try_into()?,
226 )?;
227 Ok(Some(obj))
228 } else {
229 Ok(None)
230 }
231 }
232
233 pub(crate) fn scbytes_from_vec(&self, v: Vec<u8>) -> Result<ScBytes, HostError> {
234 Ok(ScBytes(v.try_into()?))
235 }
236
237 pub(crate) fn metered_slice_to_vec(&self, s: &[u8]) -> Result<Vec<u8>, HostError> {
238 Vec::<u8>::charge_bulk_init_cpy(s.len() as u64, self)?;
239 Ok(s.to_vec())
240 }
241
242 pub(crate) fn scbytes_from_slice(&self, s: &[u8]) -> Result<ScBytes, HostError> {
244 self.scbytes_from_vec(self.metered_slice_to_vec(s)?)
245 }
246
247 pub(crate) fn scbytes_from_hash(&self, hash: &Hash) -> Result<ScBytes, HostError> {
248 self.scbytes_from_slice(hash.as_slice())
249 }
250
251 pub fn scaddress_from_address(&self, address: AddressObject) -> Result<ScAddress, HostError> {
252 self.visit_obj(address, |addr: &ScAddress| addr.metered_clone(self))
253 }
254
255 pub(crate) fn scsymbol_from_symbol(&self, symbol: Symbol) -> Result<ScSymbol, HostError> {
256 if let Ok(sobj) = SymbolObject::try_from(symbol) {
257 self.visit_obj(sobj, |sym: &ScSymbol| sym.metered_clone(self))
258 } else {
259 self.map_err(ScSymbol::try_from_val(self, &symbol))
260 }
261 }
262
263 pub(crate) fn host_map_to_scmap(&self, map: &HostMap) -> Result<ScMap, HostError> {
264 let mut mv = Vec::<ScMapEntry>::with_metered_capacity(map.len(), self)?;
265 for (k, v) in map.iter(self)? {
266 let key = self.from_host_val(*k)?;
267 let val = self.from_host_val(*v)?;
268 mv.push(ScMapEntry { key, val });
269 }
270 Ok(ScMap(self.map_err(mv.try_into())?))
271 }
272}
273
274impl Convert<&Object, ScValObject> for Host {
275 type Error = HostError;
276 fn convert(&self, ob: &Object) -> Result<ScValObject, Self::Error> {
277 self.from_host_obj(*ob)
278 }
279}
280
281impl Convert<Object, ScValObject> for Host {
282 type Error = HostError;
283 fn convert(&self, ob: Object) -> Result<ScValObject, Self::Error> {
284 self.from_host_obj(ob)
285 }
286}
287
288impl<'a> Convert<&ScValObjRef<'a>, Object> for Host {
289 type Error = HostError;
290 fn convert(&self, ob: &ScValObjRef<'a>) -> Result<Object, Self::Error> {
291 self.to_host_obj(ob)
292 }
293}
294
295impl<'a> Convert<ScValObjRef<'a>, Object> for Host {
296 type Error = HostError;
297 fn convert(&self, ob: ScValObjRef<'a>) -> Result<Object, Self::Error> {
298 self.to_host_obj(&ob)
299 }
300}
301
302impl Host {
303 pub(crate) fn check_val_representable_scval(&self, scval: &ScVal) -> Result<(), HostError> {
304 if Val::can_represent_scval(&scval) {
305 Ok(())
306 } else {
307 Err(self.err(
308 ScErrorType::Value,
309 ScErrorCode::InternalError,
310 "unexpected non-Val-representable ScVal type",
311 &[Val::from_u32(scval.discriminant() as u32).into()],
312 ))
313 }
314 }
315
316 pub(crate) fn from_host_val(&self, val: Val) -> Result<ScVal, HostError> {
317 let _span = tracy_span!("Val to ScVal");
321 let scval = self.budget_cloned().with_limited_depth(|_| {
322 ScVal::try_from_val(self, &val)
323 .map_err(|cerr| self.error(cerr, "failed to convert host value to ScVal", &[val]))
324 })?;
325 self.check_val_representable_scval(&scval)?;
328 Ok(scval)
329 }
330
331 pub(crate) fn to_host_val(&self, v: &ScVal) -> Result<Val, HostError> {
332 let _span = tracy_span!("ScVal to Val");
333 self.budget_cloned().with_limited_depth(|_| {
337 v.try_into_val(self)
338 .map_err(|cerr| self.error(cerr, "failed to convert ScVal to host value", &[]))
339 })
340 }
341
342 pub(crate) fn to_valid_host_val(&self, v: &ScVal) -> Result<Val, HostError> {
345 self.to_host_val(v).map_err(|e| {
346 if e.error.is_type(ScErrorType::Budget) {
347 e
348 } else {
349 self.err(
350 ScErrorType::Value,
351 ScErrorCode::InternalError,
352 "unexpected non-Val-representable ScVal in internal conversion",
353 &[],
354 )
355 }
356 })
357 }
358
359 pub(crate) fn from_host_obj(&self, ob: impl Into<Object>) -> Result<ScValObject, HostError> {
360 unsafe {
361 let objref: Object = ob.into();
362 self.visit_obj_untyped(objref, |ho| {
363 let val = match ho {
364 HostObject::Vec(vv) => {
365 Vec::<ScVal>::charge_bulk_init_cpy(vv.len() as u64, self)?;
366 let sv = vv.iter().map(|e| self.from_host_val(*e)).collect::<Result<
367 Vec<ScVal>,
368 HostError,
369 >>(
370 )?;
371 ScVal::Vec(Some(ScVec(self.map_err(sv.try_into())?)))
372 }
373 HostObject::Map(mm) => ScVal::Map(Some(self.host_map_to_scmap(mm)?)),
374 HostObject::U64(u) => {
375 charge_shallow_copy::<u64>(1, self)?;
376 ScVal::U64(*u)
377 }
378 HostObject::I64(i) => {
379 charge_shallow_copy::<i64>(1, self)?;
380 ScVal::I64(*i)
381 }
382 HostObject::TimePoint(tp) => ScVal::Timepoint(tp.metered_clone(self)?),
383 HostObject::Duration(d) => ScVal::Duration(d.metered_clone(self)?),
384 HostObject::U128(u) => {
385 charge_shallow_copy::<u128>(1, self)?;
386 ScVal::U128(UInt128Parts {
387 hi: int128_helpers::u128_hi(*u),
388 lo: int128_helpers::u128_lo(*u),
389 })
390 }
391 HostObject::I128(i) => {
392 charge_shallow_copy::<i128>(1, self)?;
393 ScVal::I128(Int128Parts {
394 hi: int128_helpers::i128_hi(*i),
395 lo: int128_helpers::i128_lo(*i),
396 })
397 }
398 HostObject::U256(u) => {
399 charge_shallow_copy::<u128>(2, self)?;
400 let (hi_hi, hi_lo, lo_hi, lo_lo) = u256_into_pieces(*u);
401 ScVal::U256(UInt256Parts {
402 hi_hi,
403 hi_lo,
404 lo_hi,
405 lo_lo,
406 })
407 }
408 HostObject::I256(i) => {
409 charge_shallow_copy::<i128>(2, self)?;
410 let (hi_hi, hi_lo, lo_hi, lo_lo) = i256_into_pieces(*i);
411 ScVal::I256(Int256Parts {
412 hi_hi,
413 hi_lo,
414 lo_hi,
415 lo_lo,
416 })
417 }
418 HostObject::Bytes(b) => ScVal::Bytes(b.metered_clone(self)?),
419 HostObject::String(s) => ScVal::String(s.metered_clone(self)?),
420 HostObject::Symbol(s) => ScVal::Symbol(s.metered_clone(self)?),
421 HostObject::Address(addr) => ScVal::Address(addr.metered_clone(self)?),
422 };
423 Ok(ScValObject::unchecked_from_val(val))
424 })
425 }
426 }
427
428 pub(crate) fn to_host_obj(&self, ob: &ScValObjRef<'_>) -> Result<Object, HostError> {
429 let val: &ScVal = (*ob).into();
430 match val {
431 ScVal::Vec(Some(v)) => {
435 let mut vv = Vec::<Val>::with_metered_capacity(v.len(), self)?;
436 for e in v.iter() {
437 vv.push(self.to_host_val(e)?)
438 }
439 Ok(self.add_host_object(HostVec::from_vec(vv)?)?.into())
440 }
441 ScVal::Map(Some(m)) => {
442 let mut mm = Vec::<(Val, Val)>::with_metered_capacity(m.len(), self)?;
443 for pair in m.iter() {
444 let k = self.to_host_val(&pair.key)?;
445 let v = self.to_host_val(&pair.val)?;
446 mm.push((k, v))
447 }
448 Ok(self.add_host_object(HostMap::from_map(mm, self)?)?.into())
449 }
450 ScVal::Vec(None) => Err(self.err(
451 ScErrorType::Value,
452 ScErrorCode::InvalidInput,
453 "ScVal::Vec body missing",
454 &[],
455 )),
456 ScVal::Map(None) => Err(self.err(
457 ScErrorType::Value,
458 ScErrorCode::InvalidInput,
459 "ScVal::Map body missing",
460 &[],
461 )),
462 ScVal::U64(u) => {
463 charge_shallow_copy::<u64>(1, self)?;
464 Ok(self.add_host_object(*u)?.into())
465 }
466 ScVal::I64(i) => {
467 charge_shallow_copy::<i64>(1, self)?;
468 Ok(self.add_host_object(*i)?.into())
469 }
470 ScVal::Timepoint(t) => Ok(self.add_host_object(t.metered_clone(self)?)?.into()),
471 ScVal::Duration(d) => Ok(self.add_host_object(d.metered_clone(self)?)?.into()),
472 ScVal::U128(u) => {
473 charge_shallow_copy::<u128>(1, self)?;
474 Ok(self
475 .add_host_object(int128_helpers::u128_from_pieces(u.hi, u.lo))?
476 .into())
477 }
478 ScVal::I128(i) => {
479 charge_shallow_copy::<i128>(1, self)?;
480 Ok(self
481 .add_host_object(int128_helpers::i128_from_pieces(i.hi, i.lo))?
482 .into())
483 }
484 ScVal::U256(u) => {
485 charge_shallow_copy::<u128>(2, self)?;
486 Ok(self
487 .add_host_object(u256_from_pieces(u.hi_hi, u.hi_lo, u.lo_hi, u.lo_lo))?
488 .into())
489 }
490 ScVal::I256(i) => {
491 charge_shallow_copy::<i128>(2, self)?;
492 Ok(self
493 .add_host_object(i256_from_pieces(i.hi_hi, i.hi_lo, i.lo_hi, i.lo_lo))?
494 .into())
495 }
496 ScVal::Bytes(b) => Ok(self.add_host_object(b.metered_clone(self)?)?.into()),
497 ScVal::String(s) => Ok(self.add_host_object(s.metered_clone(self)?)?.into()),
498 ScVal::Symbol(s) => Ok(self
501 .add_host_object(ScSymbol::try_from_bytes(
502 self,
503 s.0.metered_clone(self.as_budget())?.into(),
504 )?)?
505 .into()),
506
507 ScVal::Address(addr) => Ok(self.add_host_object(addr.metered_clone(self)?)?.into()),
508
509 ScVal::Bool(_)
512 | ScVal::Void
513 | ScVal::Error(_)
514 | ScVal::U32(_)
515 | ScVal::I32(_)
516 | ScVal::LedgerKeyNonce(_)
517 | ScVal::ContractInstance(_)
518 | ScVal::LedgerKeyContractInstance => Err(self.err(
519 ScErrorType::Value,
520 ScErrorCode::InternalError,
521 "converting ScValObjRef on non-object ScVal type",
522 &[],
523 )),
524 }
525 }
526}