Skip to content

Commit 55b02e4

Browse files
update rust bindings
1 parent b8b6c8b commit 55b02e4

File tree

3 files changed

+176
-234
lines changed

3 files changed

+176
-234
lines changed

rust/src/fvm/machine.rs

Lines changed: 117 additions & 156 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
1-
use std::convert::{TryFrom, TryInto};
1+
use std::convert::TryFrom;
22
use std::sync::Mutex;
33

4+
use anyhow::anyhow;
45
use cid::Cid;
56
use futures::executor::block_on;
67
use fvm::call_manager::DefaultCallManager;
@@ -9,6 +10,7 @@ use fvm::machine::DefaultMachine;
910
use fvm::{Config, DefaultKernel};
1011
use fvm_ipld_blockstore::Blockstore;
1112
use fvm_ipld_car::load_car;
13+
use fvm_shared::receipt::Receipt;
1214
use fvm_shared::{clock::ChainEpoch, econ::TokenAmount, message::Message, version::NetworkVersion};
1315
use lazy_static::lazy_static;
1416
use log::info;
@@ -18,8 +20,7 @@ use super::blockstore::{CgoBlockstore, FakeBlockstore, OverlayBlockstore};
1820
use super::externs::CgoExterns;
1921
use super::types::*;
2022
use 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

2425
pub 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]
116117
fn 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

238199
fn 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

Comments
 (0)