Skip to content

Commit e3d1b21

Browse files
committed
stub object store actor
Signed-off-by: Sander Pick <sanderpick@gmail.com>
1 parent f6fc53d commit e3d1b21

6 files changed

Lines changed: 219 additions & 0 deletions

File tree

Cargo.lock

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

Cargo.toml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ members = [
2828
"fendermint/vm/*",
2929
"fendermint/actors",
3030
"fendermint/actors/chainmetadata",
31+
"fendermint/actors/objectstore",
3132
]
3233

3334
[workspace.package]
@@ -169,6 +170,7 @@ fvm_ipld_car = "0.7.1"
169170
fvm_ipld_encoding = "0.4.0"
170171
fvm_ipld_hamt = "0.9.0"
171172
fvm_ipld_amt = "0.6.2"
173+
fvm_ipld_kamt = "0.3.0"
172174

173175
# Local FVM debugging
174176
# fvm = { path = "../ref-fvm/fvm", default-features = false }
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
[package]
2+
name = "fendermint_actor_objectstore"
3+
description = "Actor for object storage"
4+
license.workspace = true
5+
edition.workspace = true
6+
authors.workspace = true
7+
version = "0.1.0"
8+
9+
[lib]
10+
crate-type = ["cdylib", "lib"]
11+
12+
[dependencies]
13+
cid = { workspace = true, default-features = false }
14+
fil_actors_runtime = { workspace = true, optional = true, features = [
15+
"fil-actor",
16+
] }
17+
fvm_shared = { workspace = true }
18+
fvm_ipld_encoding = { workspace = true }
19+
fvm_ipld_blockstore = { workspace = true }
20+
fvm_ipld_kamt = { workspace = true }
21+
num-derive = { workspace = true }
22+
serde = { workspace = true, features = ["derive"] }
23+
serde_tuple = { workspace = true }
24+
num-traits = { workspace = true }
25+
frc42_dispatch = { workspace = true }
26+
anyhow = { workspace = true }
27+
28+
[features]
29+
default = []
30+
fil-actor = ["fil_actors_runtime"]
Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,87 @@
1+
// Copyright 2021-2023 Protocol Labs
2+
// SPDX-License-Identifier: Apache-2.0, MIT
3+
4+
use fil_actors_runtime::actor_dispatch;
5+
use fil_actors_runtime::actor_error;
6+
use fil_actors_runtime::builtin::singletons::SYSTEM_ACTOR_ADDR;
7+
use fil_actors_runtime::runtime::{ActorCode, Runtime};
8+
use fil_actors_runtime::ActorDowncast;
9+
use fil_actors_runtime::ActorError;
10+
use fvm_shared::error::ExitCode;
11+
12+
use crate::{ConstructorParams, Method, State, OBJECTSTORE_ACTOR_NAME};
13+
14+
fil_actors_runtime::wasm_trampoline!(Actor);
15+
16+
pub struct Actor;
17+
18+
impl Actor {
19+
fn constructor(rt: &impl Runtime, params: ConstructorParams) -> Result<(), ActorError> {
20+
// Note(sander): We're setting this up to be a subnet-wide actor for a single repo.
21+
// Note(sander): In the future, this could be deployed dynamically for multi repo subnets.
22+
rt.validate_immediate_caller_is(std::iter::once(&SYSTEM_ACTOR_ADDR))?;
23+
24+
let state = State::new(rt.store()).map_err(|e| {
25+
e.downcast_default(ExitCode::USR_ILLEGAL_STATE, "failed to create empty KAMT")
26+
})?;
27+
28+
rt.create(&state)?;
29+
30+
Ok(())
31+
}
32+
33+
// Note(sander): Probably obvious, but example actor method that mutates state
34+
// fn push_block_hash(rt: &impl Runtime, params: PushBlockParams) -> Result<(), ActorError> {
35+
// rt.validate_immediate_caller_is(std::iter::once(&SYSTEM_ACTOR_ADDR))?;
36+
//
37+
// rt.transaction(|st: &mut State, rt| {
38+
// // load the blockhashes AMT
39+
// let mut blockhashes = Array::load(&st.blockhashes, rt.store()).map_err(|e| {
40+
// e.downcast_default(
41+
// ExitCode::USR_ILLEGAL_STATE,
42+
// "failed to load blockhashes states",
43+
// )
44+
// })?;
45+
//
46+
// // push the block to the AMT
47+
// blockhashes.set(params.epoch as u64, params.block).unwrap();
48+
//
49+
// // remove the oldest block if the AMT is full (note that this assume the
50+
// // for_each_while iterates in order, which it seems to do)
51+
// if blockhashes.count() > st.lookback_len {
52+
// let mut first_idx = 0;
53+
// blockhashes
54+
// .for_each_while(|i, _: &BlockHash| {
55+
// first_idx = i;
56+
// Ok(false)
57+
// })
58+
// .unwrap();
59+
// blockhashes.delete(first_idx).unwrap();
60+
// }
61+
//
62+
// // save the new blockhashes AMT cid root
63+
// st.blockhashes = blockhashes.flush().map_err(|e| {
64+
// e.downcast_default(ExitCode::USR_ILLEGAL_STATE, "failed to save blockhashes")
65+
// })?;
66+
//
67+
// Ok(())
68+
// })?;
69+
//
70+
// Ok(())
71+
// }
72+
}
73+
74+
impl ActorCode for Actor {
75+
type Methods = Method;
76+
77+
fn name() -> &'static str {
78+
OBJECTSTORE_ACTOR_NAME
79+
}
80+
81+
actor_dispatch! {
82+
Constructor => constructor,
83+
// PushBlockHash => push_block_hash,
84+
// LookbackLen => lookback_len,
85+
// GetBlockHash => get_block_hash,
86+
}
87+
}
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
// Copyright 2021-2023 Protocol Labs
2+
// SPDX-License-Identifier: Apache-2.0, MIT
3+
#[cfg(feature = "fil-actor")]
4+
mod actor;
5+
mod shared;
6+
7+
pub use shared::*;
Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
// Copyright 2021-2023 Protocol Labs
2+
// SPDX-License-Identifier: Apache-2.0, MIT
3+
4+
use cid::Cid;
5+
use fvm_ipld_blockstore::Blockstore;
6+
use fvm_ipld_encoding::tuple::{Deserialize_tuple, Serialize_tuple};
7+
use fvm_ipld_kamt::{id::Identity, Kamt};
8+
use fvm_shared::METHOD_CONSTRUCTOR;
9+
use num_derive::FromPrimitive;
10+
11+
// The state stores the blockhashes of the last `lookback_len` epochs
12+
#[derive(Serialize_tuple, Deserialize_tuple)]
13+
pub struct State {
14+
// the KAMT root cid of keys
15+
pub keys: Cid,
16+
}
17+
18+
impl State {
19+
pub fn new<BS: Blockstore>(store: &BS) -> anyhow::Result<Self> {
20+
// Note(sander): I don't know if these generics are correct... maybe K should be Cid?
21+
let empty_keys_cid = match Kamt::<_, String, Vec<u8>, Identity, 32>::new(store).flush() {
22+
Ok(cid) => cid,
23+
Err(e) => {
24+
return Err(anyhow::anyhow!(
25+
"objectstore actor failed to create empty Kamt: {}",
26+
e
27+
))
28+
}
29+
};
30+
31+
Ok(Self {
32+
keys: empty_keys_cid,
33+
})
34+
}
35+
}
36+
37+
pub const OBJECTSTORE_ACTOR_NAME: &str = "objectstore";
38+
39+
#[derive(Default, Debug, Serialize_tuple, Deserialize_tuple)]
40+
pub struct ConstructorParams {
41+
pub foo: u64,
42+
}
43+
44+
// Note(sander): Example of method params
45+
// #[derive(Default, Debug, Serialize_tuple, Deserialize_tuple)]
46+
// pub struct PushBlockParams {
47+
//
48+
// }
49+
50+
#[derive(FromPrimitive)]
51+
#[repr(u64)]
52+
pub enum Method {
53+
Constructor = METHOD_CONSTRUCTOR,
54+
// PushBlockHash = frc42_dispatch::method_hash!("PushBlockHash"),
55+
// LookbackLen = frc42_dispatch::method_hash!("LookbackLen"),
56+
// GetBlockHash = frc42_dispatch::method_hash!("GetBlockHash"),
57+
}

0 commit comments

Comments
 (0)