1- use std:: convert:: { TryFrom , TryInto } ;
1+ use std:: convert:: TryFrom ;
22use std:: sync:: Mutex ;
33
4+ use anyhow:: anyhow;
45use cid:: Cid ;
56use futures:: executor:: block_on;
67use fvm:: call_manager:: DefaultCallManager ;
@@ -9,6 +10,7 @@ use fvm::machine::DefaultMachine;
910use fvm:: { Config , DefaultKernel } ;
1011use fvm_ipld_blockstore:: Blockstore ;
1112use fvm_ipld_car:: load_car;
13+ use fvm_shared:: receipt:: Receipt ;
1214use fvm_shared:: { clock:: ChainEpoch , econ:: TokenAmount , message:: Message , version:: NetworkVersion } ;
1315use lazy_static:: lazy_static;
1416use log:: info;
@@ -18,8 +20,7 @@ use super::blockstore::{CgoBlockstore, FakeBlockstore, OverlayBlockstore};
1820use super :: externs:: CgoExterns ;
1921use super :: types:: * ;
2022use crate :: destructor;
21- use crate :: util:: api:: init_log;
22- use crate :: util:: types:: { catch_panic_response, Result } ;
23+ use crate :: util:: types:: { catch_panic_response, catch_panic_response_no_default, Result } ;
2324
2425pub type CgoExecutor = DefaultExecutor <
2526 DefaultKernel < DefaultCallManager < DefaultMachine < OverlayBlockstore < CgoBlockstore > , CgoExterns > > > ,
@@ -46,200 +47,160 @@ fn create_fvm_machine(
4647 manifest_cid : c_slice:: Ref < u8 > ,
4748 blockstore_id : u64 ,
4849 externs_id : u64 ,
49- ) -> repr_c:: Box < Result < FvmMachine > > {
50- catch_panic_response ( "create_fvm_machine" , || {
51- match fvm_version {
52- FvmRegisteredVersion :: V1 => info ! ( "using FVM V1" ) ,
53- //_ => panic!("unsupported FVM Registered Version")
54- }
55-
56- let config = Config :: default ( ) ;
57- let chain_epoch = chain_epoch as ChainEpoch ;
58-
59- let base_circ_supply = TokenAmount :: from (
60- ( ( base_circ_supply_hi as u128 ) << u64:: BITS ) | base_circ_supply_lo as u128 ,
61- ) ;
62- let base_fee =
63- TokenAmount :: from ( ( ( base_fee_hi as u128 ) << u64:: BITS ) | base_fee_lo as u128 ) ;
64-
65- let network_version = NetworkVersion :: try_from ( network_version as u32 )
66- . map_err ( |_| format ! ( "unsupported network version: {}" , network_version) ) ?;
67- let state_root =
68- Cid :: try_from ( & state_root) . map_err ( |err| format ! ( "invalid state root: {}" , err) ) ?;
69-
70- let manifest_cid = if !manifest_cid. is_empty ( ) {
71- let cid =
72- Cid :: try_from ( & manifest_cid) . map_err ( |err| format ! ( "invalid manifest: {}" , err) ) ?;
73- Some ( cid)
74- } else {
75- // handle cid.Undef for no manifest
76- // this can mean two things:
77- // - for pre nv16, use the builtin bundles
78- // - for nv16 or higher, it means we have already migrated state for system
79- // actor and we can pass None to the machine constructor to fish it from state.
80- // The presence of the manifest cid argument allows us to test with new bundles
81- // with minimum friction.
82- None
83- } ;
84-
85- let blockstore = FakeBlockstore :: new ( CgoBlockstore :: new ( blockstore_id) ) ;
86-
87- let builtin_actors = import_actors ( & blockstore, manifest_cid, network_version)
88- . map_err ( |err| format ! ( "couldn't load builtin actors: {}" , err) ) ?;
89-
90- let blockstore = blockstore. finish ( ) ;
91-
92- let externs = CgoExterns :: new ( externs_id) ;
93- let machine = fvm:: machine:: DefaultMachine :: new (
94- config,
95- ENGINE . clone ( ) ,
96- chain_epoch,
97- base_fee,
98- base_circ_supply,
99- network_version,
100- state_root,
101- builtin_actors,
102- blockstore,
103- externs,
104- )
105- . map_err ( |err| format ! ( "failed to create machine: {}" , err) ) ?;
50+ ) -> repr_c:: Box < Result < repr_c:: Box < FvmMachine > > > {
51+ unsafe {
52+ catch_panic_response_no_default ( "create_fvm_machine" , || {
53+ match fvm_version {
54+ FvmRegisteredVersion :: V1 => info ! ( "using FVM V1" ) ,
55+ //_ => panic!("unsupported FVM Registered Version")
56+ }
10657
107- Ok ( FvmMachine {
108- machine : Mutex :: new ( CgoExecutor :: new ( machine) ) ,
58+ let config = Config :: default ( ) ;
59+ let chain_epoch = chain_epoch as ChainEpoch ;
60+
61+ let base_circ_supply = TokenAmount :: from (
62+ ( ( base_circ_supply_hi as u128 ) << u64:: BITS ) | base_circ_supply_lo as u128 ,
63+ ) ;
64+ let base_fee =
65+ TokenAmount :: from ( ( ( base_fee_hi as u128 ) << u64:: BITS ) | base_fee_lo as u128 ) ;
66+
67+ let network_version = NetworkVersion :: try_from ( network_version as u32 )
68+ . map_err ( |_| anyhow ! ( "unsupported network version: {}" , network_version) ) ?;
69+ let state_root = Cid :: try_from ( & state_root[ ..] )
70+ . map_err ( |err| anyhow ! ( "invalid state root: {}" , err) ) ?;
71+
72+ let manifest_cid = if !manifest_cid. is_empty ( ) {
73+ let cid = Cid :: try_from ( & manifest_cid[ ..] )
74+ . map_err ( |err| anyhow ! ( "invalid manifest: {}" , err) ) ?;
75+ Some ( cid)
76+ } else {
77+ // handle cid.Undef for no manifest
78+ // this can mean two things:
79+ // - for pre nv16, use the builtin bundles
80+ // - for nv16 or higher, it means we have already migrated state for system
81+ // actor and we can pass None to the machine constructor to fish it from state.
82+ // The presence of the manifest cid argument allows us to test with new bundles
83+ // with minimum friction.
84+ None
85+ } ;
86+
87+ let blockstore = FakeBlockstore :: new ( CgoBlockstore :: new ( blockstore_id) ) ;
88+
89+ let builtin_actors = import_actors ( & blockstore, manifest_cid, network_version)
90+ . map_err ( |err| anyhow ! ( "couldn't load builtin actors: {}" , err) ) ?;
91+
92+ let blockstore = blockstore. finish ( ) ;
93+
94+ let externs = CgoExterns :: new ( externs_id) ;
95+ let machine = fvm:: machine:: DefaultMachine :: new (
96+ config,
97+ ENGINE . clone ( ) ,
98+ chain_epoch,
99+ base_fee,
100+ base_circ_supply,
101+ network_version,
102+ state_root,
103+ builtin_actors,
104+ blockstore,
105+ externs,
106+ )
107+ . map_err ( |err| anyhow ! ( "failed to create machine: {}" , err) ) ?;
108+
109+ Ok ( repr_c:: Box :: new ( FvmMachine {
110+ machine : Some ( Mutex :: new ( CgoExecutor :: new ( machine) ) ) ,
111+ } ) )
109112 } )
110- } )
113+ }
111114}
112115
113- destructor ! ( drop_fvm_machine, Result <FvmMachine >) ;
114-
115116#[ ffi_export]
116117fn fvm_machine_execute_message (
117- executor : * mut libc:: c_void ,
118- message_ptr : * const u8 ,
119- message_len : libc:: size_t ,
118+ executor : & ' _ FvmMachine ,
119+ message : c_slice:: Ref < u8 > ,
120120 chain_len : u64 ,
121121 apply_kind : u64 , /* 0: Explicit, _: Implicit */
122- ) -> * mut fil_FvmMachineExecuteResponse {
123- catch_panic_response ( || {
124- init_log ( ) ;
125-
126- info ! ( "fil_fvm_machine_execute_message: start" ) ;
127-
128- let mut response = fil_FvmMachineExecuteResponse:: default ( ) ;
129-
122+ ) -> repr_c:: Box < Result < FvmMachineExecuteResponse > > {
123+ catch_panic_response ( "fvm_machine_execute_message" , || {
130124 let apply_kind = if apply_kind == 0 {
131125 ApplyKind :: Explicit
132126 } else {
133127 ApplyKind :: Implicit
134128 } ;
135129
136- let message_bytes = std:: slice:: from_raw_parts ( message_ptr, message_len) ;
137- let message: Message = match fvm_ipld_encoding:: from_slice ( message_bytes) {
138- Ok ( x) => x,
139- Err ( err) => {
140- response. status_code = FCPResponseStatus :: FCPUnclassifiedError ;
141- response. error_msg = rust_str_to_c_str ( format ! ( "{:?}" , err) ) ;
142- return raw_ptr ( response) ;
143- }
144- } ;
130+ let message: Message = fvm_ipld_encoding:: from_slice ( & message) ?;
145131
146- let mut executor = unsafe { & * ( executor as * mut Mutex < CgoExecutor > ) }
132+ let mut executor = executor
133+ . machine
134+ . as_ref ( )
135+ . expect ( "missing executor" )
147136 . lock ( )
148137 . unwrap ( ) ;
149- let apply_ret = match executor. execute_message ( message, apply_kind, chain_len as usize ) {
150- Ok ( x) => x,
151- Err ( err) => {
152- response. status_code = FCPResponseStatus :: FCPUnclassifiedError ;
153- response. error_msg = rust_str_to_c_str ( format ! ( "{:?}" , err) ) ;
154- return raw_ptr ( response) ;
155- }
156- } ;
138+ let apply_ret = executor. execute_message ( message, apply_kind, chain_len as usize ) ?;
157139
158140 // TODO: use the non-bigint token amount everywhere in the FVM
159141 let penalty: u128 = apply_ret. penalty . try_into ( ) . unwrap ( ) ;
160142 let miner_tip: u128 = apply_ret. miner_tip . try_into ( ) . unwrap ( ) ;
161143
162- // Only do this if the return data is non-empty. The empty vec pointer is non-null and not
163- // valid in go.
164- if !apply_ret. msg_receipt . return_data . is_empty ( ) {
165- let return_bytes = Vec :: from ( apply_ret. msg_receipt . return_data ) . into_boxed_slice ( ) ;
166- response. return_ptr = return_bytes. as_ptr ( ) ;
167- response. return_len = return_bytes. len ( ) ;
168- Box :: leak ( return_bytes) ;
169- }
144+ let Receipt {
145+ exit_code,
146+ return_data,
147+ gas_used,
148+ } = apply_ret. msg_receipt ;
170149
171- // TODO: Do something with the backtrace.
172- response. status_code = FCPResponseStatus :: FCPNoError ;
173- response. exit_code = apply_ret. msg_receipt . exit_code as u64 ;
174- response. gas_used = apply_ret. msg_receipt . gas_used as u64 ;
175- response. penalty_hi = ( penalty >> u64:: BITS ) as u64 ;
176- response. penalty_lo = penalty as u64 ;
177- response. miner_tip_hi = ( miner_tip >> u64:: BITS ) as u64 ;
178- response. miner_tip_lo = miner_tip as u64 ;
150+ let return_val = if return_data. is_empty ( ) {
151+ None
152+ } else {
153+ let bytes: Vec < u8 > = return_data. into ( ) ;
154+ Some ( bytes. into_boxed_slice ( ) . into ( ) )
155+ } ;
179156
180- info ! ( "fil_fvm_machine_execute_message: end" ) ;
157+ // TODO: Do something with the backtrace.
181158
182- raw_ptr ( response)
159+ Ok ( FvmMachineExecuteResponse {
160+ exit_code : exit_code as u64 ,
161+ return_val,
162+ gas_used : gas_used as u64 ,
163+ penalty_hi : ( penalty >> u64:: BITS ) as u64 ,
164+ penalty_lo : penalty as u64 ,
165+ miner_tip_hi : ( miner_tip >> u64:: BITS ) as u64 ,
166+ miner_tip_lo : miner_tip as u64 ,
167+ } )
183168 } )
184169}
185170
186- #[ no_mangle]
187- pub unsafe extern "C" fn fil_fvm_machine_flush (
188- executor : * mut libc:: c_void ,
189- ) -> * mut fil_FvmMachineFlushResponse {
190- catch_panic_response ( || {
191- init_log ( ) ;
192-
193- info ! ( "fil_fvm_machine_flush: start" ) ;
194-
195- let mut executor = unsafe { & * ( executor as * mut Mutex < CgoExecutor > ) }
171+ #[ ffi_export]
172+ fn fil_fvm_machine_flush ( executor : & ' _ FvmMachine ) -> repr_c:: Box < Result < c_slice:: Box < u8 > > > {
173+ catch_panic_response ( "fvm_machine_flush" , || {
174+ let mut executor = executor
175+ . machine
176+ . as_ref ( )
177+ . expect ( "missing executor" )
196178 . lock ( )
197179 . unwrap ( ) ;
198- let mut response = fil_FvmMachineFlushResponse:: default ( ) ;
199- match executor. flush ( ) {
200- Ok ( cid) => {
201- let bytes = cid. to_bytes ( ) . into_boxed_slice ( ) ;
202- response. state_root_ptr = bytes. as_ptr ( ) ;
203- response. state_root_len = bytes. len ( ) ;
204- Box :: leak ( bytes) ;
205- }
206- Err ( e) => {
207- response. status_code = FCPResponseStatus :: FCPReceiverError ;
208- response. error_msg = rust_str_to_c_str ( e. to_string ( ) ) ;
209- }
210- }
211- info ! ( "fil_fvm_machine_flush: end" ) ;
180+ let cid = executor. flush ( ) ?;
212181
213- raw_ptr ( response )
182+ Ok ( cid . to_bytes ( ) . into_boxed_slice ( ) . into ( ) )
214183 } )
215184}
216185
217- #[ no_mangle]
218- pub unsafe extern "C" fn fil_destroy_create_fvm_machine_response (
219- ptr : * mut fil_CreateFvmMachineResponse ,
220- ) {
221- let _ = Box :: from_raw ( ptr) ;
222- }
186+ destructor ! ( drop_fvm_machine, FvmMachine ) ;
187+ destructor ! (
188+ destroy_create_fvm_machine_response,
189+ Result <repr_c:: Box <FvmMachine >>
190+ ) ;
223191
224- #[ no_mangle]
225- pub unsafe extern "C" fn fil_destroy_fvm_machine_execute_response (
226- ptr : * mut fil_FvmMachineExecuteResponse ,
227- ) {
228- let _ = Box :: from_raw ( ptr) ;
229- }
192+ destructor ! (
193+ destroy_fvm_machine_execute_response,
194+ Result <FvmMachineExecuteResponse >
195+ ) ;
230196
231- #[ no_mangle]
232- pub unsafe extern "C" fn fil_destroy_fvm_machine_flush_response (
233- ptr : * mut fil_FvmMachineFlushResponse ,
234- ) {
235- let _ = Box :: from_raw ( ptr) ;
236- }
197+ destructor ! ( destroy_fvm_machine_flush_response, Result <c_slice:: Box <u8 >>) ;
237198
238199fn import_actors (
239200 blockstore : & impl Blockstore ,
240201 manifest_cid : Option < Cid > ,
241202 network_version : NetworkVersion ,
242- ) -> Result < Option < Cid > , & ' static str > {
203+ ) -> std :: result :: Result < Option < Cid > , & ' static str > {
243204 if manifest_cid. is_some ( ) {
244205 return Ok ( manifest_cid) ;
245206 }
0 commit comments