iop_coeus_node/operations/
mod.rs1mod delete;
2mod register;
3mod renew;
4mod start_block;
5mod transfer;
6mod update;
7
8pub use delete::*;
9pub use register::*;
10pub use renew::*;
11pub use start_block::*;
12pub use transfer::*;
13pub use update::*;
14
15use super::*;
16
17pub trait Command {
18 fn execute(self, state: &mut State) -> Result<UndoOperation>;
19}
20
21pub(crate) trait AuthorizedCommand: Command {
22 fn validate_auth(&self, state: &State, pk: &MPublicKey) -> Result<()>;
23}
24
25pub trait UndoCommand {
27 fn execute(self, state: &mut State) -> Result<()>;
28}
29
30impl Command for UserOperation {
31 fn execute(self, state: &mut State) -> Result<UndoOperation> {
32 match self {
33 Self::Register(op) => op.execute(state),
34 Self::Update(op) => op.execute(state),
35 Self::Renew(op) => op.execute(state),
36 Self::Transfer(op) => op.execute(state),
37 Self::Delete(op) => op.execute(state),
38 }
39 }
40}
41
42impl AuthorizedCommand for UserOperation {
43 fn validate_auth(&self, state: &State, pk: &MPublicKey) -> Result<()> {
44 match self {
45 Self::Register(op) => op.validate_auth(state, pk),
46 Self::Update(op) => op.validate_auth(state, pk),
47 Self::Renew(op) => op.validate_auth(state, pk),
48 Self::Transfer(op) => op.validate_auth(state, pk),
49 Self::Delete(op) => op.validate_auth(state, pk),
50 }
51 }
52}
53
54#[derive(Debug, Clone, Serialize, Deserialize, Eq, PartialEq)]
55#[serde(tag = "type", rename_all = "camelCase")]
56pub enum SystemOperation {
57 StartBlock(DoStartBlock),
58}
59
60impl SystemOperation {
61 pub fn start_block(height: BlockHeight) -> Self {
62 SystemOperation::StartBlock(DoStartBlock { height })
63 }
64}
65
66impl Command for SystemOperation {
67 fn execute(self, state: &mut State) -> Result<UndoOperation> {
68 match self {
69 Self::StartBlock(op) => op.execute(state),
70 }
71 }
72}
73
74#[derive(Debug, Clone, Serialize, Deserialize, Eq, PartialEq)]
75#[serde(untagged)]
76#[allow(clippy::large_enum_variant)] pub enum Operation {
78 System(SystemOperation),
79 User(UserOperation),
80}
81
82impl Command for Operation {
83 fn execute(self, state: &mut State) -> Result<UndoOperation> {
84 match self {
85 Self::System(op) => op.execute(state),
86 Self::User(op) => op.execute(state),
87 }
88 }
89}
90
91impl From<SystemOperation> for Operation {
92 fn from(op: SystemOperation) -> Self {
93 Self::System(op)
94 }
95}
96
97impl From<UserOperation> for Operation {
98 fn from(op: UserOperation) -> Self {
99 Self::User(op)
100 }
101}
102
103#[derive(Debug, Clone, Serialize, Deserialize, Eq, PartialEq)]
104#[serde(tag = "type", rename_all = "camelCase")]
105pub enum UndoOperation {
106 StartBlock(UndoStartBlock),
107 Register(Box<UndoRegister>), Update(UndoUpdate),
109 Renew(UndoRenew),
110 Transfer(UndoTransfer),
111 Delete(Box<UndoDelete>), }
113
114impl UndoCommand for UndoOperation {
115 fn execute(self, state: &mut State) -> Result<()> {
116 match self {
117 Self::StartBlock(op) => op.execute(state),
118 Self::Register(op) => op.execute(state),
119 Self::Update(op) => op.execute(state),
120 Self::Renew(op) => op.execute(state),
121 Self::Transfer(op) => op.execute(state),
122 Self::Delete(op) => op.execute(state),
123 }
124 }
125}
126
127#[cfg(test)]
128mod test {
129 use super::*;
130
131 #[test]
132 fn serde() {
133 let input = r#"{"type":"register","name":".schema.company","owner":"pszp9HBQY4qrx2yPGqM6biZeLmudJanMK6LXzXzLZGciLYA","subtreePolicies":{},"registrationPolicy":"owner","data":{},"expiresAtHeight":1000}"#;
134 let op: UserOperation = serde_json::from_str(input).unwrap();
135
136 assert!(matches!(op, UserOperation::Register(_)));
137 if let UserOperation::Register(r) = &op {
138 assert_eq!(r.name.to_string(), ".schema.company");
139 }
140
141 let output = serde_json::to_string(&op).unwrap();
142
143 assert_eq!(output, input);
144 }
145}