Skip to content

Commit 6ecf99d

Browse files
anorthdignifiedquire
authored andcommitted
Traits and impls for adding context and exit codes to results. (#589)
Co-authored-by: dignifiedquire <[email protected]>
1 parent 023dd20 commit 6ecf99d

File tree

12 files changed

+267
-311
lines changed

12 files changed

+267
-311
lines changed

actors/init/src/lib.rs

Lines changed: 26 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -5,12 +5,12 @@ use std::iter;
55

66
use cid::Cid;
77
use fil_actors_runtime::runtime::{ActorCode, Runtime};
8-
use fil_actors_runtime::EAM_ACTOR_ADDR;
9-
use fil_actors_runtime::{actor_error, cbor, ActorDowncast, ActorError, SYSTEM_ACTOR_ADDR};
8+
use fil_actors_runtime::{
9+
actor_error, cbor, ActorContext, ActorError, EAM_ACTOR_ADDR, SYSTEM_ACTOR_ADDR,
10+
};
1011
use fvm_ipld_blockstore::Blockstore;
1112
use fvm_ipld_encoding::RawBytes;
1213
use fvm_shared::address::Address;
13-
use fvm_shared::error::ExitCode;
1414
use fvm_shared::{ActorID, MethodNum, METHOD_CONSTRUCTOR};
1515
use num_derive::FromPrimitive;
1616
use num_traits::FromPrimitive;
@@ -47,10 +47,7 @@ impl Actor {
4747
{
4848
let sys_ref: &Address = &SYSTEM_ACTOR_ADDR;
4949
rt.validate_immediate_caller_is(std::iter::once(sys_ref))?;
50-
let state = State::new(rt.store(), params.network_name).map_err(|e| {
51-
e.downcast_default(ExitCode::USR_ILLEGAL_STATE, "failed to construct init actor state")
52-
})?;
53-
50+
let state = State::new(rt.store(), params.network_name)?;
5451
rt.create(&state)?;
5552

5653
Ok(())
@@ -91,9 +88,8 @@ impl Actor {
9188
// Allocate an ID for this actor.
9289
// Store mapping of actor addresses to the actor ID.
9390
let id_address: ActorID = rt.transaction(|s: &mut State, rt| {
94-
s.map_address_to_new_id(rt.store(), &robust_address).map_err(|e| {
95-
e.downcast_default(ExitCode::USR_ILLEGAL_STATE, "failed to allocate ID address")
96-
})
91+
s.map_address_to_new_id(rt.store(), &robust_address)
92+
.context("failed to allocate ID address")
9793
})?;
9894

9995
// Create an empty actor
@@ -106,7 +102,7 @@ impl Actor {
106102
params.constructor_params,
107103
rt.message().value_received(),
108104
)
109-
.map_err(|err| err.wrap("constructor failed"))?;
105+
.context("constructor failed")?;
110106

111107
Ok(ExecReturn { id_address: Address::new_id(id_address), robust_address })
112108
}
@@ -143,9 +139,8 @@ impl Actor {
143139
// Allocate an ID for this actor.
144140
// Store mapping of actor addresses to the actor ID.
145141
let id_address: ActorID = rt.transaction(|s: &mut State, rt| {
146-
s.map_address_to_f4(rt.store(), &robust_address, &delegated_address).map_err(|e| {
147-
e.downcast_default(ExitCode::USR_ILLEGAL_STATE, "failed to allocate ID address")
148-
})
142+
s.map_address_to_f4(rt.store(), &robust_address, &delegated_address)
143+
.context("constructor failed")
149144
})?;
150145

151146
// Create an empty actor
@@ -176,36 +171,27 @@ impl Actor {
176171

177172
let (code_cid, installed) = rt.transaction(|st: &mut State, rt| {
178173
let code = params.code.bytes();
179-
let code_cid =
180-
rt.store().put(Code::Blake2b256, &Block::new(0x55, code)).map_err(|e| {
181-
e.downcast_default(
182-
ExitCode::USR_SERIALIZATION,
183-
"failed to put code into the bockstore",
184-
)
185-
})?;
186-
187-
if st.is_installed_actor(rt.store(), &code_cid).map_err(|e| {
188-
e.downcast_default(
189-
ExitCode::USR_ILLEGAL_STATE,
190-
"failed to check state for installed actor",
191-
)
192-
})? {
174+
let code_cid = rt.store().put(Code::Blake2b256, &Block::new(0x55, code)).context_code(
175+
ExitCode::USR_SERIALIZATION,
176+
"failed to put code into the bockstore",
177+
)?;
178+
179+
if st.is_installed_actor(rt.store(), &code_cid).context_code(
180+
ExitCode::USR_ILLEGAL_STATE,
181+
"failed to check state for installed actor",
182+
)? {
193183
return Ok((code_cid, false));
194184
}
195185

196-
rt.install_actor(&code_cid).map_err(|e| {
197-
e.downcast_default(
198-
ExitCode::USR_ILLEGAL_ARGUMENT,
199-
"failed to check state for installed actor",
200-
)
201-
})?;
186+
rt.install_actor(&code_cid).context_code(
187+
ExitCode::USR_ILLEGAL_ARGUMENT,
188+
"failed to check state for installed actor",
189+
)?;
202190

203-
st.add_installed_actor(rt.store(), code_cid).map_err(|e| {
204-
e.downcast_default(
205-
ExitCode::USR_ILLEGAL_STATE,
206-
"failed to add installed actor to state",
207-
)
208-
})?;
191+
st.add_installed_actor(rt.store(), code_cid).context_code(
192+
ExitCode::USR_ILLEGAL_STATE,
193+
"failed to add installed actor to state",
194+
)?;
209195
Ok((code_cid, true))
210196
})?;
211197

actors/init/src/state.rs

Lines changed: 40 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,20 @@
11
// Copyright 2019-2022 ChainSafe Systems
22
// SPDX-License-Identifier: Apache-2.0, MIT
33

4-
use anyhow::anyhow;
54
#[cfg(feature = "m2-native")]
65
use cid::multihash::Code;
76
use cid::Cid;
8-
use fil_actors_runtime::actor_error;
97
use fil_actors_runtime::{
10-
make_empty_map, make_map_with_root_and_bitwidth, FIRST_NON_SINGLETON_ADDR,
8+
actor_error, make_empty_map, make_map_with_root_and_bitwidth, ActorError, AsActorError,
9+
FIRST_NON_SINGLETON_ADDR,
1110
};
1211
use fvm_ipld_blockstore::Blockstore;
1312
use fvm_ipld_encoding::tuple::*;
1413
use fvm_ipld_encoding::Cbor;
1514
#[cfg(feature = "m2-native")]
1615
use fvm_ipld_encoding::CborStore;
1716
use fvm_shared::address::{Address, Protocol};
17+
use fvm_shared::error::ExitCode;
1818
use fvm_shared::{ActorID, HAMT_BIT_WIDTH};
1919

2020
/// State is reponsible for creating
@@ -28,10 +28,10 @@ pub struct State {
2828
}
2929

3030
impl State {
31-
pub fn new<BS: Blockstore>(store: &BS, network_name: String) -> anyhow::Result<Self> {
31+
pub fn new<BS: Blockstore>(store: &BS, network_name: String) -> Result<Self, ActorError> {
3232
let empty_map = make_empty_map::<_, ()>(store, HAMT_BIT_WIDTH)
3333
.flush()
34-
.map_err(|e| anyhow!("failed to create empty map: {}", e))?;
34+
.context_code(ExitCode::USR_ILLEGAL_STATE, "failed to create empty map")?;
3535
#[cfg(feature = "m2-native")]
3636
let installed_actors = store.put_cbor(&Vec::<Cid>::new(), Code::Blake2b256)?;
3737
Ok(Self {
@@ -52,22 +52,26 @@ impl State {
5252
&mut self,
5353
store: &BS,
5454
addr: &Address,
55-
) -> anyhow::Result<ActorID> {
55+
) -> Result<ActorID, ActorError> {
5656
let id = self.next_id;
5757
self.next_id += 1;
5858

59-
let mut map = make_map_with_root_and_bitwidth(&self.address_map, store, HAMT_BIT_WIDTH)?;
60-
let is_new = map.set_if_absent(addr.to_bytes().into(), id)?;
59+
let mut map = make_map_with_root_and_bitwidth(&self.address_map, store, HAMT_BIT_WIDTH)
60+
.context_code(ExitCode::USR_ILLEGAL_STATE, "failed to load address map")?;
61+
let is_new = map
62+
.set_if_absent(addr.to_bytes().into(), id)
63+
.context_code(ExitCode::USR_ILLEGAL_STATE, "failed to set map key")?;
6164
if !is_new {
6265
// this is impossible today as the robust address is a hash of unique inputs
6366
// but in close future predictable address generation will make this possible
64-
return Err(anyhow!(actor_error!(
67+
return Err(actor_error!(
6568
forbidden,
6669
"robust address {} is already allocated in the address map",
6770
addr
68-
)));
71+
));
6972
}
70-
self.address_map = map.flush()?;
73+
self.address_map =
74+
map.flush().context_code(ExitCode::USR_ILLEGAL_STATE, "failed to store address map")?;
7175

7276
Ok(id)
7377
}
@@ -79,37 +83,45 @@ impl State {
7983
store: &BS,
8084
addr: &Address,
8185
f4addr: &Address,
82-
) -> anyhow::Result<ActorID>
86+
) -> Result<ActorID, ActorError>
8387
where
8488
BS: Blockstore,
8589
{
86-
let mut map = make_map_with_root_and_bitwidth(&self.address_map, store, HAMT_BIT_WIDTH)?;
90+
let mut map = make_map_with_root_and_bitwidth(&self.address_map, store, HAMT_BIT_WIDTH)
91+
.context_code(ExitCode::USR_ILLEGAL_STATE, "failed to load address map")?;
8792

8893
// Assign a new ID address, or use the one currently mapped to the f4 address. We don't
8994
// bother checking if the target actor is an embryo here, the FVM will check that when we go to create the actor.
9095
let f4addr_key = f4addr.to_bytes().into();
91-
let id: u64 = match map.get(&f4addr_key)? {
96+
let id: u64 = match map
97+
.get(&f4addr_key)
98+
.context_code(ExitCode::USR_ILLEGAL_STATE, "failed to lookup f4 address in map")?
99+
{
92100
Some(id) => *id,
93101
None => {
94102
let id = self.next_id;
95103
self.next_id += 1;
96-
map.set(f4addr_key, id)?;
104+
map.set(f4addr_key, id)
105+
.context_code(ExitCode::USR_ILLEGAL_STATE, "failed to set f4 address in map")?;
97106
id
98107
}
99108
};
100109

101110
// Then go ahead and assign the f2 address.
102-
let is_new = map.set_if_absent(addr.to_bytes().into(), id)?;
111+
let is_new = map
112+
.set_if_absent(addr.to_bytes().into(), id)
113+
.context_code(ExitCode::USR_ILLEGAL_STATE, "failed to set map key")?;
103114
if !is_new {
104115
// this is impossible today as the robust address is a hash of unique inputs
105116
// but in close future predictable address generation will make this possible
106-
return Err(anyhow!(actor_error!(
117+
return Err(actor_error!(
107118
forbidden,
108119
"robust address {} is already allocated in the address map",
109120
addr
110-
)));
121+
));
111122
}
112-
self.address_map = map.flush()?;
123+
self.address_map =
124+
map.flush().context_code(ExitCode::USR_ILLEGAL_STATE, "failed to store address map")?;
113125

114126
Ok(id)
115127
}
@@ -128,14 +140,18 @@ impl State {
128140
&self,
129141
store: &BS,
130142
addr: &Address,
131-
) -> anyhow::Result<Option<Address>> {
143+
) -> Result<Option<Address>, ActorError> {
132144
if addr.protocol() == Protocol::ID {
133145
return Ok(Some(*addr));
134146
}
135147

136-
let map = make_map_with_root_and_bitwidth(&self.address_map, store, HAMT_BIT_WIDTH)?;
148+
let map = make_map_with_root_and_bitwidth(&self.address_map, store, HAMT_BIT_WIDTH)
149+
.context_code(ExitCode::USR_ILLEGAL_STATE, "failed to load address map")?;
137150

138-
Ok(map.get(&addr.to_bytes())?.copied().map(Address::new_id))
151+
let found = map
152+
.get(&addr.to_bytes())
153+
.context_code(ExitCode::USR_ILLEGAL_STATE, "failed to get address entry")?;
154+
Ok(found.copied().map(Address::new_id))
139155
}
140156

141157
/// Check to see if an actor is already installed
@@ -144,7 +160,7 @@ impl State {
144160
&self,
145161
store: &BS,
146162
cid: &Cid,
147-
) -> anyhow::Result<bool> {
163+
) -> Result<bool, ActorError> {
148164
let installed: Vec<Cid> = match store.get_cbor(&self.installed_actors)? {
149165
Some(v) => v,
150166
None => Vec::new(),
@@ -158,7 +174,7 @@ impl State {
158174
&mut self,
159175
store: &BS,
160176
cid: Cid,
161-
) -> anyhow::Result<()> {
177+
) -> Result<(), ActorError> {
162178
let mut installed: Vec<Cid> = match store.get_cbor(&self.installed_actors)? {
163179
Some(v) => v,
164180
None => Vec::new(),

0 commit comments

Comments
 (0)