defuse_core/engine/
mod.rs

1mod inspector;
2mod state;
3
4pub use self::{inspector::*, state::*};
5
6use defuse_crypto::{Payload, SignedPayload};
7
8use crate::{
9    DefuseError, Result,
10    intents::{DefuseIntents, ExecutableIntent},
11    payload::{DefusePayload, ExtractDefusePayload, multi::MultiPayload},
12};
13
14use self::deltas::{Deltas, Transfers};
15
16pub struct Engine<S, I> {
17    pub state: Deltas<S>,
18    pub inspector: I,
19}
20
21impl<S, I> Engine<S, I>
22where
23    S: State,
24    I: Inspector,
25{
26    #[inline]
27    pub fn new(state: S, inspector: I) -> Self {
28        Self {
29            state: Deltas::new(state),
30            inspector,
31        }
32    }
33
34    pub fn execute_signed_intents(
35        mut self,
36        signed: impl IntoIterator<Item = MultiPayload>,
37    ) -> Result<Transfers> {
38        for signed in signed {
39            self.execute_signed_intent(signed)?;
40        }
41        self.finalize()
42    }
43
44    fn execute_signed_intent(&mut self, signed: MultiPayload) -> Result<()> {
45        // verify signed payload and get public key
46        let public_key = signed.verify().ok_or(DefuseError::InvalidSignature)?;
47
48        // calculate intent hash
49        let hash = signed.hash();
50
51        // extract NEP-413 payload
52        let DefusePayload::<DefuseIntents> {
53            signer_id,
54            verifying_contract,
55            deadline,
56            nonce,
57            message: intents,
58        } = signed.extract_defuse_payload()?;
59
60        // check recipient
61        if verifying_contract != *self.state.verifying_contract() {
62            return Err(DefuseError::WrongVerifyingContract);
63        }
64
65        self.inspector.on_deadline(deadline);
66        // make sure message is still valid
67        if deadline.has_expired() {
68            return Err(DefuseError::DeadlineExpired);
69        }
70
71        // make sure the account has this public key
72        if !self.state.has_public_key(&signer_id, &public_key) {
73            return Err(DefuseError::PublicKeyNotExist(signer_id, public_key));
74        }
75
76        // commit nonce
77        self.state.commit_nonce(signer_id.clone(), nonce)?;
78
79        intents.execute_intent(&signer_id, self, hash)?;
80        self.inspector.on_intent_executed(&signer_id, hash);
81
82        Ok(())
83    }
84
85    #[inline]
86    fn finalize(self) -> Result<Transfers> {
87        self.state
88            .finalize()
89            .map_err(DefuseError::InvariantViolated)
90    }
91}