Skip to content

Commit 8882852

Browse files
authored
Initial implementation of new, more convenient Map wrapping HAMT (#1349)
* Initial implementation of new, more convenient Map wrapping HAMT * MapKey trait
1 parent f9b5760 commit 8882852

File tree

7 files changed

+262
-86
lines changed

7 files changed

+262
-86
lines changed

Cargo.lock

Lines changed: 1 addition & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

actors/init/src/state.rs

Lines changed: 15 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -2,30 +2,27 @@
22
// SPDX-License-Identifier: Apache-2.0, MIT
33

44
use cid::Cid;
5-
use fil_actors_runtime::{
6-
actor_error, make_empty_map, make_map_with_root_and_bitwidth, ActorError, AsActorError,
7-
FIRST_NON_SINGLETON_ADDR,
8-
};
95
use fvm_ipld_blockstore::Blockstore;
106
use fvm_ipld_encoding::tuple::*;
117
use fvm_shared::address::{Address, Protocol};
12-
use fvm_shared::error::ExitCode;
13-
use fvm_shared::{ActorID, HAMT_BIT_WIDTH};
8+
use fvm_shared::ActorID;
9+
10+
use fil_actors_runtime::{actor_error, ActorError, Map2, DEFAULT_CONF, FIRST_NON_SINGLETON_ADDR};
1411

15-
/// State is reponsible for creating
1612
#[derive(Serialize_tuple, Deserialize_tuple, Clone, Debug)]
1713
pub struct State {
14+
/// HAMT[Address]ActorID
1815
pub address_map: Cid,
1916
pub next_id: ActorID,
2017
pub network_name: String,
2118
}
2219

20+
pub type AddressMap<BS> = Map2<BS, Address, ActorID>;
21+
2322
impl State {
2423
pub fn new<BS: Blockstore>(store: &BS, network_name: String) -> Result<Self, ActorError> {
25-
let empty_map = make_empty_map::<_, ()>(store, HAMT_BIT_WIDTH)
26-
.flush()
27-
.context_code(ExitCode::USR_ILLEGAL_STATE, "failed to create empty map")?;
28-
Ok(Self { address_map: empty_map, next_id: FIRST_NON_SINGLETON_ADDR, network_name })
24+
let empty = AddressMap::flush_empty(store, DEFAULT_CONF)?;
25+
Ok(Self { address_map: empty, next_id: FIRST_NON_SINGLETON_ADDR, network_name })
2926
}
3027

3128
/// Maps argument addresses to to a new or existing actor ID.
@@ -40,22 +37,16 @@ impl State {
4037
robust_addr: &Address,
4138
delegated_addr: Option<&Address>,
4239
) -> Result<(ActorID, bool), ActorError> {
43-
let mut map = make_map_with_root_and_bitwidth(&self.address_map, store, HAMT_BIT_WIDTH)
44-
.context_code(ExitCode::USR_ILLEGAL_STATE, "failed to load address map")?;
40+
let mut map = AddressMap::load(store, &self.address_map, DEFAULT_CONF, "addresses")?;
4541
let (id, existing) = if let Some(delegated_addr) = delegated_addr {
4642
// If there's a delegated address, either recall the already-mapped actor ID or
4743
// create and map a new one.
48-
let delegated_key = delegated_addr.to_bytes().into();
49-
if let Some(existing_id) = map
50-
.get(&delegated_key)
51-
.context_code(ExitCode::USR_ILLEGAL_STATE, "failed to lookup delegated address")?
52-
{
44+
if let Some(existing_id) = map.get(delegated_addr)? {
5345
(*existing_id, true)
5446
} else {
5547
let new_id = self.next_id;
5648
self.next_id += 1;
57-
map.set(delegated_key, new_id)
58-
.context_code(ExitCode::USR_ILLEGAL_STATE, "failed to map delegated address")?;
49+
map.set(delegated_addr, new_id)?;
5950
(new_id, false)
6051
}
6152
} else {
@@ -66,18 +57,15 @@ impl State {
6657
};
6758

6859
// Map the robust address to the ID, failing if it's already mapped to anything.
69-
let is_new = map
70-
.set_if_absent(robust_addr.to_bytes().into(), id)
71-
.context_code(ExitCode::USR_ILLEGAL_STATE, "failed to map robust address")?;
60+
let is_new = map.set_if_absent(robust_addr, id)?;
7261
if !is_new {
7362
return Err(actor_error!(
7463
forbidden,
7564
"robust address {} is already allocated in the address map",
7665
robust_addr
7766
));
7867
}
79-
self.address_map =
80-
map.flush().context_code(ExitCode::USR_ILLEGAL_STATE, "failed to store address map")?;
68+
self.address_map = map.flush()?;
8169
Ok((id, existing))
8270
}
8371

@@ -99,13 +87,8 @@ impl State {
9987
if addr.protocol() == Protocol::ID {
10088
return Ok(Some(*addr));
10189
}
102-
103-
let map = make_map_with_root_and_bitwidth(&self.address_map, store, HAMT_BIT_WIDTH)
104-
.context_code(ExitCode::USR_ILLEGAL_STATE, "failed to load address map")?;
105-
106-
let found = map
107-
.get(&addr.to_bytes())
108-
.context_code(ExitCode::USR_ILLEGAL_STATE, "failed to get address entry")?;
90+
let map = AddressMap::load(store, &self.address_map, DEFAULT_CONF, "addresses")?;
91+
let found = map.get(addr)?;
10992
Ok(found.copied().map(Address::new_id))
11093
}
11194
}

actors/init/src/testing.rs

Lines changed: 13 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,14 @@
11
use std::collections::HashMap;
22

3-
use fil_actors_runtime::{Map, MessageAccumulator, FIRST_NON_SINGLETON_ADDR};
43
use fvm_ipld_blockstore::Blockstore;
54
use fvm_shared::{
65
address::{Address, Protocol},
76
ActorID,
87
};
98

9+
use fil_actors_runtime::{MessageAccumulator, DEFAULT_CONF, FIRST_NON_SINGLETON_ADDR};
10+
11+
use crate::state::AddressMap;
1012
use crate::State;
1113

1214
pub struct StateSummary {
@@ -31,44 +33,37 @@ pub fn check_state_invariants<BS: Blockstore>(
3133

3234
let mut stable_address_by_id = HashMap::<ActorID, Address>::new();
3335
let mut delegated_address_by_id = HashMap::<ActorID, Address>::new();
34-
match Map::<_, ActorID>::load(&state.address_map, store) {
36+
37+
match AddressMap::load(store, &state.address_map, DEFAULT_CONF, "addresses") {
3538
Ok(address_map) => {
3639
let ret = address_map.for_each(|key, actor_id| {
37-
let key_address = Address::from_bytes(key)?;
38-
39-
acc.require(
40-
key_address.protocol() != Protocol::ID,
41-
format!("key {key_address} is an ID address"),
42-
);
40+
acc.require(key.protocol() != Protocol::ID, format!("key {key} is an ID address"));
4341
acc.require(
4442
actor_id >= &FIRST_NON_SINGLETON_ADDR,
4543
format!("unexpected singleton ID value {actor_id}"),
4644
);
4745

48-
match key_address.protocol() {
46+
match key.protocol() {
4947
Protocol::ID => {
50-
acc.add(format!("key {key_address} is an ID address"));
48+
acc.add(format!("key {key} is an ID address"));
5149
}
5250
Protocol::Delegated => {
53-
if let Some(duplicate) =
54-
delegated_address_by_id.insert(*actor_id, key_address)
55-
{
51+
if let Some(duplicate) = delegated_address_by_id.insert(*actor_id, key) {
5652
acc.add(format!(
57-
"duplicate mapping to ID {actor_id}: {key_address} {duplicate}"
53+
"duplicate mapping to ID {actor_id}: {key} {duplicate}"
5854
));
5955
}
6056
}
6157
_ => {
62-
if let Some(duplicate) = stable_address_by_id.insert(*actor_id, key_address)
63-
{
58+
if let Some(duplicate) = stable_address_by_id.insert(*actor_id, key) {
6459
acc.add(format!(
65-
"duplicate mapping to ID {actor_id}: {key_address} {duplicate}"
60+
"duplicate mapping to ID {actor_id}: {key} {duplicate}"
6661
));
6762
}
6863
}
6964
}
7065

71-
init_summary.ids_by_address.insert(key_address, *actor_id);
66+
init_summary.ids_by_address.insert(key, *actor_id);
7267

7368
Ok(())
7469
});

runtime/Cargo.toml

Lines changed: 21 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -8,40 +8,41 @@ edition = "2021"
88
repository = "https://github.com/filecoin-project/builtin-actors"
99

1010
[dependencies]
11-
fvm_ipld_hamt = { workspace = true }
12-
fvm_ipld_amt = { workspace = true }
13-
fvm_shared = { workspace = true }
14-
num = { workspace = true }
15-
num-traits = { workspace = true }
16-
num-derive = { workspace = true }
17-
serde = { workspace = true }
18-
lazy_static = { workspace = true, optional = true }
19-
unsigned-varint = { workspace = true }
11+
anyhow = { workspace = true }
2012
byteorder = { workspace = true }
13+
castaway = { workspace = true }
2114
cid = { workspace = true }
22-
log = { workspace = true }
23-
thiserror = { workspace = true }
24-
anyhow = { workspace = true }
25-
fvm_sdk = { workspace = true, optional = true }
15+
fvm_ipld_amt = { workspace = true }
16+
fvm_ipld_bitfield = { workspace = true }
2617
fvm_ipld_blockstore = { workspace = true }
2718
fvm_ipld_encoding = { workspace = true }
28-
fvm_ipld_bitfield = { workspace = true }
29-
multihash = { workspace = true }
30-
serde_repr = { workspace = true }
31-
regex = { workspace = true }
19+
fvm_ipld_hamt = { workspace = true }
20+
fvm_sdk = { workspace = true, optional = true }
21+
fvm_shared = { workspace = true }
22+
integer-encoding = { workspace = true }
3223
itertools = { workspace = true }
24+
lazy_static = { workspace = true, optional = true }
25+
log = { workspace = true }
26+
multihash = { workspace = true }
27+
num = { workspace = true }
28+
num-derive = { workspace = true }
29+
num-traits = { workspace = true }
3330
paste = { workspace = true }
34-
castaway = { workspace = true }
31+
regex = { workspace = true }
32+
serde = { workspace = true }
33+
serde_repr = { workspace = true }
34+
thiserror = { workspace = true }
35+
unsigned-varint = { workspace = true }
3536

3637
# A fake-proofs dependency but... we can't select on that feature here because we enable it from
3738
# build.rs.
3839
sha2 = { workspace = true }
3940

4041
# test_util
41-
rand = { workspace = true, optional = true }
42-
hex = { workspace = true, optional = true }
4342
blake2b_simd = { workspace = true, optional = true }
43+
hex = { workspace = true, optional = true }
4444
pretty_env_logger = { workspace = true, optional = true }
45+
rand = { workspace = true, optional = true }
4546

4647
[dependencies.libsecp256k1]
4748
workspace = true

runtime/src/lib.rs

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

4-
use builtin::HAMT_BIT_WIDTH;
54
use cid::Cid;
65
use fvm_ipld_amt::Amt;
76
use fvm_ipld_blockstore::Blockstore;
7+
#[cfg(not(feature = "fil-actor"))]
8+
use fvm_ipld_hamt::Sha256;
89
use fvm_ipld_hamt::{BytesKey, Error as HamtError, Hamt};
9-
use fvm_shared::address::Address;
1010
use fvm_shared::bigint::BigInt;
1111
pub use fvm_shared::BLOCKS_PER_EPOCH as EXPECTED_LEADERS_PER_EPOCH;
1212
use serde::de::DeserializeOwned;
1313
use serde::Serialize;
1414
use unsigned_varint::decode::Error as UVarintError;
15-
pub use {fvm_ipld_amt, fvm_ipld_hamt};
1615

17-
pub use self::actor_error::*;
18-
pub use self::builtin::*;
19-
pub use self::util::*;
20-
use crate::runtime::Runtime;
16+
use builtin::HAMT_BIT_WIDTH;
17+
pub use dispatch::{dispatch, dispatch_default};
18+
pub use {fvm_ipld_amt, fvm_ipld_hamt};
2119

2220
#[cfg(feature = "fil-actor")]
2321
use crate::runtime::hash_algorithm::FvmHashSha256;
22+
use crate::runtime::Runtime;
2423

25-
#[cfg(not(feature = "fil-actor"))]
26-
use fvm_ipld_hamt::Sha256;
24+
pub use self::actor_error::*;
25+
pub use self::builtin::*;
26+
pub use self::util::*;
2727

2828
pub mod actor_error;
2929
pub mod builtin;
3030
pub mod runtime;
3131
pub mod util;
3232

3333
mod dispatch;
34-
pub use dispatch::{dispatch, dispatch_default};
3534
#[cfg(feature = "test_utils")]
3635
pub mod test_utils;
3736

@@ -112,12 +111,6 @@ pub trait Keyer {
112111
fn key(&self) -> BytesKey;
113112
}
114113

115-
impl Keyer for Address {
116-
fn key(&self) -> BytesKey {
117-
self.to_bytes().into()
118-
}
119-
}
120-
121114
impl Keyer for u64 {
122115
fn key(&self) -> BytesKey {
123116
u64_key(*self)

0 commit comments

Comments
 (0)