1use std::{
2 collections::{BTreeMap, BTreeSet},
3 convert::TryFrom,
4};
5
6use casper_wasmi::{Externals, RuntimeArgs, RuntimeValue, Trap};
7
8use casper_storage::global_state::{error::Error as GlobalStateError, state::StateReader};
9use casper_types::{
10 account::AccountHash,
11 addressable_entity::{EntityEntryPoint, EntryPoints},
12 api_error,
13 bytesrepr::{self, ToBytes},
14 contract_messages::MessageTopicOperation,
15 contracts::{
16 ContractPackageHash, EntryPoints as ContractEntryPoints, NamedKeys, ProtocolVersionMajor,
17 },
18 AddressableEntityHash, ApiError, EntityVersion, Gas, Group, HashAlgorithm, HostFunction,
19 HostFunctionCost, Key, PackageHash, PackageStatus, PublicKey, Signature, StoredValue, URef,
20 U512, UREF_SERIALIZED_LENGTH,
21};
22
23use super::{args::Args, ExecError, Runtime};
24use crate::{resolvers::v1_function_index::FunctionIndex, runtime::cryptography};
25
26impl<R> Externals for Runtime<'_, R>
27where
28 R: StateReader<Key, StoredValue, Error = GlobalStateError>,
29{
30 fn invoke_index(
31 &mut self,
32 index: usize,
33 args: RuntimeArgs,
34 ) -> Result<Option<RuntimeValue>, Trap> {
35 let func = FunctionIndex::try_from(index).expect("unknown function index");
36
37 let host_function_costs =
38 (*self.context.engine_config().wasm_config().v1()).take_host_function_costs();
39
40 match func {
41 FunctionIndex::ReadFuncIndex => {
42 let (key_ptr, key_size, output_size_ptr) = Args::parse(args)?;
46 self.charge_host_function_call(
47 &host_function_costs.read_value,
48 [key_ptr, key_size, output_size_ptr],
49 )?;
50 let ret = self.read(key_ptr, key_size, output_size_ptr)?;
51 Ok(Some(RuntimeValue::I32(api_error::i32_from(ret))))
52 }
53
54 FunctionIndex::LoadNamedKeysFuncIndex => {
55 let (total_keys_ptr, result_size_ptr) = Args::parse(args)?;
58 self.charge_host_function_call(
59 &host_function_costs.load_named_keys,
60 [total_keys_ptr, result_size_ptr],
61 )?;
62 let ret = self.load_named_keys(total_keys_ptr, result_size_ptr)?;
63 Ok(Some(RuntimeValue::I32(api_error::i32_from(ret))))
64 }
65
66 FunctionIndex::WriteFuncIndex => {
67 let (key_ptr, key_size, value_ptr, value_size) = Args::parse(args)?;
72 self.charge_host_function_call(
73 &host_function_costs.write,
74 [key_ptr, key_size, value_ptr, value_size],
75 )?;
76 self.write(key_ptr, key_size, value_ptr, value_size)?;
77 Ok(None)
78 }
79
80 FunctionIndex::AddFuncIndex => {
81 let (key_ptr, key_size, value_ptr, value_size) = Args::parse(args)?;
86 self.charge_host_function_call(
87 &host_function_costs.add,
88 [key_ptr, key_size, value_ptr, value_size],
89 )?;
90 self.add(key_ptr, key_size, value_ptr, value_size)?;
91 Ok(None)
92 }
93
94 FunctionIndex::NewFuncIndex => {
95 let (uref_ptr, value_ptr, value_size) = Args::parse(args)?;
99 self.charge_host_function_call(
100 &host_function_costs.new_uref,
101 [uref_ptr, value_ptr, value_size],
102 )?;
103 self.new_uref(uref_ptr, value_ptr, value_size)?;
104 Ok(None)
105 }
106
107 FunctionIndex::RetFuncIndex => {
108 let (value_ptr, value_size) = Args::parse(args)?;
111 self.charge_host_function_call(&host_function_costs.ret, [value_ptr, value_size])?;
112 Err(self.ret(value_ptr, value_size as usize))
113 }
114
115 FunctionIndex::GetKeyFuncIndex => {
116 let (name_ptr, name_size, output_ptr, output_size, bytes_written) =
122 Args::parse(args)?;
123 self.charge_host_function_call(
124 &host_function_costs.get_key,
125 [name_ptr, name_size, output_ptr, output_size, bytes_written],
126 )?;
127 let ret = self.load_key(
128 name_ptr,
129 name_size,
130 output_ptr,
131 output_size as usize,
132 bytes_written,
133 )?;
134 Ok(Some(RuntimeValue::I32(api_error::i32_from(ret))))
135 }
136
137 FunctionIndex::HasKeyFuncIndex => {
138 let (name_ptr, name_size) = Args::parse(args)?;
141 self.charge_host_function_call(
142 &host_function_costs.has_key,
143 [name_ptr, name_size],
144 )?;
145 let result = self.has_key(name_ptr, name_size)?;
146 Ok(Some(RuntimeValue::I32(result)))
147 }
148
149 FunctionIndex::PutKeyFuncIndex => {
150 let (name_ptr, name_size, key_ptr, key_size) = Args::parse(args)?;
155 self.charge_host_function_call(
156 &host_function_costs.put_key,
157 [name_ptr, name_size, key_ptr, key_size],
158 )?;
159 self.put_key(name_ptr, name_size, key_ptr, key_size)?;
160 Ok(None)
161 }
162
163 FunctionIndex::RemoveKeyFuncIndex => {
164 let (name_ptr, name_size) = Args::parse(args)?;
167 self.charge_host_function_call(
168 &host_function_costs.remove_key,
169 [name_ptr, name_size],
170 )?;
171 self.remove_key(name_ptr, name_size)?;
172 Ok(None)
173 }
174
175 FunctionIndex::GetCallerIndex => {
176 let (output_size_ptr,) = Args::parse(args)?;
178 self.charge_host_function_call(&host_function_costs.get_caller, [output_size_ptr])?;
179 let ret = self.get_caller(output_size_ptr)?;
180 Ok(Some(RuntimeValue::I32(api_error::i32_from(ret))))
181 }
182
183 FunctionIndex::GetBlocktimeIndex => {
184 let (dest_ptr,) = Args::parse(args)?;
186 self.charge_host_function_call(&host_function_costs.get_blocktime, [dest_ptr])?;
187 self.get_blocktime(dest_ptr)?;
188 Ok(None)
189 }
190
191 FunctionIndex::GasFuncIndex => {
192 let (gas_arg,): (u32,) = Args::parse(args)?;
193 self.gas(Gas::new(gas_arg))?;
196 Ok(None)
197 }
198
199 FunctionIndex::IsValidURefFnIndex => {
200 let (uref_ptr, uref_size) = Args::parse(args)?;
203 self.charge_host_function_call(
204 &host_function_costs.is_valid_uref,
205 [uref_ptr, uref_size],
206 )?;
207 Ok(Some(RuntimeValue::I32(i32::from(
208 self.is_valid_uref(uref_ptr, uref_size)?,
209 ))))
210 }
211
212 FunctionIndex::RevertFuncIndex => {
213 let (status,) = Args::parse(args)?;
215 self.charge_host_function_call(&host_function_costs.revert, [status])?;
216 Err(self.revert(status))
217 }
218
219 FunctionIndex::AddAssociatedKeyFuncIndex => {
220 let (account_hash_ptr, account_hash_size, weight_value) = Args::parse(args)?;
224 self.charge_host_function_call(
225 &host_function_costs.add_associated_key,
226 [
227 account_hash_ptr,
228 account_hash_size,
229 weight_value as HostFunctionCost,
230 ],
231 )?;
232 let value = self.add_associated_key(
233 account_hash_ptr,
234 account_hash_size as usize,
235 weight_value,
236 )?;
237 Ok(Some(RuntimeValue::I32(value)))
238 }
239
240 FunctionIndex::RemoveAssociatedKeyFuncIndex => {
241 let (account_hash_ptr, account_hash_size) = Args::parse(args)?;
244 self.charge_host_function_call(
245 &host_function_costs.remove_associated_key,
246 [account_hash_ptr, account_hash_size],
247 )?;
248 let value =
249 self.remove_associated_key(account_hash_ptr, account_hash_size as usize)?;
250 Ok(Some(RuntimeValue::I32(value)))
251 }
252
253 FunctionIndex::UpdateAssociatedKeyFuncIndex => {
254 let (account_hash_ptr, account_hash_size, weight_value) = Args::parse(args)?;
258 self.charge_host_function_call(
259 &host_function_costs.update_associated_key,
260 [
261 account_hash_ptr,
262 account_hash_size,
263 weight_value as HostFunctionCost,
264 ],
265 )?;
266 let value = self.update_associated_key(
267 account_hash_ptr,
268 account_hash_size as usize,
269 weight_value,
270 )?;
271 Ok(Some(RuntimeValue::I32(value)))
272 }
273
274 FunctionIndex::SetActionThresholdFuncIndex => {
275 let (action_type_value, threshold_value) = Args::parse(args)?;
278 self.charge_host_function_call(
279 &host_function_costs.set_action_threshold,
280 [action_type_value, threshold_value as HostFunctionCost],
281 )?;
282 let value = self.set_action_threshold(action_type_value, threshold_value)?;
283 Ok(Some(RuntimeValue::I32(value)))
284 }
285
286 FunctionIndex::CreatePurseIndex => {
287 let (dest_ptr, dest_size) = Args::parse(args)?;
290
291 self.charge_host_function_call(
292 &host_function_costs.create_purse,
293 [dest_ptr, dest_size],
294 )?;
295
296 let result = if (dest_size as usize) < UREF_SERIALIZED_LENGTH {
297 Err(ApiError::PurseNotCreated)
298 } else {
299 let purse = self.create_purse()?;
300 let purse_bytes = purse.into_bytes().map_err(ExecError::BytesRepr)?;
301 self.try_get_memory()?
302 .set(dest_ptr, &purse_bytes)
303 .map_err(|e| ExecError::Interpreter(e.into()))?;
304 Ok(())
305 };
306
307 Ok(Some(RuntimeValue::I32(api_error::i32_from(result))))
308 }
309
310 FunctionIndex::TransferToAccountIndex => {
311 let (key_ptr, key_size, amount_ptr, amount_size, id_ptr, id_size, result_ptr) =
319 Args::parse(args)?;
320 self.charge_host_function_call(
321 &host_function_costs.transfer_to_account,
322 [
323 key_ptr,
324 key_size,
325 amount_ptr,
326 amount_size,
327 id_ptr,
328 id_size,
329 result_ptr,
330 ],
331 )?;
332 let account_hash: AccountHash = {
333 let bytes = self.bytes_from_mem(key_ptr, key_size as usize)?;
334 bytesrepr::deserialize_from_slice(bytes).map_err(ExecError::BytesRepr)?
335 };
336 let amount: U512 = {
337 let bytes = self.bytes_from_mem(amount_ptr, amount_size as usize)?;
338 bytesrepr::deserialize_from_slice(bytes).map_err(ExecError::BytesRepr)?
339 };
340 let id: Option<u64> = {
341 let bytes = self.bytes_from_mem(id_ptr, id_size as usize)?;
342 bytesrepr::deserialize_from_slice(bytes).map_err(ExecError::BytesRepr)?
343 };
344
345 let ret = match self.transfer_to_account(account_hash, amount, id)? {
346 Ok(transferred_to) => {
347 let result_value: u32 = transferred_to as u32;
348 let result_value_bytes = result_value.to_le_bytes();
349 self.try_get_memory()?
350 .set(result_ptr, &result_value_bytes)
351 .map_err(|error| ExecError::Interpreter(error.into()))?;
352 Ok(())
353 }
354 Err(api_error) => Err(api_error),
355 };
356 Ok(Some(RuntimeValue::I32(api_error::i32_from(ret))))
357 }
358
359 FunctionIndex::TransferFromPurseToAccountIndex => {
360 let (
370 source_ptr,
371 source_size,
372 key_ptr,
373 key_size,
374 amount_ptr,
375 amount_size,
376 id_ptr,
377 id_size,
378 result_ptr,
379 ) = Args::parse(args)?;
380 self.charge_host_function_call(
381 &host_function_costs.transfer_from_purse_to_account,
382 [
383 source_ptr,
384 source_size,
385 key_ptr,
386 key_size,
387 amount_ptr,
388 amount_size,
389 id_ptr,
390 id_size,
391 result_ptr,
392 ],
393 )?;
394 let source_purse = {
395 let bytes = self.bytes_from_mem(source_ptr, source_size as usize)?;
396 bytesrepr::deserialize_from_slice(bytes).map_err(ExecError::BytesRepr)?
397 };
398 let account_hash: AccountHash = {
399 let bytes = self.bytes_from_mem(key_ptr, key_size as usize)?;
400 bytesrepr::deserialize_from_slice(bytes).map_err(ExecError::BytesRepr)?
401 };
402 let amount: U512 = {
403 let bytes = self.bytes_from_mem(amount_ptr, amount_size as usize)?;
404 bytesrepr::deserialize_from_slice(bytes).map_err(ExecError::BytesRepr)?
405 };
406 let id: Option<u64> = {
407 let bytes = self.bytes_from_mem(id_ptr, id_size as usize)?;
408 bytesrepr::deserialize_from_slice(bytes).map_err(ExecError::BytesRepr)?
409 };
410 let ret = match self.transfer_from_purse_to_account_hash(
411 source_purse,
412 account_hash,
413 amount,
414 id,
415 )? {
416 Ok(transferred_to) => {
417 let result_value: u32 = transferred_to as u32;
418 let result_value_bytes = result_value.to_le_bytes();
419 self.try_get_memory()?
420 .set(result_ptr, &result_value_bytes)
421 .map_err(|error| ExecError::Interpreter(error.into()))?;
422 Ok(())
423 }
424 Err(api_error) => Err(api_error),
425 };
426 Ok(Some(RuntimeValue::I32(api_error::i32_from(ret))))
427 }
428
429 FunctionIndex::TransferFromPurseToPurseIndex => {
430 let (
439 source_ptr,
440 source_size,
441 target_ptr,
442 target_size,
443 amount_ptr,
444 amount_size,
445 id_ptr,
446 id_size,
447 ) = Args::parse(args)?;
448 self.charge_host_function_call(
449 &host_function_costs.transfer_from_purse_to_purse,
450 [
451 source_ptr,
452 source_size,
453 target_ptr,
454 target_size,
455 amount_ptr,
456 amount_size,
457 id_ptr,
458 id_size,
459 ],
460 )?;
461
462 let source: URef = {
463 let bytes = self.bytes_from_mem(source_ptr, source_size as usize)?;
464 bytesrepr::deserialize_from_slice(bytes).map_err(ExecError::BytesRepr)?
465 };
466
467 let target: URef = {
468 let bytes = self.bytes_from_mem(target_ptr, target_size as usize)?;
469 bytesrepr::deserialize_from_slice(bytes).map_err(ExecError::BytesRepr)?
470 };
471
472 let amount: U512 = {
473 let bytes = self.bytes_from_mem(amount_ptr, amount_size as usize)?;
474 bytesrepr::deserialize_from_slice(bytes).map_err(ExecError::BytesRepr)?
475 };
476
477 let id: Option<u64> = {
478 let bytes = self.bytes_from_mem(id_ptr, id_size as usize)?;
479 bytesrepr::deserialize_from_slice(bytes).map_err(ExecError::BytesRepr)?
480 };
481
482 let ret = self.transfer_from_purse_to_purse(source, target, amount, id)?;
483 Ok(Some(RuntimeValue::I32(api_error::i32_from(ret))))
484 }
485
486 FunctionIndex::GetBalanceIndex => {
487 let (ptr, ptr_size, output_size_ptr) = Args::parse(args)?;
491 self.charge_host_function_call(
492 &host_function_costs.get_balance,
493 [ptr, ptr_size, output_size_ptr],
494 )?;
495 let ret = self.get_balance_host_buffer(ptr, ptr_size as usize, output_size_ptr)?;
496 Ok(Some(RuntimeValue::I32(api_error::i32_from(ret))))
497 }
498
499 FunctionIndex::GetPhaseIndex => {
500 let (dest_ptr,) = Args::parse(args)?;
502 self.charge_host_function_call(&host_function_costs.get_phase, [dest_ptr])?;
503 self.get_phase(dest_ptr)?;
504 Ok(None)
505 }
506
507 FunctionIndex::GetSystemContractIndex => {
508 let (system_contract_index, dest_ptr, dest_size) = Args::parse(args)?;
512 self.charge_host_function_call(
513 &host_function_costs.get_system_contract,
514 [system_contract_index, dest_ptr, dest_size],
515 )?;
516 let ret = self.get_system_contract(system_contract_index, dest_ptr, dest_size)?;
517 Ok(Some(RuntimeValue::I32(api_error::i32_from(ret))))
518 }
519
520 FunctionIndex::GetMainPurseIndex => {
521 let (dest_ptr,) = Args::parse(args)?;
523 self.charge_host_function_call(&host_function_costs.get_main_purse, [dest_ptr])?;
524 self.get_main_purse(dest_ptr)?;
525 Ok(None)
526 }
527
528 FunctionIndex::ReadHostBufferIndex => {
529 let (dest_ptr, dest_size, bytes_written_ptr) = Args::parse(args)?;
531 self.charge_host_function_call(
532 &host_function_costs.read_host_buffer,
533 [dest_ptr, dest_size, bytes_written_ptr],
534 )?;
535 let ret = self.read_host_buffer(dest_ptr, dest_size as usize, bytes_written_ptr)?;
536 Ok(Some(RuntimeValue::I32(api_error::i32_from(ret))))
537 }
538
539 FunctionIndex::CreateContractPackageAtHash => {
540 let (hash_dest_ptr, access_dest_ptr, is_locked) = Args::parse(args)?;
544 self.charge_host_function_call(
545 &host_function_costs.create_contract_package_at_hash,
546 [hash_dest_ptr, access_dest_ptr],
547 )?;
548 let package_status = PackageStatus::new(is_locked);
549 let (hash_addr, access_addr) =
550 self.create_contract_package_at_hash(package_status)?;
551
552 self.function_address(hash_addr, hash_dest_ptr)?;
553 self.function_address(access_addr, access_dest_ptr)?;
554 Ok(None)
555 }
556
557 FunctionIndex::CreateContractUserGroup => {
558 let (
567 package_key_ptr,
568 package_key_size,
569 label_ptr,
570 label_size,
571 num_new_urefs,
572 existing_urefs_ptr,
573 existing_urefs_size,
574 output_size_ptr,
575 ) = Args::parse(args)?;
576
577 self.charge_host_function_call(
578 &host_function_costs.create_contract_user_group,
579 [
580 package_key_ptr,
581 package_key_size,
582 label_ptr,
583 label_size,
584 num_new_urefs,
585 existing_urefs_ptr,
586 existing_urefs_size,
587 output_size_ptr,
588 ],
589 )?;
590
591 let contract_package_hash: PackageHash =
592 self.t_from_mem(package_key_ptr, package_key_size)?;
593 let label: String = self.t_from_mem(label_ptr, label_size)?;
594 let existing_urefs: BTreeSet<URef> =
595 self.t_from_mem(existing_urefs_ptr, existing_urefs_size)?;
596
597 let ret = self.create_contract_user_group(
598 contract_package_hash,
599 label,
600 num_new_urefs,
601 existing_urefs,
602 output_size_ptr,
603 )?;
604 Ok(Some(RuntimeValue::I32(api_error::i32_from(ret))))
605 }
606
607 FunctionIndex::AddContractVersion => {
608 let (
618 contract_package_hash_ptr,
619 contract_package_hash_size,
620 version_ptr,
621 entry_points_ptr,
622 entry_points_size,
623 named_keys_ptr,
624 named_keys_size,
625 output_ptr,
626 output_size,
627 bytes_written_ptr,
628 ) = Args::parse(args)?;
629 self.charge_host_function_call(
630 &host_function_costs.add_contract_version,
631 [
632 contract_package_hash_ptr,
633 contract_package_hash_size,
634 version_ptr,
635 entry_points_ptr,
636 entry_points_size,
637 named_keys_ptr,
638 named_keys_size,
639 output_ptr,
640 output_size,
641 bytes_written_ptr,
642 ],
643 )?;
644
645 let contract_package_hash: ContractPackageHash =
646 self.t_from_mem(contract_package_hash_ptr, contract_package_hash_size)?;
647 let package_hash = PackageHash::new(contract_package_hash.value());
648 let entry_points: EntryPoints = {
649 let contract_entry_points: ContractEntryPoints =
650 self.t_from_mem(entry_points_ptr, entry_points_size)?;
651
652 let points: Vec<EntityEntryPoint> = contract_entry_points
653 .take_entry_points()
654 .into_iter()
655 .map(EntityEntryPoint::from)
656 .collect();
657
658 points.into()
659 };
660 let named_keys: NamedKeys = self.t_from_mem(named_keys_ptr, named_keys_size)?;
661 let ret = self.add_contract_version(
662 package_hash,
663 version_ptr,
664 entry_points,
665 named_keys,
666 BTreeMap::new(),
667 output_ptr,
668 )?;
669 Ok(Some(RuntimeValue::I32(api_error::i32_from(ret))))
670 }
671 FunctionIndex::AddContractVersionWithMessageTopics => {
672 let (
684 contract_package_hash_ptr,
685 contract_package_hash_size,
686 version_ptr,
687 entry_points_ptr,
688 entry_points_size,
689 named_keys_ptr,
690 named_keys_size,
691 message_topics_ptr,
692 message_topics_size,
693 output_ptr,
694 output_size,
695 ) = Args::parse(args)?;
696 self.charge_host_function_call(
697 &host_function_costs.add_contract_version_with_message_topics,
698 [
699 contract_package_hash_ptr,
700 contract_package_hash_size,
701 version_ptr,
702 entry_points_ptr,
703 entry_points_size,
704 named_keys_ptr,
705 named_keys_size,
706 message_topics_ptr,
707 message_topics_size,
708 output_ptr,
709 output_size,
710 ],
711 )?;
712
713 if output_size < 32 {
715 return Ok(Some(RuntimeValue::I32(api_error::i32_from(Err(
717 ApiError::BufferTooSmall,
718 )))));
719 }
720
721 let package_hash: PackageHash =
722 self.t_from_mem(contract_package_hash_ptr, contract_package_hash_size)?;
723 let entry_points: EntryPoints =
724 self.t_from_mem(entry_points_ptr, entry_points_size)?;
725 let named_keys: NamedKeys = self.t_from_mem(named_keys_ptr, named_keys_size)?;
726 let message_topics: BTreeMap<String, MessageTopicOperation> =
727 self.t_from_mem(message_topics_ptr, message_topics_size)?;
728
729 let message_limits = self.context.engine_config().wasm_config().messages_limits();
732 for (topic_name, _) in
733 message_topics
734 .iter()
735 .filter(|(_, operation)| match operation {
736 MessageTopicOperation::Add => true,
737 })
738 {
739 if topic_name.len() > message_limits.max_topic_name_size() as usize {
740 return Ok(Some(RuntimeValue::I32(api_error::i32_from(Err(
741 ApiError::MaxTopicNameSizeExceeded,
742 )))));
743 }
744 }
745
746 let ret = self.add_contract_version(
747 package_hash,
748 version_ptr,
749 entry_points,
750 named_keys,
751 message_topics,
752 output_ptr,
753 )?;
754 Ok(Some(RuntimeValue::I32(api_error::i32_from(ret))))
755 }
756
757 FunctionIndex::AddPackageVersionWithMessageTopics => {
758 let (
770 contract_package_hash_ptr,
771 contract_package_hash_size,
772 version_ptr,
773 entry_points_ptr,
774 entry_points_size,
775 named_keys_ptr,
776 named_keys_size,
777 message_topics,
778 message_topics_size,
779 output_ptr,
780 output_size,
781 ) = Args::parse(args)?;
782
783 self.charge_host_function_call(
784 &host_function_costs.add_package_version_with_message_topics,
785 [
786 contract_package_hash_ptr,
787 contract_package_hash_size,
788 version_ptr,
789 entry_points_ptr,
790 entry_points_size,
791 named_keys_ptr,
792 named_keys_size,
793 message_topics,
794 message_topics_size,
795 output_ptr,
796 output_size,
797 ],
798 )?;
799
800 if output_size < 32 {
802 return Ok(Some(RuntimeValue::I32(api_error::i32_from(Err(
804 ApiError::BufferTooSmall,
805 )))));
806 }
807
808 let package_hash: PackageHash =
809 self.t_from_mem(contract_package_hash_ptr, contract_package_hash_size)?;
810 let entry_points: EntryPoints =
811 self.t_from_mem(entry_points_ptr, entry_points_size)?;
812 let named_keys: NamedKeys = self.t_from_mem(named_keys_ptr, named_keys_size)?;
813 let message_topics: BTreeMap<String, MessageTopicOperation> =
814 self.t_from_mem(message_topics, message_topics_size)?;
815
816 let message_limits = self.context.engine_config().wasm_config().messages_limits();
819 for (topic_name, _) in
820 message_topics
821 .iter()
822 .filter(|(_, operation)| match operation {
823 MessageTopicOperation::Add => true,
824 })
825 {
826 if topic_name.len() > message_limits.max_topic_name_size() as usize {
827 return Ok(Some(RuntimeValue::I32(api_error::i32_from(Err(
828 ApiError::MaxTopicNameSizeExceeded,
829 )))));
830 }
831 }
832
833 let ret = self.add_contract_version(
834 package_hash,
835 version_ptr,
836 entry_points,
837 named_keys,
838 message_topics,
839 output_ptr,
840 )?;
841 Ok(Some(RuntimeValue::I32(api_error::i32_from(ret))))
842 }
843
844 FunctionIndex::DisableContractVersion => {
845 let (package_key_ptr, package_key_size, contract_hash_ptr, contract_hash_size) =
850 Args::parse(args)?;
851 self.charge_host_function_call(
852 &host_function_costs.disable_contract_version,
853 [
854 package_key_ptr,
855 package_key_size,
856 contract_hash_ptr,
857 contract_hash_size,
858 ],
859 )?;
860 let contract_package_hash = self.t_from_mem(package_key_ptr, package_key_size)?;
861 let contract_hash = self.t_from_mem(contract_hash_ptr, contract_hash_size)?;
862
863 let result = self.disable_contract_version(contract_package_hash, contract_hash)?;
864
865 Ok(Some(RuntimeValue::I32(api_error::i32_from(result))))
866 }
867
868 FunctionIndex::CallContractFuncIndex => {
869 let (
877 contract_hash_ptr,
878 contract_hash_size,
879 entry_point_name_ptr,
880 entry_point_name_size,
881 args_ptr,
882 args_size,
883 result_size_ptr,
884 ) = Args::parse(args)?;
885 self.charge_host_function_call(
886 &host_function_costs.call_contract,
887 [
888 contract_hash_ptr,
889 contract_hash_size,
890 entry_point_name_ptr,
891 entry_point_name_size,
892 args_ptr,
893 args_size,
894 result_size_ptr,
895 ],
896 )?;
897
898 let contract_hash: AddressableEntityHash =
899 self.t_from_mem(contract_hash_ptr, contract_hash_size)?;
900 let entry_point_name: String =
901 self.t_from_mem(entry_point_name_ptr, entry_point_name_size)?;
902 let args_bytes: Vec<u8> = {
903 let args_size: u32 = args_size;
904 self.bytes_from_mem(args_ptr, args_size as usize)?.to_vec()
905 };
906
907 let ret = self.call_contract_host_buffer(
908 contract_hash,
909 &entry_point_name,
910 &args_bytes,
911 result_size_ptr,
912 )?;
913 Ok(Some(RuntimeValue::I32(api_error::i32_from(ret))))
914 }
915
916 FunctionIndex::CallVersionedContract => {
917 let (
927 contract_package_hash_ptr,
928 contract_package_hash_size,
929 contract_version_ptr,
930 contract_package_size,
931 entry_point_name_ptr,
932 entry_point_name_size,
933 args_ptr,
934 args_size,
935 result_size_ptr,
936 ) = Args::parse(args)?;
937 self.charge_host_function_call(
938 &host_function_costs.call_versioned_contract,
939 [
940 contract_package_hash_ptr,
941 contract_package_hash_size,
942 contract_version_ptr,
943 contract_package_size,
944 entry_point_name_ptr,
945 entry_point_name_size,
946 args_ptr,
947 args_size,
948 result_size_ptr,
949 ],
950 )?;
951
952 let contract_package_hash: PackageHash =
953 self.t_from_mem(contract_package_hash_ptr, contract_package_hash_size)?;
954 let contract_version: Option<EntityVersion> =
955 self.t_from_mem(contract_version_ptr, contract_package_size)?;
956 let entry_point_name: String =
957 self.t_from_mem(entry_point_name_ptr, entry_point_name_size)?;
958 let args_bytes: Vec<u8> = {
959 let args_size: u32 = args_size;
960 self.bytes_from_mem(args_ptr, args_size as usize)?.to_vec()
961 };
962
963 let ret = self.call_versioned_contract_host_buffer(
964 contract_package_hash,
965 contract_version,
966 entry_point_name,
967 &args_bytes,
968 result_size_ptr,
969 )?;
970 Ok(Some(RuntimeValue::I32(api_error::i32_from(ret))))
971 }
972
973 #[cfg(feature = "test-support")]
974 FunctionIndex::PrintIndex => {
975 let (text_ptr, text_size) = Args::parse(args)?;
976 self.charge_host_function_call(&host_function_costs.print, [text_ptr, text_size])?;
977 self.print(text_ptr, text_size)?;
978 Ok(None)
979 }
980
981 FunctionIndex::GetRuntimeArgsizeIndex => {
982 let (name_ptr, name_size, size_ptr) = Args::parse(args)?;
986 self.charge_host_function_call(
987 &host_function_costs.get_named_arg_size,
988 [name_ptr, name_size, size_ptr],
989 )?;
990 let ret = self.get_named_arg_size(name_ptr, name_size as usize, size_ptr)?;
991 Ok(Some(RuntimeValue::I32(api_error::i32_from(ret))))
992 }
993
994 FunctionIndex::GetRuntimeArgIndex => {
995 let (name_ptr, name_size, dest_ptr, dest_size) = Args::parse(args)?;
1000 self.charge_host_function_call(
1001 &host_function_costs.get_named_arg,
1002 [name_ptr, name_size, dest_ptr, dest_size],
1003 )?;
1004 let ret =
1005 self.get_named_arg(name_ptr, name_size as usize, dest_ptr, dest_size as usize)?;
1006 Ok(Some(RuntimeValue::I32(api_error::i32_from(ret))))
1007 }
1008
1009 FunctionIndex::RemoveContractUserGroupIndex => {
1010 let (package_key_ptr, package_key_size, label_ptr, label_size) = Args::parse(args)?;
1015 self.charge_host_function_call(
1016 &host_function_costs.remove_contract_user_group,
1017 [package_key_ptr, package_key_size, label_ptr, label_size],
1018 )?;
1019 let package_key = self.t_from_mem(package_key_ptr, package_key_size)?;
1020 let label: Group = self.t_from_mem(label_ptr, label_size)?;
1021
1022 let ret = self.remove_contract_user_group(package_key, label)?;
1023 Ok(Some(RuntimeValue::I32(api_error::i32_from(ret))))
1024 }
1025
1026 FunctionIndex::ExtendContractUserGroupURefsIndex => {
1027 let (package_ptr, package_size, label_ptr, label_size, value_size_ptr) =
1033 Args::parse(args)?;
1034
1035 self.charge_host_function_call(
1036 &host_function_costs.provision_contract_user_group_uref,
1037 [
1038 package_ptr,
1039 package_size,
1040 label_ptr,
1041 label_size,
1042 value_size_ptr,
1043 ],
1044 )?;
1045 let ret = self.provision_contract_user_group_uref(
1046 package_ptr,
1047 package_size,
1048 label_ptr,
1049 label_size,
1050 value_size_ptr,
1051 )?;
1052 Ok(Some(RuntimeValue::I32(api_error::i32_from(ret))))
1053 }
1054
1055 FunctionIndex::RemoveContractUserGroupURefsIndex => {
1056 let (package_ptr, package_size, label_ptr, label_size, urefs_ptr, urefs_size) =
1063 Args::parse(args)?;
1064 self.charge_host_function_call(
1065 &host_function_costs.remove_contract_user_group_urefs,
1066 [
1067 package_ptr,
1068 package_size,
1069 label_ptr,
1070 label_size,
1071 urefs_ptr,
1072 urefs_size,
1073 ],
1074 )?;
1075 let ret = self.remove_contract_user_group_urefs(
1076 package_ptr,
1077 package_size,
1078 label_ptr,
1079 label_size,
1080 urefs_ptr,
1081 urefs_size,
1082 )?;
1083 Ok(Some(RuntimeValue::I32(api_error::i32_from(ret))))
1084 }
1085
1086 FunctionIndex::Blake2b => {
1087 let (in_ptr, in_size, out_ptr, out_size) = Args::parse(args)?;
1088 self.charge_host_function_call(
1089 &host_function_costs.blake2b,
1090 [in_ptr, in_size, out_ptr, out_size],
1091 )?;
1092 let digest =
1093 self.checked_memory_slice(in_ptr as usize, in_size as usize, |input| {
1094 cryptography::blake2b(input)
1095 })?;
1096
1097 let result = if digest.len() != out_size as usize {
1098 Err(ApiError::BufferTooSmall)
1099 } else {
1100 Ok(())
1101 };
1102 if result.is_err() {
1103 return Ok(Some(RuntimeValue::I32(api_error::i32_from(result))));
1104 }
1105
1106 self.try_get_memory()?
1107 .set(out_ptr, &digest)
1108 .map_err(|error| ExecError::Interpreter(error.into()))?;
1109 Ok(Some(RuntimeValue::I32(0)))
1110 }
1111
1112 FunctionIndex::NewDictionaryFuncIndex => {
1113 let (output_size_ptr,): (u32,) = Args::parse(args)?;
1115 const UREF_LEN: u32 = 33u32;
1116 self.charge_host_function_call(&host_function_costs.new_uref, [0, 0, UREF_LEN])?;
1117 let ret = self.new_dictionary(output_size_ptr)?;
1118 Ok(Some(RuntimeValue::I32(api_error::i32_from(ret))))
1119 }
1120
1121 FunctionIndex::DictionaryGetFuncIndex => {
1122 let (uref_ptr, uref_size, key_bytes_ptr, key_bytes_size, output_size_ptr): (
1128 _,
1129 u32,
1130 _,
1131 u32,
1132 _,
1133 ) = Args::parse(args)?;
1134 self.charge_host_function_call(
1135 &host_function_costs.dictionary_get,
1136 [key_bytes_ptr, key_bytes_size, output_size_ptr],
1137 )?;
1138 let ret = self.dictionary_get(
1139 uref_ptr,
1140 uref_size,
1141 key_bytes_ptr,
1142 key_bytes_size,
1143 output_size_ptr,
1144 )?;
1145 Ok(Some(RuntimeValue::I32(api_error::i32_from(ret))))
1146 }
1147
1148 FunctionIndex::DictionaryPutFuncIndex => {
1149 let (uref_ptr, uref_size, key_bytes_ptr, key_bytes_size, value_ptr, value_ptr_size): (_, u32, _, u32, _, u32) = Args::parse(args)?;
1156 self.charge_host_function_call(
1157 &host_function_costs.dictionary_put,
1158 [key_bytes_ptr, key_bytes_size, value_ptr, value_ptr_size],
1159 )?;
1160 let ret = self.dictionary_put(
1161 uref_ptr,
1162 uref_size,
1163 key_bytes_ptr,
1164 key_bytes_size,
1165 value_ptr,
1166 value_ptr_size,
1167 )?;
1168 Ok(Some(RuntimeValue::I32(api_error::i32_from(ret))))
1169 }
1170
1171 FunctionIndex::DictionaryReadFuncIndex => {
1172 let (key_ptr, key_size, output_size_ptr) = Args::parse(args)?;
1176 self.charge_host_function_call(
1177 &host_function_costs.read_value,
1178 [key_ptr, key_size, output_size_ptr],
1179 )?;
1180 let ret = self.dictionary_read(key_ptr, key_size, output_size_ptr)?;
1181 Ok(Some(RuntimeValue::I32(api_error::i32_from(ret))))
1182 }
1183
1184 FunctionIndex::LoadCallStack => {
1185 let (call_stack_len_ptr, result_size_ptr) = Args::parse(args)?;
1188
1189 self.charge_host_function_call(
1190 &HostFunction::fixed(10_000),
1191 [call_stack_len_ptr, result_size_ptr],
1192 )?;
1193 let ret = self.load_call_stack(call_stack_len_ptr, result_size_ptr)?;
1194 Ok(Some(RuntimeValue::I32(api_error::i32_from(ret))))
1195 }
1196
1197 FunctionIndex::LoadCallerInformation => {
1198 let (action, call_stack_len_ptr, result_size_ptr) = Args::parse(args)?;
1202 self.charge_host_function_call(
1203 &HostFunction::fixed(10_000),
1204 [0, call_stack_len_ptr, result_size_ptr],
1205 )?;
1206 let ret =
1207 self.load_caller_information(action, call_stack_len_ptr, result_size_ptr)?;
1208 Ok(Some(RuntimeValue::I32(api_error::i32_from(ret))))
1209 }
1210
1211 FunctionIndex::LoadAuthorizationKeys => {
1212 let (len_ptr, result_size_ptr) = Args::parse(args)?;
1215 self.charge_host_function_call(
1216 &HostFunction::fixed(10_000),
1217 [len_ptr, result_size_ptr],
1218 )?;
1219 let ret = self.load_authorization_keys(len_ptr, result_size_ptr)?;
1220 Ok(Some(RuntimeValue::I32(api_error::i32_from(ret))))
1221 }
1222
1223 FunctionIndex::RandomBytes => {
1224 let (out_ptr, out_size) = Args::parse(args)?;
1225 self.charge_host_function_call(
1226 &host_function_costs.random_bytes,
1227 [out_ptr, out_size],
1228 )?;
1229
1230 let random_bytes = self.context.random_bytes()?;
1231
1232 let result = if random_bytes.len() != out_size as usize {
1233 Err(ApiError::BufferTooSmall)
1234 } else {
1235 Ok(())
1236 };
1237 if result.is_err() {
1238 return Ok(Some(RuntimeValue::I32(api_error::i32_from(result))));
1239 }
1240
1241 self.try_get_memory()?
1242 .set(out_ptr, &random_bytes)
1243 .map_err(|error| ExecError::Interpreter(error.into()))?;
1244
1245 Ok(Some(RuntimeValue::I32(0)))
1246 }
1247
1248 FunctionIndex::EnableContractVersion => {
1249 let (package_key_ptr, package_key_size, contract_hash_ptr, contract_hash_size) =
1254 Args::parse(args)?;
1255 self.charge_host_function_call(
1256 &host_function_costs.enable_contract_version,
1257 [
1258 package_key_ptr,
1259 package_key_size,
1260 contract_hash_ptr,
1261 contract_hash_size,
1262 ],
1263 )?;
1264 let contract_package_hash = self.t_from_mem(package_key_ptr, package_key_size)?;
1265 let contract_hash = self.t_from_mem(contract_hash_ptr, contract_hash_size)?;
1266
1267 let result = self.enable_contract_version(contract_package_hash, contract_hash)?;
1268
1269 Ok(Some(RuntimeValue::I32(api_error::i32_from(result))))
1270 }
1271
1272 FunctionIndex::ManageMessageTopic => {
1273 let (topic_name_ptr, topic_name_size, operation_ptr, operation_size) =
1278 Args::parse(args)?;
1279 self.charge_host_function_call(
1280 &host_function_costs.manage_message_topic,
1281 [
1282 topic_name_ptr,
1283 topic_name_size,
1284 operation_ptr,
1285 operation_size,
1286 ],
1287 )?;
1288
1289 let limits = self.context.engine_config().wasm_config().messages_limits();
1290
1291 if topic_name_size > limits.max_topic_name_size() {
1292 return Ok(Some(RuntimeValue::I32(api_error::i32_from(Err(
1293 ApiError::MaxTopicNameSizeExceeded,
1294 )))));
1295 }
1296
1297 let topic_name_bytes =
1298 self.bytes_from_mem(topic_name_ptr, topic_name_size as usize)?;
1299 let topic_name = std::str::from_utf8(&topic_name_bytes)
1300 .map_err(|e| Trap::from(ExecError::InvalidUtf8Encoding(e)))?;
1301
1302 if operation_size as usize > MessageTopicOperation::max_serialized_len() {
1303 return Err(Trap::from(ExecError::InvalidImputedOperation));
1304 }
1305 let topic_operation = self
1306 .t_from_mem(operation_ptr, operation_size)
1307 .map_err(|_e| Trap::from(ExecError::InvalidImputedOperation))?;
1308
1309 if !self.context.get_context_key().is_smart_contract_key() {
1311 return Err(Trap::from(ExecError::InvalidContext));
1312 }
1313
1314 let result = match topic_operation {
1315 MessageTopicOperation::Add => {
1316 self.add_message_topic(topic_name).map_err(Trap::from)?
1317 }
1318 };
1319
1320 Ok(Some(RuntimeValue::I32(api_error::i32_from(result))))
1321 }
1322
1323 FunctionIndex::EmitMessage => {
1324 let (topic_name_ptr, topic_name_size, message_ptr, message_size) =
1329 Args::parse(args)?;
1330
1331 self.context
1334 .charge_gas(Gas::new(self.context.emit_message_cost()))?;
1335 self.charge_host_function_call(
1337 &HostFunction::new(0, host_function_costs.emit_message.arguments()),
1338 &[topic_name_ptr, topic_name_size, message_ptr, message_size],
1339 )?;
1340
1341 let limits = self.context.engine_config().wasm_config().messages_limits();
1342
1343 if topic_name_size > limits.max_topic_name_size() {
1344 return Ok(Some(RuntimeValue::I32(api_error::i32_from(Err(
1345 ApiError::MaxTopicNameSizeExceeded,
1346 )))));
1347 }
1348
1349 if message_size > limits.max_message_size() {
1350 return Ok(Some(RuntimeValue::I32(api_error::i32_from(Err(
1351 ApiError::MessageTooLarge,
1352 )))));
1353 }
1354
1355 let topic_name_bytes =
1356 self.bytes_from_mem(topic_name_ptr, topic_name_size as usize)?;
1357 let topic_name = std::str::from_utf8(&topic_name_bytes)
1358 .map_err(|e| Trap::from(ExecError::InvalidUtf8Encoding(e)))?;
1359
1360 let message = self.t_from_mem(message_ptr, message_size)?;
1361
1362 let result = self.emit_message(topic_name, message)?;
1363 if result.is_ok() {
1364 let new_cost = self
1366 .context
1367 .emit_message_cost()
1368 .checked_add(host_function_costs.cost_increase_per_message.into())
1369 .ok_or(ExecError::GasLimit)?;
1370 self.context.set_emit_message_cost(new_cost);
1371 }
1372 Ok(Some(RuntimeValue::I32(api_error::i32_from(result))))
1373 }
1374
1375 FunctionIndex::GetBlockInfoIndex => {
1376 let (field_idx, dest_ptr): (u8, u32) = Args::parse(args)?;
1379
1380 self.charge_host_function_call(&host_function_costs.get_block_info, [0u32, 0u32])?;
1381 self.get_block_info(field_idx, dest_ptr)?;
1382 Ok(None)
1383 }
1384
1385 FunctionIndex::GenericHash => {
1386 let (in_ptr, in_size, hash_algo_type, out_ptr, out_size) = Args::parse(args)?;
1392 self.charge_host_function_call(
1393 &host_function_costs.generic_hash,
1394 [in_ptr, in_size, hash_algo_type, out_ptr, out_size],
1395 )?;
1396 let hash_algo_type = match HashAlgorithm::try_from(hash_algo_type as u8) {
1397 Ok(v) => v,
1398 Err(_e) => {
1399 return Ok(Some(RuntimeValue::I32(api_error::i32_from(Err(
1400 ApiError::InvalidArgument,
1401 )))))
1402 }
1403 };
1404
1405 let digest =
1406 self.checked_memory_slice(in_ptr as usize, in_size as usize, |input| {
1407 match hash_algo_type {
1408 HashAlgorithm::Blake2b => cryptography::blake2b(input),
1409 HashAlgorithm::Blake3 => cryptography::blake3(input),
1410 HashAlgorithm::Sha256 => cryptography::sha256(input),
1411 }
1412 })?;
1413
1414 let result = if digest.len() > out_size as usize {
1415 Err(ApiError::BufferTooSmall)
1416 } else {
1417 Ok(())
1418 };
1419
1420 if result.is_err() {
1421 return Ok(Some(RuntimeValue::I32(api_error::i32_from(result))));
1422 }
1423
1424 if self.try_get_memory()?.set(out_ptr, &digest).is_err() {
1425 return Ok(Some(RuntimeValue::I32(
1426 u32::from(ApiError::HostBufferEmpty) as i32,
1427 )));
1428 }
1429
1430 Ok(Some(RuntimeValue::I32(0)))
1431 }
1432
1433 FunctionIndex::RecoverSecp256k1 => {
1434 let (
1442 data_ptr,
1443 data_size,
1444 signature_ptr,
1445 signature_size,
1446 public_key_ptr,
1447 recovery_id,
1448 ) = Args::parse(args)?;
1449
1450 self.charge_host_function_call(
1451 &host_function_costs.recover_secp256k1,
1452 [
1453 data_ptr,
1454 data_size,
1455 signature_ptr,
1456 signature_size,
1457 public_key_ptr,
1458 recovery_id,
1459 ],
1460 )?;
1461
1462 if recovery_id >= 4 {
1463 return Ok(Some(RuntimeValue::I32(
1464 u32::from(ApiError::InvalidArgument) as i32,
1465 )));
1466 }
1467
1468 let data = self.bytes_from_mem(data_ptr, data_size as usize)?;
1469 let signature: Signature = self.t_from_mem(signature_ptr, signature_size)?;
1470
1471 let Ok(public_key) =
1472 casper_types::crypto::recover_secp256k1(data, &signature, recovery_id as u8)
1473 else {
1474 return Ok(Some(RuntimeValue::I32(
1475 u32::from(ApiError::InvalidArgument) as i32,
1476 )));
1477 };
1478
1479 let Ok(key_bytes) = public_key.to_bytes() else {
1480 return Ok(Some(RuntimeValue::I32(
1481 u32::from(ApiError::OutOfMemory) as i32
1482 )));
1483 };
1484
1485 if self
1486 .try_get_memory()?
1487 .set(public_key_ptr, &key_bytes)
1488 .is_err()
1489 {
1490 return Ok(Some(RuntimeValue::I32(
1491 u32::from(ApiError::HostBufferEmpty) as i32,
1492 )));
1493 }
1494
1495 Ok(Some(RuntimeValue::I32(0)))
1496 }
1497
1498 FunctionIndex::VerifySignature => {
1499 let (
1506 message_ptr,
1507 message_size,
1508 signature_ptr,
1509 signature_size,
1510 public_key_ptr,
1511 public_key_size,
1512 ) = Args::parse(args)?;
1513
1514 self.charge_host_function_call(
1515 &host_function_costs.verify_signature,
1516 [
1517 message_ptr,
1518 message_size,
1519 signature_ptr,
1520 signature_size,
1521 public_key_ptr,
1522 public_key_size,
1523 ],
1524 )?;
1525
1526 let message = self.bytes_from_mem(message_ptr, message_size as usize)?;
1527 let signature: Signature = self.t_from_mem(signature_ptr, signature_size)?;
1528 let public_key: PublicKey = self.t_from_mem(public_key_ptr, public_key_size)?;
1529
1530 if casper_types::crypto::verify(message, &signature, &public_key).is_err() {
1531 return Ok(Some(RuntimeValue::I32(
1532 u32::from(ApiError::InvalidArgument) as i32,
1533 )));
1534 }
1535
1536 Ok(Some(RuntimeValue::I32(0)))
1537 }
1538 FunctionIndex::CallPackageVersion => {
1539 let (
1551 contract_package_hash_ptr,
1552 contract_package_hash_size,
1553 major_version_ptr,
1554 major_version_size,
1555 contract_version_ptr,
1556 contract_version_size,
1557 entry_point_name_ptr,
1558 entry_point_name_size,
1559 args_ptr,
1560 args_size,
1561 result_size_ptr,
1562 ) = Args::parse(args)?;
1563 self.charge_host_function_call(
1564 &host_function_costs.call_package_version,
1565 [
1566 contract_package_hash_ptr,
1567 contract_package_hash_size,
1568 major_version_ptr,
1569 major_version_size,
1570 contract_version_ptr,
1571 contract_version_size,
1572 entry_point_name_ptr,
1573 entry_point_name_size,
1574 args_ptr,
1575 args_size,
1576 result_size_ptr,
1577 ],
1578 )?;
1579
1580 let contract_package_hash: PackageHash =
1581 self.t_from_mem(contract_package_hash_ptr, contract_package_hash_size)?;
1582 let contract_version: Option<EntityVersion> =
1583 self.t_from_mem(contract_version_ptr, contract_version_size)?;
1584 let major_version: Option<ProtocolVersionMajor> =
1585 self.t_from_mem(major_version_ptr, major_version_size)?;
1586 let entry_point_name: String =
1587 self.t_from_mem(entry_point_name_ptr, entry_point_name_size)?;
1588 let args_bytes: Vec<u8> = {
1589 let args_size: u32 = args_size;
1590 self.bytes_from_mem(args_ptr, args_size as usize)?.to_vec()
1591 };
1592
1593 let ret = self.call_package_version_host_buffer(
1594 contract_package_hash,
1595 major_version,
1596 contract_version,
1597 entry_point_name,
1598 &args_bytes,
1599 result_size_ptr,
1600 )?;
1601 Ok(Some(RuntimeValue::I32(api_error::i32_from(ret))))
1602 }
1603 }
1604 }
1605}