Skip to content

Commit

Permalink
Traits and impls for adding context and exit codes to results. (filec…
Browse files Browse the repository at this point in the history
…oin-project#589)

Co-authored-by: dignifiedquire <me@dignifiedquire.com>
  • Loading branch information
2 people authored and shamb0 committed Oct 3, 2022
1 parent ad6f4f6 commit 6faa394
Show file tree
Hide file tree
Showing 2 changed files with 50 additions and 43 deletions.
50 changes: 21 additions & 29 deletions actors/init/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -137,9 +137,8 @@ impl Actor {
// Allocate an ID for this actor.
// Store mapping of actor addresses to the actor ID.
let id_address: ActorID = rt.transaction(|s: &mut State, rt| {
s.map_address_to_f4(rt.store(), &robust_address, &delegated_address).map_err(|e| {
e.downcast_default(ExitCode::USR_ILLEGAL_STATE, "failed to allocate ID address")
})
s.map_address_to_f4(rt.store(), &robust_address, &delegated_address)
.context("constructor failed")
})?;

// Create an empty actor
Expand All @@ -164,42 +163,35 @@ impl Actor {
RT: Runtime<BS>,
{
use cid::multihash::Code;
use fil_actors_runtime::AsActorError;
use fvm_ipld_blockstore::Block;
use fvm_shared::error::ExitCode;

rt.validate_immediate_caller_accept_any()?;

let (code_cid, installed) = rt.transaction(|st: &mut State, rt| {
let code = params.code.bytes();
let code_cid =
rt.store().put(Code::Blake2b256, &Block::new(0x55, code)).map_err(|e| {
e.downcast_default(
ExitCode::USR_SERIALIZATION,
"failed to put code into the bockstore",
)
})?;

if st.is_installed_actor(rt.store(), &code_cid).map_err(|e| {
e.downcast_default(
ExitCode::USR_ILLEGAL_STATE,
"failed to check state for installed actor",
)
})? {
let code_cid = rt.store().put(Code::Blake2b256, &Block::new(0x55, code)).context_code(
ExitCode::USR_SERIALIZATION,
"failed to put code into the bockstore",
)?;

if st.is_installed_actor(rt.store(), &code_cid).context_code(
ExitCode::USR_ILLEGAL_STATE,
"failed to check state for installed actor",
)? {
return Ok((code_cid, false));
}

rt.install_actor(&code_cid).map_err(|e| {
e.downcast_default(
ExitCode::USR_ILLEGAL_ARGUMENT,
"failed to check state for installed actor",
)
})?;
rt.install_actor(&code_cid).context_code(
ExitCode::USR_ILLEGAL_ARGUMENT,
"failed to check state for installed actor",
)?;

st.add_installed_actor(rt.store(), code_cid).map_err(|e| {
e.downcast_default(
ExitCode::USR_ILLEGAL_STATE,
"failed to add installed actor to state",
)
})?;
st.add_installed_actor(rt.store(), code_cid).context_code(
ExitCode::USR_ILLEGAL_STATE,
"failed to add installed actor to state",
)?;
Ok((code_cid, true))
})?;

Expand Down
43 changes: 29 additions & 14 deletions actors/init/src/state.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@
// SPDX-License-Identifier: Apache-2.0, MIT

use cid::Cid;
use fil_actors_runtime::actor_error;
use fil_actors_runtime::{
actor_error, make_empty_map, make_map_with_root_and_bitwidth, ActorError, AsActorError,
FIRST_NON_SINGLETON_ADDR,
Expand Down Expand Up @@ -72,37 +71,45 @@ impl State {
store: &BS,
addr: &Address,
f4addr: &Address,
) -> anyhow::Result<ActorID>
) -> Result<ActorID, ActorError>
where
BS: Blockstore,
{
let mut map = make_map_with_root_and_bitwidth(&self.address_map, store, HAMT_BIT_WIDTH)?;
let mut map = make_map_with_root_and_bitwidth(&self.address_map, store, HAMT_BIT_WIDTH)
.context_code(ExitCode::USR_ILLEGAL_STATE, "failed to load address map")?;

// Assign a new ID address, or use the one currently mapped to the f4 address. We don't
// bother checking if the target actor is an embryo here, the FVM will check that when we go to create the actor.
let f4addr_key = f4addr.to_bytes().into();
let id: u64 = match map.get(&f4addr_key)? {
let id: u64 = match map
.get(&f4addr_key)
.context_code(ExitCode::USR_ILLEGAL_STATE, "failed to lookup f4 address in map")?
{
Some(id) => *id,
None => {
let id = self.next_id;
self.next_id += 1;
map.set(f4addr_key, id)?;
map.set(f4addr_key, id)
.context_code(ExitCode::USR_ILLEGAL_STATE, "failed to set f4 address in map")?;
id
}
};

// Then go ahead and assign the f2 address.
let is_new = map.set_if_absent(addr.to_bytes().into(), id)?;
let is_new = map
.set_if_absent(addr.to_bytes().into(), id)
.context_code(ExitCode::USR_ILLEGAL_STATE, "failed to set map key")?;
if !is_new {
// this is impossible today as the robust address is a hash of unique inputs
// but in close future predictable address generation will make this possible
return Err(anyhow!(actor_error!(
return Err(actor_error!(
forbidden,
"robust address {} is already allocated in the address map",
addr
)));
));
}
self.address_map = map.flush()?;
self.address_map =
map.flush().context_code(ExitCode::USR_ILLEGAL_STATE, "failed to store address map")?;

Ok(id)
}
Expand Down Expand Up @@ -141,8 +148,11 @@ impl State {
&self,
store: &BS,
cid: &Cid,
) -> anyhow::Result<bool> {
let installed: Vec<Cid> = match store.get_cbor(&self.installed_actors)? {
) -> Result<bool, ActorError> {
let installed: Vec<Cid> = match store
.get_cbor(&self.installed_actors)
.context_code(ExitCode::USR_ILLEGAL_STATE, "failed to load installed actor list")?
{
Some(v) => v,
None => Vec::new(),
};
Expand All @@ -155,13 +165,18 @@ impl State {
&mut self,
store: &BS,
cid: Cid,
) -> anyhow::Result<()> {
let mut installed: Vec<Cid> = match store.get_cbor(&self.installed_actors)? {
) -> Result<(), ActorError> {
let mut installed: Vec<Cid> = match store
.get_cbor(&self.installed_actors)
.context_code(ExitCode::USR_ILLEGAL_STATE, "failed to load installed actor list")?
{
Some(v) => v,
None => Vec::new(),
};
installed.push(cid);
self.installed_actors = store.put_cbor(&installed, Code::Blake2b256)?;
self.installed_actors = store
.put_cbor(&installed, Code::Blake2b256)
.context_code(ExitCode::USR_ILLEGAL_STATE, "failed to save installed actor list")?;
Ok(())
}
}
Expand Down

0 comments on commit 6faa394

Please sign in to comment.