Skip to content

Commit f4098eb

Browse files
authored
Implement ExitCode as u32 wrapper, and use new spec codes (#431)
1 parent 80a8a30 commit f4098eb

File tree

9 files changed

+125
-135
lines changed

9 files changed

+125
-135
lines changed

fvm/src/call_manager/default.rs

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -323,7 +323,7 @@ where
323323
.data()
324324
.kernel
325325
.block_get(return_block_id)
326-
.map_err(|e| Abort::from_error(ExitCode::SysErrIllegalActor, e))?;
326+
.map_err(|e| Abort::from_error(ExitCode::SYS_MISSING_RETURN, e))?;
327327
debug_assert_eq!(code, DAG_CBOR);
328328
RawBytes::new(ret)
329329
} else {
@@ -350,14 +350,12 @@ where
350350
(code, message, Ok(InvocationResult::Failure(code)))
351351
}
352352
Abort::OutOfGas => (
353-
ExitCode::SysErrOutOfGas,
353+
ExitCode::SYS_OUT_OF_GAS,
354354
"out of gas".to_owned(),
355355
Err(ExecutionError::OutOfGas),
356356
),
357357
Abort::Fatal(err) => (
358-
// TODO: will be changed to a SysErrAssertionFailed when we
359-
// introduce the new exit codes.
360-
ExitCode::SysErrIllegalArgument,
358+
ExitCode::SYS_ASSERTION_FAILED,
361359
"fatal error".to_owned(),
362360
Err(ExecutionError::Fatal(err)),
363361
),

