@@ -12,6 +12,7 @@ use fvm_shared::econ::TokenAmount;
1212use fvm_shared:: error:: { ErrorNumber , ExitCode } ;
1313use fvm_shared:: event:: StampedEvent ;
1414use fvm_shared:: sys:: BlockId ;
15+ use fvm_shared:: upgrade:: UpgradeInfo ;
1516use fvm_shared:: { ActorID , MethodNum , METHOD_SEND } ;
1617use num_traits:: Zero ;
1718
@@ -417,8 +418,8 @@ where
417418 . get_actor ( actor_id) ?
418419 . ok_or_else ( || syscall_error ! ( NotFound ; "actor not found: {}" , actor_id) ) ?;
419420
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
422423 // sent a message to this actor which in turn called upgrade)
423424 let code = state. code ;
424425
@@ -434,11 +435,11 @@ where
434435 ) ,
435436 ) ;
436437
437- // run the upgrade endpoint
438+ // run the upgrade entrypoint
438439 let result = self . send :: < K > (
439440 actor_id,
440441 Address :: new_id ( actor_id) ,
441- Entrypoint :: Upgrade ,
442+ Entrypoint :: Upgrade ( UpgradeInfo { old_code_cid : code } ) ,
442443 params,
443444 & TokenAmount :: zero ( ) ,
444445 None ,
@@ -735,6 +736,11 @@ where
735736 NO_DATA_BLOCK_ID
736737 } ;
737738
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+
738744 // Increment invocation count
739745 self . invocation_count += 1 ;
740746
@@ -782,20 +788,21 @@ where
782788
783789 store. data_mut ( ) . memory = memory;
784790
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 ( ) ) ;
790800
791801 // Set the available gas.
792802 update_gas_available ( & mut store) ?;
793803
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) ?;
799806
800807 // Charge for any remaining uncharged execution gas, returning an error if we run
801808 // out.
@@ -805,35 +812,26 @@ where
805812 // detected it and returned OutOfGas above. Any other invocation failure is returned
806813 // here as an Abort
807814
808- Ok ( res? )
815+ Ok ( out [ 0 ] . unwrap_i32 ( ) as u32 )
809816 } ) ( ) ;
810817
811818 let invocation_data = store. into_data ( ) ;
812819 let last_error = invocation_data. last_error ;
813820 let ( mut cm, block_registry) = invocation_data. kernel . into_inner ( ) ;
814821
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-
831822 // Process the result, updating the backtrace if necessary.
832823 let mut ret = match result {
833- Ok ( ret ) => Ok ( InvocationResult {
824+ Ok ( NO_DATA_BLOCK_ID ) => Ok ( InvocationResult {
834825 exit_code : ExitCode :: OK ,
835- value : ret . cloned ( ) ,
826+ value : None ,
836827 } ) ,
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+ } ,
837835 Err ( abort) => {
838836 let ( code, message, res) = match abort {
839837 Abort :: Exit ( code, message, NO_DATA_BLOCK_ID ) => (
@@ -845,11 +843,6 @@ where
845843 } ) ,
846844 ) ,
847845 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- ) ,
853846 Ok ( blk) => (
854847 code,
855848 message,
@@ -858,7 +851,20 @@ where
858851 value : Some ( blk. clone ( ) ) ,
859852 } ) ,
860853 ) ,
854+ Err ( e) => (
855+ ExitCode :: SYS_MISSING_RETURN ,
856+ "error getting exit data block" . to_owned ( ) ,
857+ Err ( ExecutionError :: Fatal ( anyhow ! ( e) ) ) ,
858+ ) ,
861859 } ,
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+ ) ,
862868 Abort :: OutOfGas => (
863869 ExitCode :: SYS_OUT_OF_GAS ,
864870 "out of gas" . to_owned ( ) ,
@@ -1033,14 +1039,48 @@ impl Entrypoint {
10331039 fn method_num ( & self ) -> MethodNum {
10341040 match self {
10351041 Entrypoint :: Invoke ( num) => * num,
1036- Entrypoint :: Upgrade => 191919 ,
1042+ Entrypoint :: Upgrade ( _ ) => fvm_shared :: METHOD_UPGRADE ,
10371043 }
10381044 }
10391045
10401046 fn func_name ( & self ) -> & ' static str {
10411047 match self {
10421048 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 ( ) ,
10441066 }
10451067 }
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+ }
10461086}
0 commit comments