Skip to content

Commit 07dd602

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 07dd602

File tree

12 files changed

+284
-315
lines changed

12 files changed

+284
-315
lines changed

actors/init/src/lib.rs

Lines changed: 28 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
@@ -170,42 +165,35 @@ impl Actor {
170165
RT: Runtime<BS>,
171166
{
172167
use cid::multihash::Code;
168+
use fil_actors_runtime::AsActorError;
173169
use fvm_ipld_blockstore::Block;
170+
use fvm_shared::error::ExitCode;
174171

175172
rt.validate_immediate_caller_accept_any()?;
176173

177174
let (code_cid, installed) = rt.transaction(|st: &mut State, rt| {
178175
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-
})? {
176+
let code_cid = rt.store().put(Code::Blake2b256, &Block::new(0x55, code)).context_code(
177+
ExitCode::USR_SERIALIZATION,
178+
"failed to put code into the bockstore",
179+
)?;
180+
181+
if st.is_installed_actor(rt.store(), &code_cid).context_code(
182+
ExitCode::USR_ILLEGAL_STATE,
183+
"failed to check state for installed actor",
184+
)? {
193185
return Ok((code_cid, false));
194186
}
195187

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-
})?;
188+
rt.install_actor(&code_cid).context_code(
189+
ExitCode::USR_ILLEGAL_ARGUMENT,
190+
"failed to check state for installed actor",
191+
)?;
202192

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-
})?;
193+
st.add_installed_actor(rt.store(), code_cid).context_code(
194+
ExitCode::USR_ILLEGAL_STATE,
195+
"failed to add installed actor to state",
196+
)?;
209197
Ok((code_cid, true))
210198
})?;
211199

actors/init/src/state.rs