fvm/src/call_manager/mod.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -135,7 +135,7 @@ impl InvocationResult {
135135
/// from the [`Failure`](InvocationResult::Failure) variant otherwise.
136136
pub fn exit_code(&self) -> ExitCode {
137137
match self {
138-
Self::Return(_) => ExitCode::Ok,
138+
Self::Return(_) => ExitCode::OK,
139139
Self::Failure(e) => *e,
140140
}
141141
}

fvm/src/executor/default.rs

Lines changed: 15 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -88,7 +88,7 @@ where
8888
Ok(InvocationResult::Return(return_data)) => {
8989
backtrace.clear();
9090
Receipt {
91-
exit_code: ExitCode::Ok,
91+
exit_code: ExitCode::OK,
9292
return_data,
9393
gas_used,
9494
}
@@ -104,16 +104,19 @@ where
104104
}
105105
}
106106
Err(ExecutionError::OutOfGas) => Receipt {
107-
exit_code: ExitCode::SysErrOutOfGas,
107+
exit_code: ExitCode::SYS_OUT_OF_GAS,
108108
return_data: Default::default(),
109109
gas_used,
110110
},
111111
Err(ExecutionError::Syscall(err)) => {
112+
// Errors indicate the message couldn't be dispatched at all.
113+
// Some of these errors are mapped to exit codes that persist on chain.
114+
// The remainder propagate in the Result as error numbers and cannot be persisted.
115+
// TODO: map them all to exit codes, https://github.com/filecoin-project/ref-fvm/issues/438
112116
let exit_code = match err.1 {
113-
ErrorNumber::IllegalOperation => ExitCode::SysErrIllegalActor,
114-
ErrorNumber::AssertionFailed => ExitCode::SysErrIllegalArgument,
115-
ErrorNumber::InsufficientFunds => ExitCode::SysErrInsufficientFunds,
116-
ErrorNumber::NotFound => ExitCode::SysErrInvalidReceiver,
117+
ErrorNumber::AssertionFailed => ExitCode::SYS_ASSERTION_FAILED,
118+
ErrorNumber::InsufficientFunds => ExitCode::SYS_INSUFFICIENT_FUNDS,
119+
ErrorNumber::NotFound => ExitCode::SYS_INVALID_RECEIVER,
117120
code => {
118121
return Err(anyhow!(
119122
"unexpected syscall error when processing message: {} ({})",
@@ -207,7 +210,7 @@ where
207210
// Verify the cost of the message is not over the message gas limit.
208211
if inclusion_total > msg.gas_limit {
209212
return Ok(Err(ApplyRet::prevalidation_fail(
210-
ExitCode::SysErrOutOfGas,
213+
ExitCode::SYS_OUT_OF_GAS,
211214
format!("Out of gas ({} > {})", inclusion_total, msg.gas_limit),
212215
&self.context().base_fee * inclusion_total,
213216
)));
@@ -227,7 +230,7 @@ where
227230
Some(id) => id,
228231
None => {
229232
return Ok(Err(ApplyRet::prevalidation_fail(
230-
ExitCode::SysErrSenderInvalid,
233+
ExitCode::SYS_SENDER_INVALID,
231234
"Sender invalid",
232235
miner_penalty_amount,
233236
)))
@@ -246,7 +249,7 @@ where
246249
Some(act) => act,
247250
None => {
248251
return Ok(Err(ApplyRet::prevalidation_fail(
249-
ExitCode::SysErrSenderInvalid,
252+
ExitCode::SYS_SENDER_INVALID,
250253
"Sender invalid",
251254
miner_penalty_amount,
252255
)))
@@ -262,7 +265,7 @@ where
262265

263266
if !sender_is_account {
264267
return Ok(Err(ApplyRet::prevalidation_fail(
265-
ExitCode::SysErrSenderInvalid,
268+
ExitCode::SYS_SENDER_INVALID,
266269
"Send not from account actor",
267270
miner_penalty_amount,
268271
)));
@@ -271,7 +274,7 @@ where
271274
// Check sequence is correct
272275
if msg.sequence != sender.sequence {
273276
return Ok(Err(ApplyRet::prevalidation_fail(
274-
ExitCode::SysErrSenderStateInvalid,
277+
ExitCode::SYS_SENDER_STATE_INVALID,
275278
format!(
276279
"Actor sequence invalid: {} != {}",
277280
msg.sequence, sender.sequence
@@ -284,7 +287,7 @@ where
284287
let gas_cost: TokenAmount = msg.gas_fee_cap.clone() * msg.gas_limit;
285288
if sender.balance < gas_cost {
286289
return Ok(Err(ApplyRet::prevalidation_fail(
287-
ExitCode::SysErrSenderStateInvalid,
290+
ExitCode::SYS_SENDER_STATE_INVALID,
288291
format!(
289292
"Actor balance less than needed: {} < {}",
290293
sender.balance, gas_cost

fvm/src/syscalls/error.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ impl From<Trap> for Abort {
5050

5151
// Actor panic/wasm error.
5252
if let Some(code) = t.trap_code() {
53-
return Abort::Exit(ExitCode::SysErrActorPanic, code.to_string());
53+
return Abort::Exit(ExitCode::SYS_ILLEGAL_INSTRUCTION, code.to_string());
5454
}
5555

5656
// Try to get a smuggled error back.

fvm/src/syscalls/send.rs

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -11,10 +11,6 @@ use crate::Kernel;
1111

1212
/// Send a message to another actor. The result is placed as a CBOR-encoded
1313
/// receipt in the block registry, and can be retrieved by the returned BlockId.
14-
///
15-
/// TODO result is a Receipt, but messages within a call stack don't
16-
/// actually produce receipts.
17-
/// See https://github.com/filecoin-project/fvm/issues/168.
1814
pub fn send(
1915
context: Context<'_, impl Kernel>,
2016
recipient_off: u32,
@@ -41,10 +37,10 @@ pub fn send(
4137
.send(&recipient, method, &params.into(), &value)?
4238
{
4339
InvocationResult::Return(value) => (
44-
ExitCode::Ok as u32,
40+
ExitCode::OK.value(),
4541
context.kernel.block_create(DAG_CBOR, value.bytes())?,
4642
),
47-
InvocationResult::Failure(code) => (code as u32, 0),
43+
InvocationResult::Failure(code) => (code.value(), 0),
4844
};
4945
Ok(sys::out::send::Send {
5046
exit_code,

fvm/src/syscalls/vm.rs

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
use fvm_shared::error::ExitCode;
2-
use num_traits::FromPrimitive;
32

43
use super::error::Abort;
54
use super::Context;
@@ -18,11 +17,14 @@ pub fn abort(
1817
message_off: u32,
1918
message_len: u32,
2019
) -> Result<Never, Abort> {
21-
// Get the error and convert it into a "system illegal argument error" if it's invalid.
22-
// BUG: https://github.com/filecoin-project/fvm/issues/253
23-
let code = ExitCode::from_u32(code)
24-
//.filter(|c| !c.is_system_error())
25-
.unwrap_or(ExitCode::SysErrIllegalActor); // TODO: will become "illegal exit"
20+
let code = ExitCode::new(code);
21+
// Uncomment to fix https://github.com/filecoin-project/ref-fvm/issues/253
22+
// if code.is_system_error() {
23+
// return Err(Abort::Exit(
24+
// SystemExitCode::ILLEGAL_EXIT_CODE,
25+
// format!("actor aborted with code {}", code),
26+
// ));
27+
// }
2628

2729
let message = if message_len == 0 {
2830
"actor aborted".to_owned()

sdk/src/message.rs

Lines changed: 2 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,9 @@
1-
use fvm_ipld_encoding::{Cbor, DAG_CBOR};
1+
use fvm_ipld_encoding::DAG_CBOR;
22
use fvm_shared::econ::TokenAmount;
3-
use fvm_shared::error::{ErrorNumber, ExitCode};
43
use fvm_shared::sys::{BlockId, Codec};
54
use fvm_shared::{ActorID, MethodNum};
65

7-
use crate::{sys, vm, SyscallResult};
6+
use crate::{sys, SyscallResult};
87

98
/// BlockID representing nil parameters or return data.
109
pub const NO_DATA_BLOCK_ID: u32 = 0;
@@ -63,23 +62,3 @@ pub fn value_received() -> TokenAmount {
6362
.into()
6463
}
6564
}
66-
67-
/// Fetches the input parameters as raw bytes, and decodes them locally
68-
/// into type T using cbor serde. Failing to decode will abort execution.
69-
///
70-
/// This function errors with ErrIllegalArgument when no parameters have been
71-
/// provided.
72-
pub fn params_cbor<T: Cbor>(id: BlockId) -> SyscallResult<T> {
73-
if id == NO_DATA_BLOCK_ID {
74-
return Err(ErrorNumber::IllegalArgument);
75-
}
76-
let (codec, raw) = params_raw(id)?;
77-
debug_assert!(codec == DAG_CBOR, "parameters codec was not cbor");
78-
match fvm_ipld_encoding::from_slice(raw.as_slice()) {
79-
Ok(v) => Ok(v),
80-
Err(e) => vm::abort(
81-
ExitCode::ErrSerialization as u32,
82-
Some(format!("could not deserialize parameters as cbor: {:?}", e).as_str()),
83-
),
84-
}
85-
}

sdk/src/send.rs

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@ use fvm_shared::econ::TokenAmount;
66
use fvm_shared::error::{ErrorNumber, ExitCode};
77
use fvm_shared::receipt::Receipt;
88
use fvm_shared::MethodNum;
9-
use num_traits::FromPrimitive;
109

1110
use crate::message::NO_DATA_BLOCK_ID;
1211
use crate::{sys, SyscallResult};
@@ -47,9 +46,9 @@ pub fn send(
4746
)?;
4847

4948
// Process the result.
50-
let exit_code = ExitCode::from_u32(exit_code).unwrap_or(ExitCode::SysErrIllegalActor);
49+
let exit_code = ExitCode::new(exit_code);
5150
let return_data = match exit_code {
52-
ExitCode::Ok if return_id != NO_DATA_BLOCK_ID => {
51+
ExitCode::OK if return_id != NO_DATA_BLOCK_ID => {
5352
// Allocate a buffer to read the return data.
5453
let fvm_shared::sys::out::ipld::IpldStat { size, .. } = sys::ipld::stat(return_id)?;
5554
let mut bytes = vec![0; size as usize];

0 commit comments

Comments
 (0)