actors_runtime/util/chaos/
mod.rs1use cid::Cid;
5use fvm_shared::actor::builtin::Type;
6use fvm_shared::address::Address;
7use fvm_shared::blockstore::Blockstore;
8use fvm_shared::encoding::RawBytes;
9use fvm_shared::error::ExitCode;
10use fvm_shared::{MethodNum, METHOD_CONSTRUCTOR};
11use num_derive::FromPrimitive;
12use num_traits::FromPrimitive;
13pub use state::*;
14pub use types::*;
15
16use crate::runtime::{ActorCode, Runtime};
17use crate::{actor_error, ActorError};
18
19mod state;
20mod types;
21
22const CALLER_VALIDATION_BRANCH_NONE: i64 = 0;
26const CALLER_VALIDATION_BRANCH_TWICE: i64 = 1;
27const CALLER_VALIDATION_BRANCH_IS_ADDRESS: i64 = 2;
28const CALLER_VALIDATION_BRANCH_IS_TYPE: i64 = 3;
29
30const MUTATE_IN_TRANSACTION: i64 = 0;
32
33#[derive(FromPrimitive)]
35#[repr(u64)]
36pub enum Method {
37 Constructor = METHOD_CONSTRUCTOR,
38 CallerValidation = 2,
39 CreateActor = 3,
40 ResolveAddress = 4,
41 DeleteActor = 5,
42 Send = 6,
43 MutateState = 7,
44 AbortWith = 8,
45 InspectRuntime = 9,
46}
47
48pub struct Actor;
50
51impl Actor {
52 pub fn send<BS, RT>(rt: &mut RT, arg: SendArgs) -> Result<SendReturn, ActorError>
53 where
54 BS: Blockstore,
55 RT: Runtime<BS>,
56 {
57 rt.validate_immediate_caller_accept_any()?;
58
59 let result = rt.send(arg.to, arg.method, arg.params, arg.value);
60 if let Err(e) = result {
61 Ok(SendReturn {
62 return_value: RawBytes::default(),
63 code: e.exit_code(),
64 })
65 } else {
66 Ok(SendReturn {
67 return_value: result.unwrap(),
68 code: ExitCode::Ok,
69 })
70 }
71 }
72
73 pub fn constructor<BS, RT>(_rt: &mut RT)
75 where
76 BS: Blockstore,
77 RT: Runtime<BS>,
78 {
79 panic!("Constructor should not be called");
80 }
81
82 pub fn caller_validation<BS, RT>(
90 rt: &mut RT,
91 args: CallerValidationArgs,
92 ) -> Result<(), ActorError>
93 where
94 BS: Blockstore,
95 RT: Runtime<BS>,
96 {
97 match args.branch {
98 x if x == CALLER_VALIDATION_BRANCH_NONE => {}
99 x if x == CALLER_VALIDATION_BRANCH_TWICE => {
100 rt.validate_immediate_caller_accept_any()?;
101 rt.validate_immediate_caller_accept_any()?;
102 }
103 x if x == CALLER_VALIDATION_BRANCH_IS_ADDRESS => {
104 rt.validate_immediate_caller_is(&args.addrs)?;
105 }
106 x if x == CALLER_VALIDATION_BRANCH_IS_TYPE => {
107 let types: Vec<Type> = args
108 .types
109 .iter()
110 .map(|typ| rt.resolve_builtin_actor_type(typ).unwrap())
111 .collect();
112 rt.validate_immediate_caller_type(&types)?;
113 }
114 _ => panic!("invalid branch passed to CallerValidation"),
115 }
116 Ok(())
117 }
118
119 pub fn create_actor<BS, RT>(rt: &mut RT, arg: CreateActorArgs) -> Result<(), ActorError>
121 where
122 BS: Blockstore,
123 RT: Runtime<BS>,
124 {
125 rt.validate_immediate_caller_accept_any()?;
126 let actor_cid = if arg.undef_cid {
128 Cid::default()
129 } else {
130 arg.cid
131 };
132
133 let actor_address = arg.actor_id;
134
135 rt.create_actor(actor_cid, actor_address)
136 }
137
138 pub fn resolve_address<BS, RT>(
140 rt: &mut RT,
141 args: Address,
142 ) -> Result<ResolveAddressResponse, ActorError>
143 where
144 BS: Blockstore,
145 RT: Runtime<BS>,
146 {
147 rt.validate_immediate_caller_accept_any()?;
148 let resolved = rt.resolve_address(&args);
149 Ok(ResolveAddressResponse {
150 address: resolved.unwrap_or_else(|| Address::new_id(0)),
151 success: resolved.is_some(),
152 })
153 }
154
155 pub fn delete_actor<BS, RT>(rt: &mut RT, beneficiary: Address) -> Result<(), ActorError>
156 where
157 BS: Blockstore,
158 RT: Runtime<BS>,
159 {
160 rt.validate_immediate_caller_accept_any()?;
161 rt.delete_actor(&beneficiary)
162 }
163
164 pub fn mutate_state<BS, RT>(rt: &mut RT, arg: MutateStateArgs) -> Result<(), ActorError>
165 where
166 BS: Blockstore,
167 RT: Runtime<BS>,
168 {
169 rt.validate_immediate_caller_accept_any()?;
170
171 match arg.branch {
172 x if x == MUTATE_IN_TRANSACTION => rt.transaction(|s: &mut State, _| {
173 s.value = arg.value;
174 Ok(())
175 }),
176
177 _ => Err(actor_error!(ErrIllegalArgument; "Invalid mutate state command given" )),
178 }
179 }
180
181 pub fn abort_with(arg: AbortWithArgs) -> Result<(), ActorError> {
182 if arg.uncontrolled {
183 panic!("Uncontrolled abort/error");
184 }
185 Err(ActorError::new(arg.code, arg.message))
186 }
187
188 pub fn inspect_runtime<BS, RT>(rt: &mut RT) -> Result<InspectRuntimeReturn, ActorError>
189 where
190 BS: Blockstore,
191 RT: Runtime<BS>,
192 {
193 rt.validate_immediate_caller_accept_any()?;
194 Ok(InspectRuntimeReturn {
195 caller: rt.message().caller(),
196 receiver: rt.message().receiver(),
197 value_received: rt.message().value_received(),
198 curr_epoch: rt.curr_epoch(),
199 current_balance: rt.current_balance(),
200 state: rt.state()?,
201 })
202 }
203}
204
205impl ActorCode for Actor {
206 fn invoke_method<BS, RT>(
207 rt: &mut RT,
208 method: MethodNum,
209 params: &RawBytes,
210 ) -> Result<RawBytes, ActorError>
211 where
212 BS: Blockstore,
213 RT: Runtime<BS>,
214 {
215 match FromPrimitive::from_u64(method) {
216 Some(Method::Constructor) => {
217 Self::constructor(rt);
218 Ok(RawBytes::default())
219 }
220 Some(Method::CallerValidation) => {
221 Self::caller_validation(rt, rt.deserialize_params(params)?)?;
222 Ok(RawBytes::default())
223 }
224
225 Some(Method::CreateActor) => {
226 Self::create_actor(rt, rt.deserialize_params(params)?)?;
227 Ok(RawBytes::default())
228 }
229 Some(Method::ResolveAddress) => {
230 let res = Self::resolve_address(rt, rt.deserialize_params(params)?)?;
231 Ok(RawBytes::serialize(res)?)
232 }
233
234 Some(Method::Send) => {
235 let res: SendReturn = Self::send(rt, rt.deserialize_params(params)?)?;
236 Ok(RawBytes::serialize(res)?)
237 }
238
239 Some(Method::DeleteActor) => {
240 Self::delete_actor(rt, rt.deserialize_params(params)?)?;
241 Ok(RawBytes::default())
242 }
243
244 Some(Method::MutateState) => {
245 Self::mutate_state(rt, rt.deserialize_params(params)?)?;
246 Ok(RawBytes::default())
247 }
248
249 Some(Method::AbortWith) => {
250 Self::abort_with(rt.deserialize_params(params)?)?;
251 Ok(RawBytes::default())
252 }
253
254 Some(Method::InspectRuntime) => {
255 let inspect = Self::inspect_runtime(rt)?;
256 Ok(RawBytes::serialize(inspect)?)
257 }
258
259 None => Err(actor_error!(SysErrInvalidMethod; "Invalid method")),
260 }
261 }
262}