@@ -2,7 +2,6 @@ use std::fmt::{self, Display};
22use std:: io:: { Cursor , Write as _} ;
33use std:: ops:: { AddAssign , SubAssign } ;
44
5- use crate :: vm:: ExecutionCost ;
65use stacks_common:: types:: StacksEpochId ;
76use stacks_common:: types:: chainstate:: StacksBlockId ;
87use stacks_common:: util:: hash:: { Keccak256Hash , Sha512Sum , Sha512Trunc256Sum } ;
@@ -32,7 +31,7 @@ use crate::vm::errors::{RuntimeCheckErrorKind, RuntimeError, VmExecutionError, W
3231use crate :: vm:: types:: {
3332 BufferLength , SequenceSubtype , SequencedValue , StringSubtype , TypeSignature , TypeSignatureExt ,
3433} ;
35- use crate :: vm:: { ClarityName , ContractContext , CostErrors , Value } ;
34+ use crate :: vm:: { ClarityName , ContractContext , CostErrors , ExecutionCost , Value } ;
3635
3736enum MintAssetErrorCodes {
3837 ALREADY_EXIST = 1 ,
@@ -473,75 +472,6 @@ pub fn initialize_contract(
473472 }
474473}
475474
476- // Charge the cost of contract call analog to the UserFunctionApplication and InnerTypeCheckCost in the interpreter.
477- // UserFunctionApplication charge proportionally to the number of arguments passed to the contract call.
478- // InnerTypeCheckCost charge proportionally to the cumulative size of each argument's type.
479- fn apply_contract_call_cost (
480- instance : & Instance ,
481- store : & mut impl AsContextMut ,
482- contract_context : & ContractContext ,
483- epoch_id : & StacksEpochId ,
484- number_of_arguments : u32 ,
485- total_size_of_parameters : u32 ,
486- ) -> Result < ( ) , VmExecutionError > {
487- let function_name = ".contract-call-cost-overhead" ;
488- let func = instance
489- . get_func ( & mut store. as_context_mut ( ) , function_name)
490- . ok_or ( RuntimeCheckErrorKind :: UndefinedFunction (
491- function_name. into ( ) ,
492- ) ) ?;
493-
494- // Access the global stack pointer from the instance
495- let stack_pointer = instance
496- . get_global ( & mut store. as_context_mut ( ) , "stack-pointer" )
497- . ok_or ( VmExecutionError :: Wasm ( WasmError :: GlobalNotFound (
498- "stack-pointer" . to_string ( ) ,
499- ) ) ) ?;
500-
501- let offset = stack_pointer
502- . get ( & mut store. as_context_mut ( ) )
503- . i32 ( )
504- . ok_or ( VmExecutionError :: Wasm ( WasmError :: ValueTypeMismatch ) ) ?;
505-
506- let memory = instance
507- . get_memory ( & mut store. as_context_mut ( ) , "memory" )
508- . ok_or ( VmExecutionError :: Wasm ( WasmError :: MemoryNotFound ) ) ?;
509-
510- // Determine how much space is needed for arguments
511- //4 byte for an i32
512- let arg_size = 2 * 4 ;
513-
514- let in_mem_offset = offset + arg_size;
515-
516- ensure_memory ( & memory, & mut store. as_context_mut ( ) , in_mem_offset as usize ) ?;
517-
518- // Convert the args into wasmtime values
519- let wasm_args = vec ! [
520- Val :: I32 ( number_of_arguments as i32 ) ,
521- Val :: I32 ( total_size_of_parameters as i32 ) ,
522- ] ;
523-
524- // Update the stack pointer after space is reserved for the arguments and
525- // return values.
526- stack_pointer
527- . set ( & mut store. as_context_mut ( ) , Val :: I32 ( offset) )
528- . map_err ( |e| VmExecutionError :: Wasm ( WasmError :: Runtime ( e) ) ) ?;
529-
530- // Call the function
531- func. call ( & mut store. as_context_mut ( ) , & wasm_args, & mut [ ] )
532- . map_err ( |e| {
533- error_mapping:: resolve_error (
534- e,
535- * instance,
536- & mut store. as_context_mut ( ) ,
537- epoch_id,
538- contract_context. get_clarity_version ( ) ,
539- )
540- } ) ?;
541-
542- Ok ( ( ) )
543- }
544-
545475/// Call a function in the contract.
546476#[ allow( clippy:: too_many_arguments) ]
547477pub fn call_function < ' a > (
@@ -600,25 +530,6 @@ pub fn call_function<'a>(
600530 . instantiate ( & mut store, & module)
601531 . map_err ( |e| VmExecutionError :: Wasm ( WasmError :: UnableToLoadModule ( e) ) ) ?;
602532
603- let mut total_size = 0 ;
604- for arg in func_types. get_arg_types ( ) {
605- total_size += arg. size ( ) ?;
606- }
607-
608- apply_contract_call_cost (
609- & instance,
610- & mut store. as_context_mut ( ) ,
611- contract_context,
612- & epoch,
613- args. len ( ) as u32 ,
614- total_size,
615- ) ?;
616-
617- // Call the specified function
618- let func = instance. get_func ( & mut store, function_name) . ok_or (
619- RuntimeCheckErrorKind :: UndefinedFunction ( function_name. to_string ( ) ) ,
620- ) ?;
621-
622533 // Access the global stack pointer from the instance
623534 let stack_pointer =
624535 instance
@@ -641,12 +552,6 @@ pub fn call_function<'a>(
641552 . get_memory ( & mut store, "memory" )
642553 . ok_or ( VmExecutionError :: Wasm ( WasmError :: MemoryNotFound ) ) ?;
643554
644- let return_type = func_types
645- . get_return_type ( )
646- . as_ref ( )
647- . ok_or ( VmExecutionError :: Wasm ( WasmError :: ExpectedReturnValue ) ) ?
648- . clone ( ) ;
649-
650555 // Validate argument count
651556 let expected_args = func_types. get_arg_types ( ) ;
652557 if args. len ( ) != expected_args. len ( ) {
@@ -677,8 +582,51 @@ pub fn call_function<'a>(
677582 total_required_bytes += get_required_bytes ( ty, arg) ?;
678583 }
679584
585+ // Space needed for the arguments to call the overhead cost for contract call
586+ //4 byte for an i32
587+ let total_required_bytes_contract_call = 8 ;
588+
589+ total_required_bytes = total_required_bytes. max ( total_required_bytes_contract_call) ;
590+
680591 ensure_memory ( & memory, & mut store, total_required_bytes + offset as usize ) ?;
681592
593+ // Before calling the function, we need to check if we have enough fuel to do so
594+ // Apply contract call cost
595+ let mut total_size_of_parameters = 0 ;
596+ for arg in func_types. get_arg_types ( ) {
597+ total_size_of_parameters += arg. size ( ) ?;
598+ }
599+ // Convert the args into wasmtime values
600+ let wasm_args = vec ! [
601+ Val :: I32 ( args. len( ) as i32 ) ,
602+ Val :: I32 ( total_size_of_parameters as i32 ) ,
603+ ] ;
604+
605+ let contract_call_cost_func = instance
606+ . get_func ( & mut store. as_context_mut ( ) , ".contract-call-cost-overhead" )
607+ . ok_or ( RuntimeCheckErrorKind :: UndefinedFunction (
608+ ".contract-call-cost-overhead" . into ( ) ,
609+ ) ) ?;
610+
611+ // Compute and spend contract call cost
612+ contract_call_cost_func
613+ . call ( & mut store. as_context_mut ( ) , & wasm_args, & mut [ ] )
614+ . map_err ( |e| {
615+ error_mapping:: resolve_error (
616+ e,
617+ instance,
618+ & mut store. as_context_mut ( ) ,
619+ & epoch,
620+ contract_context. get_clarity_version ( ) ,
621+ )
622+ } ) ?;
623+
624+ // Now that we checked if we had enough fuel to make the contract call
625+ // We call the specified function
626+ let func = instance. get_func ( & mut store, function_name) . ok_or (
627+ RuntimeCheckErrorKind :: UndefinedFunction ( function_name. to_string ( ) ) ,
628+ ) ?;
629+
682630 // Convert the args into wasmtime values
683631 let mut wasm_args = vec ! [ ] ;
684632 for ( arg, ty) in args. iter ( ) . zip ( expected_args) {
@@ -693,6 +641,12 @@ pub fn call_function<'a>(
693641 . set ( & mut store, Val :: I32 ( offset) )
694642 . map_err ( |e| VmExecutionError :: Wasm ( WasmError :: Runtime ( e) ) ) ?;
695643
644+ let return_type = func_types
645+ . get_return_type ( )
646+ . as_ref ( )
647+ . ok_or ( VmExecutionError :: Wasm ( WasmError :: ExpectedReturnValue ) ) ?
648+ . clone ( ) ;
649+
696650 // Call the function
697651 let mut results: Vec < _ > = clar2wasm_ty ( & return_type)
698652 . into_iter ( )
@@ -2306,17 +2260,17 @@ fn link_global<T>(
23062260 name : & str ,
23072261 value : Val ,
23082262) -> Result < Global , VmExecutionError > {
2309- let the_global = Global :: new (
2263+ let global_to_link = Global :: new (
23102264 store. as_context_mut ( ) ,
23112265 GlobalType :: new ( wasmtime:: ValType :: I64 , wasmtime:: Mutability :: Var ) ,
23122266 value,
23132267 )
23142268 . map_err ( |e| VmExecutionError :: Wasm ( WasmError :: UnableToLoadModule ( e) ) ) ?;
23152269
23162270 linker
2317- . define ( & mut store. as_context_mut ( ) , "clarity" , name, the_global )
2271+ . define ( & mut store. as_context_mut ( ) , "clarity" , name, global_to_link )
23182272 . map_err ( |e| VmExecutionError :: Wasm ( WasmError :: UnableToLoadModule ( e) ) ) ?;
2319- Ok ( the_global )
2273+ Ok ( global_to_link )
23202274}
23212275
23222276/// Link the host interface functions for into the Wasm module.
0 commit comments