iop_coeus_node/operations/
register.rs

1use super::*;
2
3impl AuthorizedCommand for DoRegister {
4    fn validate_auth(&self, state: &State, pk: &MPublicKey) -> Result<()> {
5        self.owner.validate_impersonation(pk)
6    }
7}
8
9fn validate_inside_state(
10    state: &State, name: &DomainName, domain_before_op_opt: &Option<Domain>,
11) -> Result<()> {
12    if let Some(domain_before_op) = domain_before_op_opt {
13        let last_block = state.last_seen_height();
14        ensure!(domain_before_op.is_expired_at(last_block), "Valid domain {} exists", name);
15        ensure!(
16            domain_before_op.is_grace_period_over(last_block),
17            "Expired domain {} in grace period exists",
18            name
19        );
20    }
21
22    state.validate_subtree_policies(name)
23}
24
25impl Command for DoRegister {
26    fn execute(self, state: &mut State) -> Result<UndoOperation> {
27        let parent_name = self.name.parent().with_context(|| "Cannot register root domain")?;
28        let parent_domain = state.domain_mut(&parent_name)?;
29        parent_domain.registration_policy().validate(parent_domain, &self)?;
30
31        // NOTE child domain must be inserted into state so that
32        //      it can be reached by domain::child(edge) -> domain queries during schema validation
33        let child_domain = Domain::new(
34            self.name.to_owned(),
35            self.owner,
36            self.subtree_policies,
37            self.registration_policy,
38            self.data,
39            self.expires_at_height,
40        );
41        let old_domain = parent_domain.insert_or_replace_child(child_domain)?;
42        let undo_operation = UndoRegister { name: self.name.to_owned(), old_domain };
43
44        match validate_inside_state(state, &self.name, &undo_operation.old_domain) {
45            Ok(()) => Ok(UndoOperation::Register(Box::new(undo_operation))),
46            Err(e) => {
47                undo_operation.execute(state)?;
48                Err(e)
49            }
50        }
51    }
52}
53
54#[derive(Debug, Clone, Serialize, Deserialize, Eq, PartialEq)]
55#[serde(rename_all = "camelCase")]
56pub struct UndoRegister {
57    #[serde(with = "serde_str")]
58    name: DomainName,
59    old_domain: Option<Domain>,
60}
61
62impl UndoCommand for UndoRegister {
63    fn execute(self, state: &mut State) -> Result<()> {
64        let parent_name =
65            self.name.parent().with_context(|| "Cannot undo registering root domain")?;
66        let parent_domain = state.domain_mut(&parent_name)?;
67        match self.old_domain {
68            Some(old) => {
69                parent_domain.insert_or_replace_child(old)?;
70            }
71            None => {
72                parent_domain.remove_child(self.name.last_edge().unwrap())?;
73            }
74        };
75
76        Ok(())
77    }
78}