revm_database_interface/
try_commit.rs

1use crate::DatabaseCommit;
2use core::{convert::Infallible, error::Error, fmt};
3use primitives::{Address, HashMap};
4use state::Account;
5use std::sync::Arc;
6
7/// EVM database commit interface that can fail.
8///
9/// This is intended for use with types that may fail to commit changes, e.g.
10/// because they are directly interacting with the filesystem, or must arrange
11/// access to a shared resource.
12pub trait TryDatabaseCommit {
13    /// Error type for when [`TryDatabaseCommit::try_commit`] fails.
14    type Error: Error;
15
16    /// Attempt to commit changes to the database.
17    fn try_commit(&mut self, changes: HashMap<Address, Account>) -> Result<(), Self::Error>;
18}
19
20impl<Db> TryDatabaseCommit for Db
21where
22    Db: DatabaseCommit,
23{
24    type Error = Infallible;
25
26    #[inline]
27    fn try_commit(&mut self, changes: HashMap<Address, Account>) -> Result<(), Self::Error> {
28        self.commit(changes);
29        Ok(())
30    }
31}
32
33/// Error type for implementation of [`TryDatabaseCommit`] on
34/// [`Arc`].
35#[derive(Debug, Clone, Copy, PartialEq, Eq)]
36pub struct ArcUpgradeError;
37
38impl fmt::Display for ArcUpgradeError {
39    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
40        write!(f, "Arc reference is not unique, cannot mutate")
41    }
42}
43
44impl Error for ArcUpgradeError {}
45
46impl<Db> TryDatabaseCommit for Arc<Db>
47where
48    Db: DatabaseCommit + Send + Sync,
49{
50    type Error = ArcUpgradeError;
51
52    #[inline]
53    fn try_commit(&mut self, changes: HashMap<Address, Account>) -> Result<(), Self::Error> {
54        Arc::get_mut(self)
55            .map(|db| db.commit(changes))
56            .ok_or(ArcUpgradeError)
57    }
58}
59
60#[cfg(test)]
61mod test {
62    use super::*;
63    use crate::DatabaseCommit;
64    use std::sync::Arc;
65
66    struct MockDb;
67
68    impl DatabaseCommit for MockDb {
69        fn commit(&mut self, _changes: HashMap<Address, Account>) {}
70    }
71
72    #[test]
73    fn arc_try_commit() {
74        let mut db = Arc::new(MockDb);
75        let db_2 = Arc::clone(&db);
76
77        assert_eq!(
78            db.try_commit(Default::default()).unwrap_err(),
79            ArcUpgradeError
80        );
81        drop(db_2);
82        db.try_commit(Default::default()).unwrap();
83    }
84}