Lines changed: 55 additions & 28 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,12 +28,15 @@ 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")]
36-
let installed_actors = store.put_cbor(&Vec::<Cid>::new(), Code::Blake2b256)?;
36+
let installed_actors = store.put_cbor(&Vec::<Cid>::new(), Code::Blake2b256).context_code(
37+
ExitCode::USR_ILLEGAL_STATE,
38+
"failed to create installed actors object",
39+
)?;
3740
Ok(Self {
3841
address_map: empty_map,
3942
next_id: FIRST_NON_SINGLETON_ADDR,
@@ -52,22 +55,26 @@ impl State {
5255
&mut self,
5356
store: &BS,
5457
addr: &Address,
55-
) -> anyhow::Result<ActorID> {
58+
) -> Result<ActorID, ActorError> {
5659
let id = self.next_id;
5760
self.next_id += 1;
5861

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)?;
62+
let mut map = make_map_with_root_and_bitwidth(&self.address_map, store, HAMT_BIT_WIDTH)
63+
.context_code(ExitCode::USR_ILLEGAL_STATE, "failed to load address map")?;
64+
let is_new = map
65+
.set_if_absent(addr.to_bytes().into(), id)
66+
.context_code(ExitCode::USR_ILLEGAL_STATE, "failed to set map key")?;
6167
if !is_new {
6268
// this is impossible today as the robust address is a hash of unique inputs
6369
// but in close future predictable address generation will make this possible
64-
return Err(anyhow!(actor_error!(
70+
return Err(actor_error!(
6571
forbidden,
6672
"robust address {} is already allocated in the address map",
6773
addr
68-
)));
74+
));
6975
}
70-
self.address_map = map.flush()?;
76+
self.address_map =
77+
map.flush().context_code(ExitCode::USR_ILLEGAL_STATE, "failed to store address map")?;
7178

7279
Ok(id)
7380
}
@@ -79,37 +86,45 @@ impl State {
7986
store: &BS,
8087
addr: &Address,
8188
f4addr: &Address,
82-
) -> anyhow::Result<ActorID>
89+
) -> Result<ActorID, ActorError>
8390
where
8491
BS: Blockstore,
8592
{
86-
let mut map = make_map_with_root_and_bitwidth(&self.address_map, store, HAMT_BIT_WIDTH)?;
93+
let mut map = make_map_with_root_and_bitwidth(&self.address_map, store, HAMT_BIT_WIDTH)
94+
.context_code(ExitCode::USR_ILLEGAL_STATE, "failed to load address map")?;
8795

8896
// Assign a new ID address, or use the one currently mapped to the f4 address. We don't
8997
// bother checking if the target actor is an embryo here, the FVM will check that when we go to create the actor.
9098
let f4addr_key = f4addr.to_bytes().into();
91-
let id: u64 = match map.get(&f4addr_key)? {
99+
let id: u64 = match map
100+
.get(&f4addr_key)
101+
.context_code(ExitCode::USR_ILLEGAL_STATE, "failed to lookup f4 address in map")?
102+
{
92103
Some(id) => *id,
93104
None => {
94105
let id = self.next_id;
95106
self.next_id += 1;
96-
map.set(f4addr_key, id)?;
107+
map.set(f4addr_key, id)
108+
.context_code(ExitCode::USR_ILLEGAL_STATE, "failed to set f4 address in map")?;
97109
id
98110
}
99111
};
100112

101113
// Then go ahead and assign the f2 address.
102-
let is_new = map.set_if_absent(addr.to_bytes().into(), id)?;
114+
let is_new = map
115+
.set_if_absent(addr.to_bytes().into(), id)
116+
.context_code(ExitCode::USR_ILLEGAL_STATE, "failed to set map key")?;
103117
if !is_new {
104118
// this is impossible today as the robust address is a hash of unique inputs
105119
// but in close future predictable address generation will make this possible
106-
return Err(anyhow!(actor_error!(
120+
return Err(actor_error!(
107121
forbidden,
108122
"robust address {} is already allocated in the address map",
109123
addr
110-
)));
124+
));
111125
}
112-
self.address_map = map.flush()?;
126+
self.address_map =
127+
map.flush().context_code(ExitCode::USR_ILLEGAL_STATE, "failed to store address map")?;
113128

114129
Ok(id)
115130
}
@@ -128,14 +143,18 @@ impl State {
128143
&self,
129144
store: &BS,
130145
addr: &Address,
131-
) -> anyhow::Result<Option<Address>> {
146+
) -> Result<Option<Address>, ActorError> {
132147
if addr.protocol() == Protocol::ID {
133148
return Ok(Some(*addr));
134149
}
135150

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

138-
Ok(map.get(&addr.to_bytes())?.copied().map(Address::new_id))
154+
let found = map
155+
.get(&addr.to_bytes())
156+
.context_code(ExitCode::USR_ILLEGAL_STATE, "failed to get address entry")?;
157+
Ok(found.copied().map(Address::new_id))
139158
}
140159

141160
/// Check to see if an actor is already installed
@@ -144,8 +163,11 @@ impl State {
144163
&self,
145164
store: &BS,
146165
cid: &Cid,
147-
) -> anyhow::Result<bool> {
148-
let installed: Vec<Cid> = match store.get_cbor(&self.installed_actors)? {
166+
) -> Result<bool, ActorError> {
167+
let installed: Vec<Cid> = match store
168+
.get_cbor(&self.installed_actors)
169+
.context_code(ExitCode::USR_ILLEGAL_STATE, "failed to load installed actor list")?
170+
{
149171
Some(v) => v,
150172
None => Vec::new(),
151173
};
@@ -158,13 +180,18 @@ impl State {
158180
&mut self,
159181
store: &BS,
160182
cid: Cid,
161-
) -> anyhow::Result<()> {
162-
let mut installed: Vec<Cid> = match store.get_cbor(&self.installed_actors)? {
183+
) -> Result<(), ActorError> {
184+
let mut installed: Vec<Cid> = match store
185+
.get_cbor(&self.installed_actors)
186+
.context_code(ExitCode::USR_ILLEGAL_STATE, "failed to load installed actor list")?
187+
{
163188
Some(v) => v,
164189
None => Vec::new(),
165190
};
166191
installed.push(cid);
167-
self.installed_actors = store.put_cbor(&installed, Code::Blake2b256)?;
192+
self.installed_actors = store
193+
.put_cbor(&installed, Code::Blake2b256)
194+
.context_code(ExitCode::USR_ILLEGAL_STATE, "failed to save installed actor list")?;
168195
Ok(())
169196
}
170197
}

0 commit comments

Comments
 (0)