Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[issue] Can't share struct Wallet by using Lazy #18

Closed
monaka opened this issue Dec 17, 2022 · 7 comments
Closed

[issue] Can't share struct Wallet by using Lazy #18

monaka opened this issue Dec 17, 2022 · 7 comments

Comments

@monaka
Copy link
Contributor

monaka commented Dec 17, 2022

How to reproduce

git clone https://github.com/diamondhands-rgb/rgb-lib-sample.git -b 43ba33c
cd rgb-lib-sample/wallet-share
cargo build --all-features

Expected

Finishes builds.

Actually

Failed to errors.

Addtional

cargo build is built with no error.

Logs after running `cargo build --all-features`. $ cargo test --all-features Compiling wallet-share v0.1.0 (/home/monaka/diamondhands-rdb/rgb-lib-sample/wallet-share) error[E0277]: `RefCell` cannot be shared between threads safely --> src/main.rs:31:26 | 31 | static WALLET_STATE: Lazy>> = Lazy::new(|| Arc::new(RwLock::new(WalletState::new()))); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `RefCell` cannot be shared between threads safely | = help: within `WalletState`, the trait `Sync` is not implemented for `RefCell` = note: required because it appears within the type `bdk::wallet::Wallet` = note: required because it appears within the type `rgb_lib::Wallet` = note: required because it appears within the type `Option` note: required because it appears within the type `WalletState` --> src/main.rs:9:12 | 9 | pub struct WalletState { | ^^^^^^^^^^^ = note: required for `std::sync::RwLock` to implement `Sync` = note: 2 redundant requirements hidden = note: required for `once_cell::imp::OnceCell>>` to implement `Sync` = note: required because it appears within the type `once_cell::sync::OnceCell>>` = note: required for `once_cell::sync::Lazy>>` to implement `Sync` = note: shared static variables must have a type that implements `Sync`

error[E0277]: *mut c_void cannot be shared between threads safely
--> src/main.rs:31:26
|
31 | static WALLET_STATE: Lazy<Arc<RwLock>> = Lazy::new(|| Arc::new(RwLock::new(WalletState::new())));
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ *mut c_void cannot be shared between threads safely
|
= help: within (rgb_rpc::client::RpcBus, microservices::esb::controller::Endpoint<rgb_rpc::service_id::ServiceId>), the trait Sync is not implemented for *mut c_void
= note: required because it appears within the type zmq2::Socket
= note: required because it appears within the type internet2::transport::zeromq::WrappedSocket
= note: required because it appears within the type internet2::transport::zeromq::Connection
= note: required because it appears within the type internet2::session::session::Session<internet2::session::transcoders::PlainTranscoder, internet2::transport::zeromq::Connection>
= note: required because it appears within the type microservices::esb::controller::Endpoint<rgb_rpc::service_id::ServiceId>
= note: required because it appears within the type (rgb_rpc::client::RpcBus, microservices::esb::controller::Endpoint<rgb_rpc::service_id::ServiceId>)
= note: required for hashbrown::raw::RawTable<(rgb_rpc::client::RpcBus, microservices::esb::controller::Endpoint<rgb_rpc::service_id::ServiceId>)> to implement Sync
= note: required because it appears within the type hashbrown::map::HashMap<rgb_rpc::client::RpcBus, microservices::esb::controller::Endpoint<rgb_rpc::service_id::ServiceId>, RandomState>
= note: required because it appears within the type HashMap<rgb_rpc::client::RpcBus, microservices::esb::controller::Endpoint<rgb_rpc::service_id::ServiceId>>
= note: required because it appears within the type microservices::esb::controller::EndpointList<rgb_rpc::client::RpcBus>
= note: required because it appears within the type microservices::esb::controller::Controller<rgb_rpc::client::RpcBus, rgb_rpc::messages::BusMsg, rgb_rpc::client::Handler>
= note: required because it appears within the type rgb_rpc::client::Client
= note: required because it appears within the type Option<rgb_rpc::client::Client>
= note: required because it appears within the type rgb_lib::Wallet
= note: required because it appears within the type Option<rgb_lib::Wallet>
note: required because it appears within the type WalletState
--> src/main.rs:9:12
|
9 | pub struct WalletState {
| ^^^^^^^^^^^
= note: required for std::sync::RwLock<WalletState> to implement Sync
= note: 2 redundant requirements hidden
= note: required for once_cell::imp::OnceCell<std::sync::Arc<std::sync::RwLock<WalletState>>> to implement Sync
= note: required because it appears within the type once_cell::sync::OnceCell<std::sync::Arc<std::sync::RwLock<WalletState>>>
= note: required for once_cell::sync::Lazy<std::sync::Arc<std::sync::RwLock<WalletState>>> to implement Sync
= note: shared static variables must have a type that implements Sync

For more information about this error, try rustc --explain E0277.
error: could not compile wallet-share due to 2 previous errors

refs #16 (comment)

@monaka
Copy link
Contributor Author

monaka commented Dec 17, 2022

I suppose this is a different {approach|issue} from RGB-WG/rgb-node#222 .
And I guess this can be resolved by mutual exclusions in rgb-lib.

@zoedberg
Copy link
Collaborator

@monaka running both cargo build or cargo build --all-features fails because there is no main function, while running cargo test --all-features produces the error you've mentioned.

The error doesn't seem strictly related to rgb-lib, looking to the code I think there are a few things that need to be fixed.

First, the example uses a lot of unnecessary complexity, making it harder to locate exactly what's the issue.

Moreover I don't understand why you are also saving WalletData, which is not necessary in order to operate the wallet and for which there's a method (get_wallet_data) to extract it in case it's needed.

I've pushed here a commit that simplifies the example, showing that it's possible to share the rgb-lib Wallet across different threads using Lazy and Mutex. You can check it works by running: cargo test -- --nocapture

@monaka
Copy link
Contributor Author

monaka commented Dec 18, 2022

@zoedberg

running both cargo build or cargo build --all-features fails because there is no main function, while running cargo test --all-features produces the error you've mentioned.

Surely, my code doesn't have the main() function.
But we don't need to care about this issue.

In fact, tests don't use the main function.
It's the reason that cargo build (without --all-features) runs with no issue.

$ cargo test 
   Compiling wallet-share v0.1.0 (/home/monaka/diamondhands-rgb/rgb-lib-sample/wallet-share)
    Finished test [unoptimized + debuginfo] target(s) in 20.33s
     Running unittests src/main.rs (target/debug/deps/wallet_share-e1f8a9c0723b1cbe)

running 1 test
test test::test1 ... ok

test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s

@zoedberg
Copy link
Collaborator

But we don't need to care about this issue.

@monaka I was just reporting the typo (that you actually made again, you are saying cargo build and then showing cargo test output) to avoid confusion. I understand this is not the main issue, in fact, the rest of the message explains what's the issue you're facing and also posts an example that shows this is not an rgb-lib issue but instead an issue with your example.

@monaka
Copy link
Contributor Author

monaka commented Dec 18, 2022

@zoedberg

Moreover I don't understand why you are also saving WalletData

This is simple.
I want to use rgb-lib on the WebApp's back-end. Not desktop. Not mobile.

Users may want to store mnemonic on the front-end side.
So the back-end won't store a mnemonic (and a publickey) on its startup time.

there's a method (get_wallet_data) to extract it in case it's needed.

Yes. Once the Wallet was instantiated, we can use get_wallet_data().
My code is an example for instantiating the Wallet (on a web-backend).

In other words, the back-end should be changed to its states as follows:

  1. (Startup the back-end)
  2. No WalletData, No Wallet.
  3. Takes WalletData from a web browser, No Wallet
  4. Creates Wallet from WalletData above.
  5. Calls go_online().

@zoedberg
Copy link
Collaborator

@monaka The flow you describe is possible and also instantiating and sharing the wallet with a combination of Lazy and Mutex is possible, so I think we can close this issue. If you're having issues in sharing the wallet in Shiro, I think we should directly debug that and not the example you have provided. So if you open an issue there, let me know, I will be happy to help

@monaka
Copy link
Contributor Author

monaka commented Dec 18, 2022

@zoedberg I read your code and docs published by Actix-web.
I suppose this issue can be resolved by your suggestion (using Mutex).

I'll try to fix my code tomorrow in Japan (because it's evening here).

I close this issue for now. Thank you for your help.

@monaka monaka closed this as completed Dec 18, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants