@@ -564,7 +564,7 @@ pub fn call_function<'a, 'b, 'c>(
564
564
565
565
// Call the function
566
566
func. call ( & mut store, & wasm_args, & mut results)
567
- . map_err ( |e| error_mapping:: resolve_error ( e, instance, & mut store) ) ?;
567
+ . map_err ( |e| error_mapping:: resolve_error ( e, instance, & mut store, & epoch , & clarity_version ) ) ?;
568
568
569
569
// If the function returns a value, translate it into a Clarity `Value`
570
570
wasm_to_clarity_value ( & return_type, 0 , & results, memory, & mut & mut store, epoch)
@@ -7719,6 +7719,18 @@ mod error_mapping {
7719
7719
/// Indicates an attempt to use a name that is already in use, possibly for a variable or function.
7720
7720
NameAlreadyUsed = 9 ,
7721
7721
7722
+ /// Represents a short-return error for an expected value that wraps a Response type.
7723
+ /// Usually triggered by `(try!...)`.
7724
+ ShortReturnExpectedValueResponse = 10 ,
7725
+
7726
+ /// Represents a short-return error for an expected value that wraps an Optional type.
7727
+ /// Usually triggered by `(try!...)`.
7728
+ ShortReturnExpectedValueOptional = 11 ,
7729
+
7730
+ /// Represents a short-return error for an expected value.
7731
+ /// usually triggered by `(unwrap!...)` and `(unwrap-err!...)`.
7732
+ ShortReturnExpectedValue = 12 ,
7733
+
7722
7734
/// A catch-all for errors that are not mapped to specific error codes.
7723
7735
/// This might be used for unexpected or unclassified errors.
7724
7736
NotMapped = 99 ,
@@ -7738,15 +7750,20 @@ mod error_mapping {
7738
7750
7 => ErrorMap :: ShortReturnAssertionFailure ,
7739
7751
8 => ErrorMap :: ArithmeticPowError ,
7740
7752
9 => ErrorMap :: NameAlreadyUsed ,
7753
+ 10 => ErrorMap :: ShortReturnExpectedValueResponse ,
7754
+ 11 => ErrorMap :: ShortReturnExpectedValueOptional ,
7755
+ 12 => ErrorMap :: ShortReturnExpectedValue ,
7741
7756
_ => ErrorMap :: NotMapped ,
7742
7757
}
7743
7758
}
7744
7759
}
7745
7760
7746
- pub fn resolve_error (
7761
+ pub ( crate ) fn resolve_error (
7747
7762
e : wasmtime:: Error ,
7748
7763
instance : Instance ,
7749
7764
mut store : impl AsContextMut ,
7765
+ epoch_id : & StacksEpochId ,
7766
+ clarity_version : & ClarityVersion ,
7750
7767
) -> Error {
7751
7768
if let Some ( vm_error) = e. root_cause ( ) . downcast_ref :: < Error > ( ) {
7752
7769
// SAFETY:
@@ -7804,23 +7821,32 @@ mod error_mapping {
7804
7821
// In this case, runtime errors are handled
7805
7822
// by being mapped to the corresponding ClarityWasm Errors.
7806
7823
if let Some ( Trap :: UnreachableCodeReached ) = e. root_cause ( ) . downcast_ref :: < Trap > ( ) {
7807
- return from_runtime_error_code ( instance, & mut store, e) ;
7824
+ return from_runtime_error_code ( instance, & mut store, e, epoch_id , clarity_version ) ;
7808
7825
}
7809
7826
7810
7827
// All other errors are treated as general runtime errors.
7811
7828
Error :: Wasm ( WasmError :: Runtime ( e) )
7812
7829
}
7813
7830
7831
+ /// Converts a WebAssembly runtime error code into a Clarity `Error`.
7832
+ ///
7833
+ /// This function interprets an error code from a WebAssembly runtime execution and
7834
+ /// translates it into an appropriate Clarity error type. It handles various categories
7835
+ /// of errors including arithmetic errors, short returns, and other runtime issues.
7836
+ ///
7837
+ /// # Returns
7838
+ ///
7839
+ /// Returns a Clarity `Error` that corresponds to the runtime error encountered during
7840
+ /// WebAssembly execution.
7841
+ ///
7814
7842
fn from_runtime_error_code (
7815
7843
instance : Instance ,
7816
7844
mut store : impl AsContextMut ,
7817
7845
e : wasmtime:: Error ,
7846
+ epoch_id : & StacksEpochId ,
7847
+ clarity_version : & ClarityVersion ,
7818
7848
) -> Error {
7819
- let global = "runtime-error-code" ;
7820
- let runtime_error_code = instance
7821
- . get_global ( & mut store, global)
7822
- . and_then ( |glob| glob. get ( & mut store) . i32 ( ) )
7823
- . unwrap_or_else ( || panic ! ( "Could not find {global} global with i32 value" ) ) ;
7849
+ let runtime_error_code = get_global_i32 ( & instance, & mut store, "runtime-error-code" ) ;
7824
7850
7825
7851
match ErrorMap :: from ( runtime_error_code) {
7826
7852
ErrorMap :: NotClarityError => Error :: Wasm ( WasmError :: Runtime ( e) ) ,
@@ -7849,33 +7875,19 @@ mod error_mapping {
7849
7875
// This RuntimeErrorType::UnwrapFailure need to have a proper context.
7850
7876
Error :: Runtime ( RuntimeErrorType :: UnwrapFailure , Some ( Vec :: new ( ) ) )
7851
7877
}
7852
- // TODO: UInt(42) value below is just a placeholder.
7853
- // It should be replaced by the current "thrown-value" when clarity-wasm issue #385 is resolved.
7854
- // Tests that reach this code are currently ignored.
7855
- ErrorMap :: ShortReturnAssertionFailure => Error :: ShortReturn (
7856
- ShortReturnType :: AssertionFailed ( Value :: Response ( ResponseData {
7857
- committed : false ,
7858
- data : Box :: new ( Value :: UInt ( 42 ) ) ,
7859
- } ) ) ,
7860
- ) ,
7878
+ ErrorMap :: ShortReturnAssertionFailure => {
7879
+ let clarity_val = short_return_value ( & instance, & mut store, epoch_id, clarity_version) ;
7880
+ Error :: ShortReturn ( ShortReturnType :: AssertionFailed ( clarity_val) )
7881
+ }
7861
7882
ErrorMap :: ArithmeticPowError => Error :: Runtime (
7862
7883
RuntimeErrorType :: Arithmetic ( POW_ERROR_MESSAGE . into ( ) ) ,
7863
7884
Some ( Vec :: new ( ) ) ,
7864
7885
) ,
7865
7886
ErrorMap :: NameAlreadyUsed => {
7866
- let runtime_error_arg_offset = instance
7867
- . get_global ( & mut store, "runtime-error-arg-offset" )
7868
- . and_then ( |glob| glob. get ( & mut store) . i32 ( ) )
7869
- . unwrap_or_else ( || {
7870
- panic ! ( "Could not find $runtime-error-arg-offset global with i32 value" )
7871
- } ) ;
7872
-
7873
- let runtime_error_arg_len = instance
7874
- . get_global ( & mut store, "runtime-error-arg-len" )
7875
- . and_then ( |glob| glob. get ( & mut store) . i32 ( ) )
7876
- . unwrap_or_else ( || {
7877
- panic ! ( "Could not find $runtime-error-arg-len global with i32 value" )
7878
- } ) ;
7887
+ let runtime_error_arg_offset =
7888
+ get_global_i32 ( & instance, & mut store, "runtime-error-arg-offset" ) ;
7889
+ let runtime_error_arg_len =
7890
+ get_global_i32 ( & instance, & mut store, "runtime-error-arg-len" ) ;
7879
7891
7880
7892
let memory = instance
7881
7893
. get_memory ( & mut store, "memory" )
@@ -7890,7 +7902,76 @@ mod error_mapping {
7890
7902
7891
7903
Error :: Unchecked ( CheckErrors :: NameAlreadyUsed ( arg_name) )
7892
7904
}
7905
+ ErrorMap :: ShortReturnExpectedValueResponse => {
7906
+ let clarity_val = short_return_value ( & instance, & mut store, epoch_id, clarity_version) ;
7907
+ Error :: ShortReturn ( ShortReturnType :: ExpectedValue ( Value :: Response (
7908
+ ResponseData {
7909
+ committed : false ,
7910
+ data : Box :: new ( clarity_val) ,
7911
+ } ,
7912
+ ) ) )
7913
+ }
7914
+ ErrorMap :: ShortReturnExpectedValueOptional => {
7915
+ Error :: ShortReturn ( ShortReturnType :: ExpectedValue ( Value :: Optional (
7916
+ clarity:: vm:: types:: OptionalData { data : None } ,
7917
+ ) ) )
7918
+ }
7919
+ ErrorMap :: ShortReturnExpectedValue => {
7920
+ let clarity_val = short_return_value ( & instance, & mut store, epoch_id, clarity_version) ;
7921
+ Error :: ShortReturn ( ShortReturnType :: ExpectedValue ( clarity_val) )
7922
+ }
7893
7923
_ => panic ! ( "Runtime error code {} not supported" , runtime_error_code) ,
7894
7924
}
7895
7925
}
7926
+
7927
+ /// Retrieves the value of a 32-bit integer global variable from a WebAssembly instance.
7928
+ ///
7929
+ /// This function attempts to fetch a global variable by name from the provided WebAssembly
7930
+ /// instance and return its value as an `i32`. It's designed to simplify the process of
7931
+ /// reading global variables in WebAssembly modules.
7932
+ ///
7933
+ /// # Returns
7934
+ ///
7935
+ /// Returns the value of the global variable as an `i32`.
7936
+ ///
7937
+ fn get_global_i32 ( instance : & Instance , store : & mut impl AsContextMut , name : & str ) -> i32 {
7938
+ instance
7939
+ . get_global ( & mut * store, name)
7940
+ . and_then ( |glob| glob. get ( store) . i32 ( ) )
7941
+ . unwrap_or_else ( || panic ! ( "Could not find ${} global with i32 value" , name) )
7942
+ }
7943
+
7944
+ /// Retrieves and deserializes a Clarity value from WebAssembly memory in the context of a short return.
7945
+ ///
7946
+ /// This function is used to extract a Clarity value that has been stored in WebAssembly memory
7947
+ /// as part of a short return operation. It reads necessary metadata from global variables,
7948
+ /// deserializes the type information, and then reads and deserializes the actual value.
7949
+ ///
7950
+ /// # Returns
7951
+ ///
7952
+ /// Returns a deserialized Clarity `Value` representing the short return value.
7953
+ ///
7954
+ fn short_return_value (
7955
+ instance : & Instance ,
7956
+ store : & mut impl AsContextMut ,
7957
+ epoch_id : & StacksEpochId ,
7958
+ clarity_version : & ClarityVersion ,
7959
+ ) -> Value {
7960
+ let val_offset = get_global_i32 ( instance, store, "runtime-error-value-offset" ) ;
7961
+ let type_ser_offset = get_global_i32 ( instance, store, "runtime-error-type-ser-offset" ) ;
7962
+ let type_ser_len = get_global_i32 ( instance, store, "runtime-error-type-ser-len" ) ;
7963
+
7964
+ let memory = instance
7965
+ . get_memory ( & mut * store, "memory" )
7966
+ . unwrap_or_else ( || panic ! ( "Could not find wasm instance memory" ) ) ;
7967
+
7968
+ let type_ser_str = read_identifier_from_wasm ( memory, store, type_ser_offset, type_ser_len)
7969
+ . unwrap_or_else ( |e| panic ! ( "Could not recover stringified type: {}" , e) ) ;
7970
+
7971
+ let value_ty = signature_from_string ( & type_ser_str, * clarity_version, * epoch_id)
7972
+ . unwrap_or_else ( |e| panic ! ( "Could not recover thrown value: {}" , e) ) ;
7973
+
7974
+ read_from_wasm_indirect ( memory, store, & value_ty, val_offset, * epoch_id)
7975
+ . unwrap_or_else ( |e| panic ! ( "Could not read thrown value from memory: {}" , e) )
7976
+ }
7896
7977
}
0 commit comments