revm_database_interface/
try_commit.rs

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