@@ -12,6 +12,7 @@ use fvm_shared::econ::TokenAmount;
12
12
use fvm_shared:: error:: { ErrorNumber , ExitCode } ;
13
13
use fvm_shared:: event:: StampedEvent ;
14
14
use fvm_shared:: sys:: BlockId ;
15
+ use fvm_shared:: upgrade:: UpgradeInfo ;
15
16
use fvm_shared:: { ActorID , MethodNum , METHOD_SEND } ;
16
17
use num_traits:: Zero ;
17
18
@@ -417,8 +418,8 @@ where
417
418
. get_actor ( actor_id) ?
418
419
. ok_or_else ( || syscall_error ! ( NotFound ; "actor not found: {}" , actor_id) ) ?;
419
420
420
- // store the code cid of the calling actor before running the upgrade endpoint
421
- // in case it was changed (which could happen if the target upgrade endpoint
421
+ // store the code cid of the calling actor before running the upgrade entrypoint
422
+ // in case it was changed (which could happen if the target upgrade entrypoint
422
423
// sent a message to this actor which in turn called upgrade)
423
424
let code = state. code ;
424
425
@@ -434,11 +435,11 @@ where
434
435
) ,
435
436
) ;
436
437
437
- // run the upgrade endpoint
438
+ // run the upgrade entrypoint
438
439
let result = self . send :: < K > (
439
440
actor_id,
440
441
Address :: new_id ( actor_id) ,
441
- Entrypoint :: Upgrade ,
442
+ Entrypoint :: Upgrade ( UpgradeInfo { old_code_cid : code } ) ,
442
443
params,
443
444
& TokenAmount :: zero ( ) ,
444
445
None ,
@@ -735,6 +736,11 @@ where
735
736
NO_DATA_BLOCK_ID
736
737
} ;
737
738
739
+ // additional_params takes care of adding entrypoint specific params to the block
740
+ // registry and passing them to wasmtime
741
+ let mut additional_params = EntrypointParams :: new ( entrypoint) ;
742
+ additional_params. maybe_put_registry ( & mut block_registry) ?;
743
+
738
744
// Increment invocation count
739
745
self . invocation_count += 1 ;
740
746
@@ -782,20 +788,21 @@ where
782
788
783
789
store. data_mut ( ) . memory = memory;
784
790
785
- // Lookup the invoke method.
786
- let invoke: wasmtime:: TypedFunc < ( u32 , ) , u32 > = instance
787
- . get_typed_func ( & mut store, entrypoint. func_name ( ) )
788
- // All actors will have an invoke method.
789
- . map_err ( Abort :: Fatal ) ?;
791
+ let func = match instance. get_func ( & mut store, entrypoint. func_name ( ) ) {
792
+ Some ( func) => func,
793
+ None => {
794
+ return Err ( Abort :: EntrypointNotFound ) ;
795
+ }
796
+ } ;
797
+
798
+ let mut params = vec ! [ wasmtime:: Val :: I32 ( params_id as i32 ) ] ;
799
+ params. extend_from_slice ( additional_params. params ( ) . as_slice ( ) ) ;
790
800
791
801
// Set the available gas.
792
802
update_gas_available ( & mut store) ?;
793
803
794
- // Invoke it.
795
- let res = std:: panic:: catch_unwind ( std:: panic:: AssertUnwindSafe ( || {
796
- invoke. call ( & mut store, ( params_id, ) )
797
- } ) )
798
- . map_err ( |panic| Abort :: Fatal ( anyhow ! ( "panic within actor: {:?}" , panic) ) ) ?;
804
+ let mut out = [ wasmtime:: Val :: I32 ( 0 ) ] ;
805
+ func. call ( & mut store, params. as_slice ( ) , & mut out) ?;
799
806
800
807
// Charge for any remaining uncharged execution gas, returning an error if we run
801
808
// out.
@@ -805,35 +812,26 @@ where
805
812
// detected it and returned OutOfGas above. Any other invocation failure is returned
806
813
// here as an Abort
807
814
808
- Ok ( res? )
815
+ Ok ( out [ 0 ] . unwrap_i32 ( ) as u32 )
809
816
} ) ( ) ;
810
817
811
818
let invocation_data = store. into_data ( ) ;
812
819
let last_error = invocation_data. last_error ;
813
820
let ( mut cm, block_registry) = invocation_data. kernel . into_inner ( ) ;
814
821
815
- // Resolve the return block's ID into an actual block, converting to an abort if it
816
- // doesn't exist.
817
- let result = result. and_then ( |ret_id| {
818
- Ok ( if ret_id == NO_DATA_BLOCK_ID {
819
- None
820
- } else {
821
- Some ( block_registry. get ( ret_id) . map_err ( |_| {
822
- Abort :: Exit (
823
- ExitCode :: SYS_MISSING_RETURN ,
824
- String :: from ( "returned block does not exist" ) ,
825
- NO_DATA_BLOCK_ID ,
826
- )
827
- } ) ?)
828
- } )
829
- } ) ;
830
-
831
822
// Process the result, updating the backtrace if necessary.
832
823
let mut ret = match result {
833
- Ok ( ret ) => Ok ( InvocationResult {
824
+ Ok ( NO_DATA_BLOCK_ID ) => Ok ( InvocationResult {
834
825
exit_code : ExitCode :: OK ,
835
- value : ret . cloned ( ) ,
826
+ value : None ,
836
827
} ) ,
828
+ Ok ( block_id) => match block_registry. get ( block_id) {
829
+ Ok ( blk) => Ok ( InvocationResult {
830
+ exit_code : ExitCode :: OK ,
831
+ value : Some ( blk. clone ( ) ) ,
832
+ } ) ,
833
+ Err ( e) => Err ( ExecutionError :: Fatal ( anyhow ! ( e) ) ) ,
834
+ } ,
837
835
Err ( abort) => {
838
836
let ( code, message, res) = match abort {
839
837
Abort :: Exit ( code, message, NO_DATA_BLOCK_ID ) => (
@@ -845,11 +843,6 @@ where
845
843
} ) ,
846
844
) ,
847
845
Abort :: Exit ( code, message, blk_id) => match block_registry. get ( blk_id) {
848
- Err ( e) => (
849
- ExitCode :: SYS_MISSING_RETURN ,
850
- "error getting exit data block" . to_owned ( ) ,
851
- Err ( ExecutionError :: Fatal ( anyhow ! ( e) ) ) ,
852
- ) ,
853
846
Ok ( blk) => (
854
847
code,
855
848
message,
@@ -858,7 +851,20 @@ where
858
851
value : Some ( blk. clone ( ) ) ,
859
852
} ) ,
860
853
) ,
854
+ Err ( e) => (
855
+ ExitCode :: SYS_MISSING_RETURN ,
856
+ "error getting exit data block" . to_owned ( ) ,
857
+ Err ( ExecutionError :: Fatal ( anyhow ! ( e) ) ) ,
858
+ ) ,
861
859
} ,
860
+ Abort :: EntrypointNotFound => (
861
+ ExitCode :: USR_FORBIDDEN ,
862
+ "entrypoint not found" . to_owned ( ) ,
863
+ Err ( ExecutionError :: Syscall ( SyscallError :: new (
864
+ ErrorNumber :: Forbidden ,
865
+ "entrypoint not found" ,
866
+ ) ) ) ,
867
+ ) ,
862
868
Abort :: OutOfGas => (
863
869
ExitCode :: SYS_OUT_OF_GAS ,
864
870
"out of gas" . to_owned ( ) ,
@@ -1033,14 +1039,48 @@ impl Entrypoint {
1033
1039
fn method_num ( & self ) -> MethodNum {
1034
1040
match self {
1035
1041
Entrypoint :: Invoke ( num) => * num,
1036
- Entrypoint :: Upgrade => 191919 ,
1042
+ Entrypoint :: Upgrade ( _ ) => fvm_shared :: METHOD_UPGRADE ,
1037
1043
}
1038
1044
}
1039
1045
1040
1046
fn func_name ( & self ) -> & ' static str {
1041
1047
match self {
1042
1048
Entrypoint :: Invoke ( _) => "invoke" ,
1043
- Entrypoint :: Upgrade => "upgrade" ,
1049
+ Entrypoint :: Upgrade ( _) => "upgrade" ,
1050
+ }
1051
+ }
1052
+ }
1053
+
1054
+ // EntrypointParams is a helper struct to init the registry with the entrypoint specific
1055
+ // parameters and then forward them to wasmtime
1056
+ struct EntrypointParams {
1057
+ entrypoint : Entrypoint ,
1058
+ params : Vec < wasmtime:: Val > ,
1059
+ }
1060
+
1061
+ impl EntrypointParams {
1062
+ fn new ( entrypoint : Entrypoint ) -> Self {
1063
+ Self {
1064
+ entrypoint,
1065
+ params : Vec :: new ( ) ,
1044
1066
}
1045
1067
}
1068
+
1069
+ fn maybe_put_registry ( & mut self , br : & mut BlockRegistry ) -> Result < ( ) > {
1070
+ match self . entrypoint {
1071
+ Entrypoint :: Invoke ( _) => Ok ( ( ) ) ,
1072
+ Entrypoint :: Upgrade ( ui) => {
1073
+ let ui_params = to_vec ( & ui) . map_err (
1074
+ |e| syscall_error ! ( IllegalArgument ; "failed to serialize upgrade params: {}" , e) ,
1075
+ ) ?;
1076
+ let block_id = br. put ( Block :: new ( CBOR , ui_params) ) ?;
1077
+ self . params . push ( wasmtime:: Val :: I32 ( block_id as i32 ) ) ;
1078
+ Ok ( ( ) )
1079
+ }
1080
+ }
1081
+ }
1082
+
1083
+ fn params ( & self ) -> & Vec < wasmtime:: Val > {
1084
+ & self . params
1085
+ }
1046
1086
}
0 commit comments