Skip to content

Commit 023dd20

Browse files
authored
feat: basic f4 support (#684)
- Adds a create4 method to the init actor. - Adds embryo actor creation to the test vm.
1 parent 047560d commit 023dd20

File tree

27 files changed

+457
-83
lines changed

27 files changed

+457
-83
lines changed

Cargo.lock

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

actors/account/Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ crate-type = ["cdylib", "lib"]
1414

1515
[dependencies]
1616
fil_actors_runtime = { version = "10.0.0-alpha.1", path = "../../runtime", features = ["fil-actor"] }
17-
fvm_shared = { version = "3.0.0-alpha.1", default-features = false }
17+
fvm_shared = { version = "3.0.0-alpha.2", default-features = false }
1818
serde = { version = "1.0.136", features = ["derive"] }
1919
num-traits = "0.2.14"
2020
num-derive = "0.3.3"

actors/cron/Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ crate-type = ["cdylib", "lib"]
1515

1616
[dependencies]
1717
fil_actors_runtime = { version = "10.0.0-alpha.1", path = "../../runtime", features = ["fil-actor"] }
18-
fvm_shared = { version = "3.0.0-alpha.1", default-features = false }
18+
fvm_shared = { version = "3.0.0-alpha.2", default-features = false }
1919
num-traits = "0.2.14"
2020
num-derive = "0.3.3"
2121
log = "0.4.14"

actors/embryo/Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ crate-type = ["cdylib", "lib"]
1414

1515
[dependencies]
1616
fvm_sdk = { version = "3.0.0-alpha.2", optional = true }
17-
fvm_shared = { version = "3.0.0-alpha.1", optional = true }
17+
fvm_shared = { version = "3.0.0-alpha.2", optional = true }
1818

1919
[features]
2020
fil-actor = ["fvm_sdk", "fvm_shared"]

actors/evm/Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ crate-type = ["cdylib", "lib"]
1515

1616
[dependencies]
1717
fil_actors_runtime = { version = "10.0.0-alpha.1", path = "../../runtime" }
18-
fvm_shared = { version = "3.0.0-alpha.1", default-features = false }
18+
fvm_shared = { version = "3.0.0-alpha.2", default-features = false }
1919
fvm_ipld_hamt = "0.5.1"
2020
serde = { version = "1.0.136", features = ["derive"] }
2121
serde_tuple = "0.5"

actors/init/Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ crate-type = ["cdylib", "lib"]
1515

1616
[dependencies]
1717
fil_actors_runtime = { version = "10.0.0-alpha.1", path = "../../runtime" }
18-
fvm_shared = { version = "3.0.0-alpha.1", default-features = false }
18+
fvm_shared = { version = "3.0.0-alpha.2", default-features = false }
1919
fvm_ipld_hamt = "0.5.1"
2020
serde = { version = "1.0.136", features = ["derive"] }
2121
num-traits = "0.2.14"

actors/init/src/lib.rs

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

4+
use std::iter;
5+
46
use cid::Cid;
57
use fil_actors_runtime::runtime::{ActorCode, Runtime};
8+
use fil_actors_runtime::EAM_ACTOR_ADDR;
69
use fil_actors_runtime::{actor_error, cbor, ActorDowncast, ActorError, SYSTEM_ACTOR_ADDR};
710
use fvm_ipld_blockstore::Blockstore;
811
use fvm_ipld_encoding::RawBytes;
@@ -28,8 +31,9 @@ fil_actors_runtime::wasm_trampoline!(Actor);
2831
pub enum Method {
2932
Constructor = METHOD_CONSTRUCTOR,
3033
Exec = 2,
34+
Exec4 = 3,
3135
#[cfg(feature = "m2-native")]
32-
InstallCode = 3,
36+
InstallCode = 4,
3337
}
3438

3539
/// Init actor
@@ -85,7 +89,7 @@ impl Actor {
8589
log::trace!("robust address: {:?}", &robust_address);
8690

8791
// Allocate an ID for this actor.
88-
// Store mapping of pubkey or actor address to actor ID
92+
// Store mapping of actor addresses to the actor ID.
8993
let id_address: ActorID = rt.transaction(|s: &mut State, rt| {
9094
s.map_address_to_new_id(rt.store(), &robust_address).map_err(|e| {
9195
e.downcast_default(ExitCode::USR_ILLEGAL_STATE, "failed to allocate ID address")
@@ -107,6 +111,58 @@ impl Actor {
107111
Ok(ExecReturn { id_address: Address::new_id(id_address), robust_address })
108112
}
109113

114+
/// Exec init actor
115+
pub fn exec4<BS, RT>(rt: &mut RT, params: Exec4Params) -> Result<Exec4Return, ActorError>
116+
where
117+
BS: Blockstore,
118+
RT: Runtime<BS>,
119+
{
120+
if cfg!(feature = "m2-native") {
121+
rt.validate_immediate_caller_accept_any()?;
122+
} else {
123+
rt.validate_immediate_caller_is(iter::once(&EAM_ACTOR_ADDR))?;
124+
}
125+
126+
// Compute the f4 address.
127+
let caller_id = rt.message().caller().id().unwrap();
128+
let delegated_address =
129+
Address::new_delegated(caller_id, &params.subaddress).map_err(|e| {
130+
ActorError::illegal_argument(format!("invalid delegated address: {}", e))
131+
})?;
132+
133+
log::trace!("delegated address: {:?}", &delegated_address);
134+
135+
// Compute a re-org-stable address.
136+
// This address exists for use by messages coming from outside the system, in order to
137+
// stably address the newly created actor even if a chain re-org causes it to end up with
138+
// a different ID.
139+
let robust_address = rt.new_actor_address()?;
140+
141+
log::trace!("robust address: {:?}", &robust_address);
142+
143+
// Allocate an ID for this actor.
144+
// Store mapping of actor addresses to the actor ID.
145+
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+
})
149+
})?;
150+
151+
// Create an empty actor
152+
rt.create_actor(params.code_cid, id_address)?;
153+
154+
// Invoke constructor
155+
rt.send(
156+
&Address::new_id(id_address),
157+
METHOD_CONSTRUCTOR,
158+
params.constructor_params,
159+
rt.message().value_received(),
160+
)
161+
.map_err(|err| err.wrap("constructor failed"))?;
162+
163+
Ok(Exec4Return { id_address: Address::new_id(id_address), robust_address })
164+
}
165+
110166
#[cfg(feature = "m2-native")]
111167
pub fn install<BS, RT>(rt: &mut RT, params: InstallParams) -> Result<InstallReturn, ActorError>
112168
where
@@ -176,6 +232,10 @@ impl ActorCode for Actor {
176232
let res = Self::exec(rt, cbor::deserialize_params(params)?)?;
177233
Ok(RawBytes::serialize(res)?)
178234
}
235+
Some(Method::Exec4) => {
236+
let res = Self::exec4(rt, cbor::deserialize_params(params)?)?;
237+
Ok(RawBytes::serialize(res)?)
238+
}
179239
#[cfg(feature = "m2-native")]
180240
Some(Method::InstallCode) => {
181241
let res = Self::install(rt, cbor::deserialize_params(params)?)?;

actors/init/src/state.rs

Lines changed: 46 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,9 @@ use anyhow::anyhow;
55
#[cfg(feature = "m2-native")]
66
use cid::multihash::Code;
77
use cid::Cid;
8+
use fil_actors_runtime::actor_error;
89
use fil_actors_runtime::{
9-
actor_error, make_empty_map, make_map_with_root_and_bitwidth, FIRST_NON_SINGLETON_ADDR,
10+
make_empty_map, make_map_with_root_and_bitwidth, FIRST_NON_SINGLETON_ADDR,
1011
};
1112
use fvm_ipld_blockstore::Blockstore;
1213
use fvm_ipld_encoding::tuple::*;
@@ -45,7 +46,8 @@ impl State {
4546
/// Allocates a new ID address and stores a mapping of the argument address to it.
4647
/// Fails if the argument address is already present in the map to facilitate a tombstone
4748
/// for when the predictable robust address generation is implemented.
48-
/// Returns the newly-allocated address.
49+
///
50+
/// Returns the newly-allocated actor ID.
4951
pub fn map_address_to_new_id<BS: Blockstore>(
5052
&mut self,
5153
store: &BS,
@@ -70,6 +72,48 @@ impl State {
7072
Ok(id)
7173
}
7274

75+
/// Allocates a new ID address and stores a mapping of the argument addresses to it.
76+
/// Returns the newly-allocated actor ID.
77+
pub fn map_address_to_f4<BS: Blockstore>(
78+
&mut self,
79+
store: &BS,
80+
addr: &Address,
81+
f4addr: &Address,
82+
) -> anyhow::Result<ActorID>
83+
where
84+
BS: Blockstore,
85+
{
86+
let mut map = make_map_with_root_and_bitwidth(&self.address_map, store, HAMT_BIT_WIDTH)?;
87+
88+
// Assign a new ID address, or use the one currently mapped to the f4 address. We don't
89+
// bother checking if the target actor is an embryo here, the FVM will check that when we go to create the actor.
90+
let f4addr_key = f4addr.to_bytes().into();
91+
let id: u64 = match map.get(&f4addr_key)? {
92+
Some(id) => *id,
93+
None => {
94+
let id = self.next_id;
95+
self.next_id += 1;
96+
map.set(f4addr_key, id)?;
97+
id
98+
}
99+
};
100+
101+
// Then go ahead and assign the f2 address.
102+
let is_new = map.set_if_absent(addr.to_bytes().into(), id)?;
103+
if !is_new {
104+
// this is impossible today as the robust address is a hash of unique inputs
105+
// but in close future predictable address generation will make this possible
106+
return Err(anyhow!(actor_error!(
107+
forbidden,
108+
"robust address {} is already allocated in the address map",
109+
addr
110+
)));
111+
}
112+
self.address_map = map.flush()?;
113+
114+
Ok(id)
115+
}
116+
73117
/// ResolveAddress resolves an address to an ID-address, if possible.
74118
/// If the provided address is an ID address, it is returned as-is.
75119
/// This means that mapped ID-addresses (which should only appear as values, not keys) and

0 commit comments

Comments
 (0)