11use anyhow:: Context ;
22use derive_more:: { Deref , DerefMut } ;
3- use fvm_ipld_encoding:: { RawBytes , DAG_CBOR } ;
3+ use fvm_ipld_encoding:: { to_vec , DAG_CBOR } ;
44use fvm_shared:: actor:: builtin:: Type ;
55use fvm_shared:: address:: { Address , Protocol } ;
66use fvm_shared:: econ:: TokenAmount ;
77use fvm_shared:: error:: { ErrorNumber , ExitCode } ;
8+ use fvm_shared:: sys:: BlockId ;
89use fvm_shared:: { ActorID , MethodNum , METHOD_SEND } ;
910use num_traits:: Zero ;
1011
1112use super :: { Backtrace , CallManager , InvocationResult , NO_DATA_BLOCK_ID } ;
1213use crate :: call_manager:: backtrace:: Frame ;
1314use crate :: call_manager:: FinishRet ;
1415use crate :: gas:: GasTracker ;
15- use crate :: kernel:: { ExecutionError , Kernel , Result , SyscallError } ;
16+ use crate :: kernel:: { Block , BlockRegistry , ExecutionError , Kernel , Result , SyscallError } ;
1617use crate :: machine:: Machine ;
1718use crate :: syscalls:: error:: Abort ;
1819use crate :: syscalls:: { charge_for_exec, update_gas_available} ;
8687 from : ActorID ,
8788 to : Address ,
8889 method : MethodNum ,
89- params : & RawBytes ,
90+ params : Option < Block > ,
9091 value : & TokenAmount ,
9192 ) -> Result < InvocationResult >
9293 where
9798 from,
9899 to,
99100 method,
100- params : params. clone ( ) ,
101+ params : params
102+ . as_ref ( )
103+ . map ( |blk| blk. data ( ) . to_owned ( ) . into ( ) )
104+ . unwrap_or_default ( ) ,
101105 value : value. clone ( ) ,
102106 } ) ) ;
103107 }
@@ -233,15 +237,15 @@ where
233237
234238 // Now invoke the constructor; first create the parameters, then
235239 // instantiate a new kernel to invoke the constructor.
236- let params = RawBytes :: serialize ( & addr)
240+ let params = to_vec ( & addr)
237241 // TODO(#198) this should be a Sys actor error, but we're copying lotus here.
238242 . map_err ( |e| syscall_error ! ( Serialization ; "failed to serialize params: {}" , e) ) ?;
239243
240244 self . send_resolved :: < K > (
241245 account_actor:: SYSTEM_ACTOR_ID ,
242246 id,
243247 fvm_shared:: METHOD_CONSTRUCTOR ,
244- & params,
248+ Some ( Block :: new ( DAG_CBOR , params) ) ,
245249 & TokenAmount :: from ( 0u32 ) ,
246250 ) ?;
247251
@@ -254,7 +258,7 @@ where
254258 from : ActorID ,
255259 to : Address ,
256260 method : MethodNum ,
257- params : & RawBytes ,
261+ params : Option < Block > ,
258262 value : & TokenAmount ,
259263 ) -> Result < InvocationResult >
260264 where
@@ -284,7 +288,7 @@ where
284288 from : ActorID ,
285289 to : ActorID ,
286290 method : MethodNum ,
287- params : & RawBytes ,
291+ params : Option < Block > ,
288292 value : & TokenAmount ,
289293 ) -> Result < InvocationResult >
290294 where
@@ -310,31 +314,29 @@ where
310314 return Ok ( InvocationResult :: Return ( Default :: default ( ) ) ) ;
311315 }
312316
317+ // Store the parametrs, and initialize the block registry for the target actor.
318+ // TODO: In M2, the block registry may have some form of shared block limit.
319+ let mut block_registry = BlockRegistry :: new ( ) ;
320+ let params_id = if let Some ( blk) = params {
321+ block_registry. put ( blk) ?
322+ } else {
323+ NO_DATA_BLOCK_ID
324+ } ;
325+
313326 // This is a cheap operation as it doesn't actually clone the struct,
314327 // it returns a referenced copy.
315328 let engine = self . engine ( ) . clone ( ) ;
316329
317330 log:: trace!( "calling {} -> {}::{}" , from, to, method) ;
318331 self . map_mut ( |cm| {
319332 // Make the kernel.
320- let mut kernel = K :: new ( cm, from, to, method, value. clone ( ) ) ;
321-
322- // Store parameters, if any.
323- let param_id = if params. len ( ) > 0 {
324- match kernel. block_create ( DAG_CBOR , params) {
325- Ok ( id) => id,
326- // This could fail if we pass some global memory limit.
327- Err ( err) => return ( Err ( err) , kernel. into_call_manager ( ) ) ,
328- }
329- } else {
330- super :: NO_DATA_BLOCK_ID
331- } ;
333+ let kernel = K :: new ( cm, block_registry, from, to, method, value. clone ( ) ) ;
332334
333335 // Make a store.
334336 let mut store = engine. new_store ( kernel) ;
335337
336338 // From this point on, there are no more syscall errors, only aborts.
337- let result: std:: result:: Result < RawBytes , Abort > = ( || {
339+ let result: std:: result:: Result < BlockId , Abort > = ( || {
338340 // Instantiate the module.
339341 let instance = engine
340342 . get_instance ( & mut store, & state. code )
@@ -358,39 +360,40 @@ where
358360 update_gas_available ( & mut store) ?;
359361
360362 // Invoke it.
361- let res = invoke. call ( & mut store, ( param_id , ) ) ;
363+ let res = invoke. call ( & mut store, ( params_id , ) ) ;
362364
363365 // Charge for any remaining uncharged execution gas, returning an error if we run
364366 // out.
365367 charge_for_exec ( & mut store) ?;
366368
367- // If the invocation failed due to running out of exec_units, we have already detected it and returned OutOfGas above.
368- // Any other invocation failure is returned here as an Abort
369- let return_block_id = res?;
370-
371- // Extract the return value, if there is one.
372- let return_value: RawBytes = if return_block_id > NO_DATA_BLOCK_ID {
373- let ( code, ret) = store
374- . data_mut ( )
375- . kernel
376- . block_get ( return_block_id)
377- . map_err ( |e| Abort :: from_error ( ExitCode :: SYS_MISSING_RETURN , e) ) ?;
378- debug_assert_eq ! ( code, DAG_CBOR ) ;
379- RawBytes :: new ( ret)
380- } else {
381- RawBytes :: default ( )
382- } ;
383-
384- Ok ( return_value)
369+ // If the invocation failed due to running out of exec_units, we have already
370+ // detected it and returned OutOfGas above. Any other invocation failure is returned
371+ // here as an Abort
372+ Ok ( res?)
385373 } ) ( ) ;
386374
387375 let invocation_data = store. into_data ( ) ;
388376 let last_error = invocation_data. last_error ;
389- let mut cm = invocation_data. kernel . into_call_manager ( ) ;
377+ let ( mut cm, block_registry) = invocation_data. kernel . into_inner ( ) ;
378+
379+ // Resolve the return block's ID into an actual block, converting to an abort if it
380+ // doesn't exist.
381+ let result = result. and_then ( |ret_id| {
382+ Ok ( if ret_id == NO_DATA_BLOCK_ID {
383+ None
384+ } else {
385+ Some ( block_registry. get ( ret_id) . map_err ( |_| {
386+ Abort :: Exit (
387+ ExitCode :: SYS_MISSING_RETURN ,
388+ String :: from ( "returned block does not exist" ) ,
389+ )
390+ } ) ?)
391+ } )
392+ } ) ;
390393
391394 // Process the result, updating the backtrace if necessary.
392395 let ret = match result {
393- Ok ( value ) => Ok ( InvocationResult :: Return ( value ) ) ,
396+ Ok ( ret ) => Ok ( InvocationResult :: Return ( ret . cloned ( ) ) ) ,
394397 Err ( abort) => {
395398 if let Some ( err) = last_error {
396399 cm. backtrace . begin ( err) ;
0 commit comments