fil_actor_cron/
lib.rs

1// Copyright 2019-2022 ChainSafe Systems
2// SPDX-License-Identifier: Apache-2.0, MIT
3
4use fil_actors_runtime::runtime::{ActorCode, Runtime};
5use fil_actors_runtime::{actor_error, cbor, ActorError, SYSTEM_ACTOR_ADDR};
6use fvm_ipld_blockstore::Blockstore;
7use fvm_ipld_encoding::tuple::*;
8use fvm_ipld_encoding::RawBytes;
9use fvm_shared::econ::TokenAmount;
10
11use fvm_shared::{MethodNum, METHOD_CONSTRUCTOR};
12use num_derive::FromPrimitive;
13use num_traits::{FromPrimitive, Zero};
14
15pub use self::state::{Entry, State};
16
17mod state;
18pub mod testing;
19
20#[cfg(feature = "fil-actor")]
21fil_actors_runtime::wasm_trampoline!(Actor);
22
23// * Updated to specs-actors commit: 845089a6d2580e46055c24415a6c32ee688e5186 (v3.0.0)
24
25/// Cron actor methods available
26#[derive(FromPrimitive)]
27#[repr(u64)]
28pub enum Method {
29    Constructor = METHOD_CONSTRUCTOR,
30    EpochTick = 2,
31}
32
33/// Constructor parameters for Cron actor, contains entries
34/// of actors and methods to call on each epoch
35#[derive(Default, Debug, Serialize_tuple, Deserialize_tuple)]
36pub struct ConstructorParams {
37    /// Entries is a set of actors (and corresponding methods) to call during EpochTick.
38    pub entries: Vec<Entry>,
39}
40
41/// Cron actor
42pub struct Actor;
43impl Actor {
44    /// Constructor for Cron actor
45    fn constructor<BS, RT>(rt: &mut RT, params: ConstructorParams) -> Result<(), ActorError>
46    where
47        BS: Blockstore,
48        RT: Runtime<BS>,
49    {
50        rt.validate_immediate_caller_is(std::iter::once(&SYSTEM_ACTOR_ADDR))?;
51        rt.create(&State { entries: params.entries })?;
52        Ok(())
53    }
54    /// Executes built-in periodic actions, run at every Epoch.
55    /// epoch_tick(r) is called after all other messages in the epoch have been applied.
56    /// This can be seen as an implicit last message.
57    fn epoch_tick<BS, RT>(rt: &mut RT) -> Result<(), ActorError>
58    where
59        BS: Blockstore,
60        RT: Runtime<BS>,
61    {
62        rt.validate_immediate_caller_is(std::iter::once(&SYSTEM_ACTOR_ADDR))?;
63
64        let st: State = rt.state()?;
65        for entry in st.entries {
66            // Intentionally ignore any error when calling cron methods
67            let res = rt.send(
68                &entry.receiver,
69                entry.method_num,
70                RawBytes::default(),
71                TokenAmount::zero(),
72            );
73            if let Err(e) = res {
74                log::error!(
75                    "cron failed to send entry to {}, send error code {}",
76                    entry.receiver,
77                    e
78                );
79            }
80        }
81        Ok(())
82    }
83}
84
85impl ActorCode for Actor {
86    fn invoke_method<BS, RT>(
87        rt: &mut RT,
88        method: MethodNum,
89        params: &RawBytes,
90    ) -> Result<RawBytes, ActorError>
91    where
92        BS: Blockstore,
93        RT: Runtime<BS>,
94    {
95        match FromPrimitive::from_u64(method) {
96            Some(Method::Constructor) => {
97                Self::constructor(rt, cbor::deserialize_params(params)?)?;
98                Ok(RawBytes::default())
99            }
100            Some(Method::EpochTick) => {
101                Self::epoch_tick(rt)?;
102                Ok(RawBytes::default())
103            }
104            None => Err(actor_error!(unhandled_message; "Invalid method")),
105        }
106    }
107}