PersistedWallet: allow `load_wallet()`, `create_wallet()`, and `persist()` to accept `Arc<P>`
Describe the enhancement
PersistedWallet should be able to be dereferenced so it can take wrappers like Arc<P>
Use case
For my project I am creating a wallet with a generic trait that implements WalletPersister. I want to pass it but it is wrapped in Arc<P>.
Additional context
Where I would like to pass Arc<impl Storage> https://github.com/bennyhodl/dlcdevkit/blob/c6cbaed7bb7c155e7249bfc1d367ddee73c53c89/ddk/src/wallet.rs#L57
https://github.com/bennyhodl/dlcdevkit/blob/c6cbaed7bb7c155e7249bfc1d367ddee73c53c89/ddk/src/lib.rs#L81
@bennyhodl I'm assuming P is a trait object of dyn Storage? If so, would implementing WalletPersister for Arc<Mutex<P>> work for you?
However, it seems you intend the Storage trait to only have methods that hold a non-mut ref to self and be both Send and Sync so you can have multiple references to it and also manipulate it at the same time. You've architectured your system to bypass lifetime rules of rust and force Storage implementations to have internal mutability.
To make this architecture work with BDK, I recommend the following:
pub trait Storage: Send + Sync + 'static {
/* Other methods not included */
fn initialize_bdk(&self) -> Result<ChangeSet, WalletError>;
fn persist_bdk(&self, changeset: &ChangeSet) -> Result<(), WalletError>;
}
impl WalletPersister for Arc<dyn Storage> {
type Error = WalletError;
fn initialize(persister: &mut Self) -> Result<ChangeSet, Self::Error> {
persister.as_ref().initialize_bdk()
}
fn persist(persister: &mut Self, changeset: &ChangeSet) -> Result<(), Self::Error> {
persister.as_ref().persist_bdk(changeset)
}
}
This way, you can have non-mut versions of initialize and persist (where the implementer is forced to do internal mutability), and pass Arc<dyn Storage> in PersistedWallet.
Thanks @evanlinjin ! https://github.com/bennyhodl/dlcdevkit/commit/59d6545127aa9ba1cc2148498bd1cef160b1a98f#diff-48cb0692300547b30fd804727339b5a1e33774e030229eb6f87a2c9bfa12f106R32