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

Use shared pointer to retain wallet instance #13063

Merged
merged 1 commit into from May 24, 2018

Conversation

promag
Copy link
Member

@promag promag commented Apr 23, 2018

Currently there are 3 places where it makes sense to retain a wallet shared pointer:

  • vpwallets;
  • interfaces::Wallet interface instance - used by the UI;
  • wallet RPC functions - given by GetWalletForJSONRPCRequest.

The way it is now it is possible to have, for instance, listunspent RPC and in parallel unload the wallet (once #13111 is merged) without blocking. Once the RPC finishes, the shared pointer will release the wallet.

It is also possible to get all existing wallets without blocking because the caller keeps a local list of shared pointers.

This is mostly relevant for wallet unloading.

This PR replaces #11402.

@jnewbery
Copy link
Contributor

needs rebase

@promag
Copy link
Member Author

promag commented Apr 24, 2018

Rebased.

@Empact
Copy link
Member

Empact commented Apr 25, 2018

I like the idea of CWalletRef here. std::shared_ptr<CWallet> buries the lede a bit.

@jonasschnelli
Copy link
Contributor

Concept ACK.
A bit unfortunate that we have a lot of CWallet* const pwallet = wallet.get(); calls outside of any lock which AFAIK partially defeats the improvements the shared pointer adds.

@promag
Copy link
Member Author

promag commented Apr 26, 2018

A bit unfortunate that we have a lot of CWallet* const pwallet = wallet.get(); calls outside of any lock

@jonasschnelli what you mean by outside? There is always a std::shared_ptr<CWallet> in scope when .get() pointer is used. The only exception is RegisterValidationInterface(walletInstance.get());.

@jonasschnelli
Copy link
Contributor

@promag: Yes. Your right.

@promag
Copy link
Member Author

promag commented May 7, 2018

Rebased on master.

@promag promag force-pushed the 2018-04-wallet-sharedptr branch from 25c5c3f to 1279e2b Compare May 8, 2018 06:39
Copy link
Contributor

@jnewbery jnewbery left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

utACK 1279e2bdc1493e1d7b53ab43d09d16ac0926eb65

@@ -453,11 +453,12 @@ class WalletImpl : public Wallet
return MakeHandler(m_wallet.NotifyWatchonlyChanged.connect(fn));
}

std::shared_ptr<CWallet> m_shared_wallet;
CWallet& m_wallet;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is it possible to remove m_wallet and just keep m_shared_wallet?

Copy link
Member Author

@promag promag May 22, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, sure, but the diff will grow.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can be done in a follow-up PR.

@@ -134,7 +134,9 @@ static std::string LabelFromValue(const UniValue& value)

static UniValue getnewaddress(const JSONRPCRequest& request)
{
CWallet * const pwallet = GetWalletForJSONRPCRequest(request);
std::shared_ptr<CWallet> const wallet = GetWalletForJSONRPCRequest(request);
CWallet* const pwallet = wallet.get();
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we update EnsureWalletIsAvailable() to take a std::shared_ptr<CWallet>, and then remove the need to create a CWallet* const in all of these rpc methods?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The problem is that there are a lot of other calls that receive CWallet* and the diff started to be big. I can do that in a separate branch so you can see, WDYT?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Definitely. Can be done in a follow-up PR.

@@ -259,7 +259,7 @@ bool WalletInit::Open() const
}

for (const std::string& walletFile : gArgs.GetArgs("-wallet")) {
CWallet * const pwallet = CWallet::CreateWalletFromFile(walletFile, fs::absolute(walletFile, GetWalletDir()));
std::shared_ptr<CWallet> pwallet = CWallet::CreateWalletFromFile(walletFile, fs::absolute(walletFile, GetWalletDir()));
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: it'd be nice to rename these variables to wallet (yes, I know these are (smart) pointers, but pwallet everywhere else means raw pointers)

@jnewbery
Copy link
Contributor

jnewbery commented May 8, 2018

Can you update the PR description with the motivation for this (possibly just copy from #11402)?

Copy link
Contributor

@jonasschnelli jonasschnelli left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

utACK 1279e2bdc1493e1d7b53ab43d09d16ac0926eb65

I agree with @jnewbery that removing m_wallet in interface/wallet.cpp would be good, though I think this can also be done in another pull.

@laanwj laanwj added this to Blockers in High-priority for review May 18, 2018
Copy link
Contributor

@jimpo jimpo left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I feel like this can all be done with unique_ptrs and references, which is preferable. Basically,

std::vector<std::unique_ptr<CWallet>> vpwallets;  // Has owning references to all the wallets

CWallet& AddWallet(std::unique_ptr<CWallet> wallet);  // Adds and gives ownership to vpwallets
std::unique_ptr<CWallet> RemoveWallet(const CWallet& wallet);  // Removes and releases ownership from vpwallets

std::vector<CWallet&> GetWallets();
CWallet& GetWallet(const std::string& name);

Any particular reason they need to be shared?

@@ -20,7 +20,7 @@ void RegisterWalletRPCCommands(CRPCTable &t);
* @param[in] request JSONRPCRequest that wishes to access a wallet
* @return nullptr if no wallet should be used, or a pointer to the CWallet
*/
CWallet *GetWalletForJSONRPCRequest(const JSONRPCRequest& request);
std::shared_ptr<CWallet> GetWalletForJSONRPCRequest(const JSONRPCRequest& request);
Copy link
Contributor

@jimpo jimpo May 19, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this should just return a raw pointer or CWallet&.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The RPC handler must hold the wallet to prevent concurrent unload.

Copy link

@danielsam danielsam left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good

@maflcko
Copy link
Member

maflcko commented May 21, 2018

Needs rebase

@promag
Copy link
Member Author

promag commented May 22, 2018

std::unique_ptr<CWallet> RemoveWallet(const CWallet& wallet);  // Removes and releases ownership from vpwallets

@jimpo without shared_ptr the caller of RemoveWallet must ensure no one is using the wallet before releasing it. This may require synchronization between multiple threads, including UI.

With shared_ptr, the last pointer can safely release the wallet.

@jimpo
Copy link
Contributor

jimpo commented May 22, 2018

utACK 80b4910

@laanwj laanwj merged commit 80b4910 into bitcoin:master May 24, 2018
laanwj added a commit that referenced this pull request May 24, 2018
80b4910 wallet: Use shared pointer to retain wallet instance (João Barbosa)

Pull request description:

  Currently there are 3 places where it makes sense to retain a wallet shared pointer:
   - `vpwallets`;
   - `interfaces::Wallet` interface instance - used by the UI;
   - wallet RPC functions - given by `GetWalletForJSONRPCRequest`.

  The way it is now it is possible to have, for instance, listunspent RPC and in parallel unload the wallet (once #13111 is merged) without blocking. Once the RPC finishes, the shared pointer will release the wallet.

  It is also possible to get all existing wallets without blocking because the caller keeps a local list of shared pointers.

  This is mostly relevant for wallet unloading.

  This PR replaces #11402.

Tree-SHA512: b7e37c7e1ab56626085afe2d40b1628e8d4f0dbda08df01b7e618ecd2d894ce9b83d4219443f444ba889096286eff002f163cb0a48f37063b62e9ba4ccfa6cce
@maflcko maflcko removed this from Blockers in High-priority for review May 24, 2018
@fanquake fanquake moved this from In progress to Done in Multiwallet support Jun 1, 2018
maflcko pushed a commit that referenced this pull request Jun 20, 2018
3a03d2a Qt: load wallet in UI after possible init aborts (Jonas Schnelli)

Pull request description:

  Bug was introduced in #13063 (80b4910) where #13097 made possible to get "hit" by that bug. Reported by @ken2812221 (#13097 (comment)).

  Dynamically loading a wallet informs the UI (and therefore makes the instance accessible) about the new wallet before all possible error cases where handled.

  Easy to reproduce by starting `bitcoin-qt --regtest --nowallet -usehd=0` then in the console enter `loadwallet wallet.dat`.

  This PR will make sure only correctly initialised (loaded) wallets will appear in the UI.

Tree-SHA512: 3139545e852d53b117182b579f45259c198d1c25c1a6fa4e0108f942d45f6fe2691e6bfcbbae2e18c33ad0174a520f379c17867b1eb87f950d830a5f519fec4f
@promag promag deleted the 2018-04-wallet-sharedptr branch April 11, 2020 00:51
PastaPastaPasta pushed a commit to PastaPastaPasta/dash that referenced this pull request Dec 16, 2020
3a03d2a Qt: load wallet in UI after possible init aborts (Jonas Schnelli)

Pull request description:

  Bug was introduced in bitcoin#13063 (80b4910) where bitcoin#13097 made possible to get "hit" by that bug. Reported by @ken2812221 (bitcoin#13097 (comment)).

  Dynamically loading a wallet informs the UI (and therefore makes the instance accessible) about the new wallet before all possible error cases where handled.

  Easy to reproduce by starting `bitcoin-qt --regtest --nowallet -usehd=0` then in the console enter `loadwallet wallet.dat`.

  This PR will make sure only correctly initialised (loaded) wallets will appear in the UI.

Tree-SHA512: 3139545e852d53b117182b579f45259c198d1c25c1a6fa4e0108f942d45f6fe2691e6bfcbbae2e18c33ad0174a520f379c17867b1eb87f950d830a5f519fec4f
PastaPastaPasta pushed a commit to PastaPastaPasta/dash that referenced this pull request Dec 18, 2020
3a03d2a Qt: load wallet in UI after possible init aborts (Jonas Schnelli)

Pull request description:

  Bug was introduced in bitcoin#13063 (80b4910) where bitcoin#13097 made possible to get "hit" by that bug. Reported by @ken2812221 (bitcoin#13097 (comment)).

  Dynamically loading a wallet informs the UI (and therefore makes the instance accessible) about the new wallet before all possible error cases where handled.

  Easy to reproduce by starting `bitcoin-qt --regtest --nowallet -usehd=0` then in the console enter `loadwallet wallet.dat`.

  This PR will make sure only correctly initialised (loaded) wallets will appear in the UI.

Tree-SHA512: 3139545e852d53b117182b579f45259c198d1c25c1a6fa4e0108f942d45f6fe2691e6bfcbbae2e18c33ad0174a520f379c17867b1eb87f950d830a5f519fec4f
maflcko pushed a commit to bitcoin-core/gui that referenced this pull request Mar 10, 2021
…2 rebased)

7c90c67 rpc: refactor rpc wallet functions to take references instead of pointers (fanquake)
4866934 rpc: remove calls to CWallet.get() (fanquake)

Pull request description:

  This is a rebased #18592.

  > This PR replaces raw pointers in `rpcwallet.cpp` and `rpcdump.cpp` with **shared_ptr**. The motivation for this PR is described here bitcoin/bitcoin#18590

  > It seems that this PR is indirectly related to this issue: bitcoin/bitcoin#13063 (comment)

  > Notice: I have deliberately **not** changed the class `WalletRescanReserver ` whose constructor expects a raw pointer, because it's external and affects other areas, which I didn't touch to avoid making this PR "viral".

  > Fixes bitcoin/bitcoin#18590

ACKs for top commit:
  MarcoFalke:
    ACK 7c90c67 🐧
  ryanofsky:
    Code review ACK 7c90c67. Changes easy to review with `--word-diff-regex=. -U0`

Tree-SHA512: 32d69c813026b02260e8a89de9d6a5ab9e87826ba230687246583ac7a80c8c3fd00318da4658f1450e04c23d2c77ae765862de0d2a110b1312b3b69a1161e7ba
xdustinface pushed a commit to xdustinface/dash that referenced this pull request Mar 31, 2021
80b4910 wallet: Use shared pointer to retain wallet instance (João Barbosa)

Pull request description:

  Currently there are 3 places where it makes sense to retain a wallet shared pointer:
   - `vpwallets`;
   - `interfaces::Wallet` interface instance - used by the UI;
   - wallet RPC functions - given by `GetWalletForJSONRPCRequest`.

  The way it is now it is possible to have, for instance, listunspent RPC and in parallel unload the wallet (once bitcoin#13111 is merged) without blocking. Once the RPC finishes, the shared pointer will release the wallet.

  It is also possible to get all existing wallets without blocking because the caller keeps a local list of shared pointers.

  This is mostly relevant for wallet unloading.

  This PR replaces bitcoin#11402.

Tree-SHA512: b7e37c7e1ab56626085afe2d40b1628e8d4f0dbda08df01b7e618ecd2d894ce9b83d4219443f444ba889096286eff002f163cb0a48f37063b62e9ba4ccfa6cce
xdustinface pushed a commit to xdustinface/dash that referenced this pull request Mar 31, 2021
80b4910 wallet: Use shared pointer to retain wallet instance (João Barbosa)

Pull request description:

  Currently there are 3 places where it makes sense to retain a wallet shared pointer:
   - `vpwallets`;
   - `interfaces::Wallet` interface instance - used by the UI;
   - wallet RPC functions - given by `GetWalletForJSONRPCRequest`.

  The way it is now it is possible to have, for instance, listunspent RPC and in parallel unload the wallet (once bitcoin#13111 is merged) without blocking. Once the RPC finishes, the shared pointer will release the wallet.

  It is also possible to get all existing wallets without blocking because the caller keeps a local list of shared pointers.

  This is mostly relevant for wallet unloading.

  This PR replaces bitcoin#11402.

Tree-SHA512: b7e37c7e1ab56626085afe2d40b1628e8d4f0dbda08df01b7e618ecd2d894ce9b83d4219443f444ba889096286eff002f163cb0a48f37063b62e9ba4ccfa6cce
xdustinface pushed a commit to xdustinface/dash that referenced this pull request Mar 31, 2021
80b4910 wallet: Use shared pointer to retain wallet instance (João Barbosa)

Pull request description:

  Currently there are 3 places where it makes sense to retain a wallet shared pointer:
   - `vpwallets`;
   - `interfaces::Wallet` interface instance - used by the UI;
   - wallet RPC functions - given by `GetWalletForJSONRPCRequest`.

  The way it is now it is possible to have, for instance, listunspent RPC and in parallel unload the wallet (once bitcoin#13111 is merged) without blocking. Once the RPC finishes, the shared pointer will release the wallet.

  It is also possible to get all existing wallets without blocking because the caller keeps a local list of shared pointers.

  This is mostly relevant for wallet unloading.

  This PR replaces bitcoin#11402.

Tree-SHA512: b7e37c7e1ab56626085afe2d40b1628e8d4f0dbda08df01b7e618ecd2d894ce9b83d4219443f444ba889096286eff002f163cb0a48f37063b62e9ba4ccfa6cce
xdustinface pushed a commit to xdustinface/dash that referenced this pull request Apr 1, 2021
80b4910 wallet: Use shared pointer to retain wallet instance (João Barbosa)

Pull request description:

  Currently there are 3 places where it makes sense to retain a wallet shared pointer:
   - `vpwallets`;
   - `interfaces::Wallet` interface instance - used by the UI;
   - wallet RPC functions - given by `GetWalletForJSONRPCRequest`.

  The way it is now it is possible to have, for instance, listunspent RPC and in parallel unload the wallet (once bitcoin#13111 is merged) without blocking. Once the RPC finishes, the shared pointer will release the wallet.

  It is also possible to get all existing wallets without blocking because the caller keeps a local list of shared pointers.

  This is mostly relevant for wallet unloading.

  This PR replaces bitcoin#11402.

Tree-SHA512: b7e37c7e1ab56626085afe2d40b1628e8d4f0dbda08df01b7e618ecd2d894ce9b83d4219443f444ba889096286eff002f163cb0a48f37063b62e9ba4ccfa6cce
PastaPastaPasta pushed a commit to dashpay/dash that referenced this pull request Apr 1, 2021
)

80b4910 wallet: Use shared pointer to retain wallet instance (João Barbosa)

Pull request description:

  Currently there are 3 places where it makes sense to retain a wallet shared pointer:
   - `vpwallets`;
   - `interfaces::Wallet` interface instance - used by the UI;
   - wallet RPC functions - given by `GetWalletForJSONRPCRequest`.

  The way it is now it is possible to have, for instance, listunspent RPC and in parallel unload the wallet (once bitcoin#13111 is merged) without blocking. Once the RPC finishes, the shared pointer will release the wallet.

  It is also possible to get all existing wallets without blocking because the caller keeps a local list of shared pointers.

  This is mostly relevant for wallet unloading.

  This PR replaces bitcoin#11402.

Tree-SHA512: b7e37c7e1ab56626085afe2d40b1628e8d4f0dbda08df01b7e618ecd2d894ce9b83d4219443f444ba889096286eff002f163cb0a48f37063b62e9ba4ccfa6cce

Co-authored-by: Wladimir J. van der Laan <laanwj@gmail.com>
xdustinface pushed a commit to xdustinface/dash that referenced this pull request Apr 4, 2021
3a03d2a Qt: load wallet in UI after possible init aborts (Jonas Schnelli)

Pull request description:

  Bug was introduced in bitcoin#13063 (80b4910) where bitcoin#13097 made possible to get "hit" by that bug. Reported by @ken2812221 (bitcoin#13097 (comment)).

  Dynamically loading a wallet informs the UI (and therefore makes the instance accessible) about the new wallet before all possible error cases where handled.

  Easy to reproduce by starting `bitcoin-qt --regtest --nowallet -usehd=0` then in the console enter `loadwallet wallet.dat`.

  This PR will make sure only correctly initialised (loaded) wallets will appear in the UI.

Tree-SHA512: 3139545e852d53b117182b579f45259c198d1c25c1a6fa4e0108f942d45f6fe2691e6bfcbbae2e18c33ad0174a520f379c17867b1eb87f950d830a5f519fec4f
xdustinface pushed a commit to xdustinface/dash that referenced this pull request Apr 4, 2021
3a03d2a Qt: load wallet in UI after possible init aborts (Jonas Schnelli)

Pull request description:

  Bug was introduced in bitcoin#13063 (80b4910) where bitcoin#13097 made possible to get "hit" by that bug. Reported by @ken2812221 (bitcoin#13097 (comment)).

  Dynamically loading a wallet informs the UI (and therefore makes the instance accessible) about the new wallet before all possible error cases where handled.

  Easy to reproduce by starting `bitcoin-qt --regtest --nowallet -usehd=0` then in the console enter `loadwallet wallet.dat`.

  This PR will make sure only correctly initialised (loaded) wallets will appear in the UI.

Tree-SHA512: 3139545e852d53b117182b579f45259c198d1c25c1a6fa4e0108f942d45f6fe2691e6bfcbbae2e18c33ad0174a520f379c17867b1eb87f950d830a5f519fec4f
xdustinface pushed a commit to xdustinface/dash that referenced this pull request Apr 4, 2021
3a03d2a Qt: load wallet in UI after possible init aborts (Jonas Schnelli)

Pull request description:

  Bug was introduced in bitcoin#13063 (80b4910) where bitcoin#13097 made possible to get "hit" by that bug. Reported by @ken2812221 (bitcoin#13097 (comment)).

  Dynamically loading a wallet informs the UI (and therefore makes the instance accessible) about the new wallet before all possible error cases where handled.

  Easy to reproduce by starting `bitcoin-qt --regtest --nowallet -usehd=0` then in the console enter `loadwallet wallet.dat`.

  This PR will make sure only correctly initialised (loaded) wallets will appear in the UI.

Tree-SHA512: 3139545e852d53b117182b579f45259c198d1c25c1a6fa4e0108f942d45f6fe2691e6bfcbbae2e18c33ad0174a520f379c17867b1eb87f950d830a5f519fec4f
xdustinface pushed a commit to xdustinface/dash that referenced this pull request Apr 4, 2021
3a03d2a Qt: load wallet in UI after possible init aborts (Jonas Schnelli)

Pull request description:

  Bug was introduced in bitcoin#13063 (80b4910) where bitcoin#13097 made possible to get "hit" by that bug. Reported by @ken2812221 (bitcoin#13097 (comment)).

  Dynamically loading a wallet informs the UI (and therefore makes the instance accessible) about the new wallet before all possible error cases where handled.

  Easy to reproduce by starting `bitcoin-qt --regtest --nowallet -usehd=0` then in the console enter `loadwallet wallet.dat`.

  This PR will make sure only correctly initialised (loaded) wallets will appear in the UI.

Tree-SHA512: 3139545e852d53b117182b579f45259c198d1c25c1a6fa4e0108f942d45f6fe2691e6bfcbbae2e18c33ad0174a520f379c17867b1eb87f950d830a5f519fec4f
xdustinface pushed a commit to xdustinface/dash that referenced this pull request Apr 5, 2021
3a03d2a Qt: load wallet in UI after possible init aborts (Jonas Schnelli)

Pull request description:

  Bug was introduced in bitcoin#13063 (80b4910) where bitcoin#13097 made possible to get "hit" by that bug. Reported by @ken2812221 (bitcoin#13097 (comment)).

  Dynamically loading a wallet informs the UI (and therefore makes the instance accessible) about the new wallet before all possible error cases where handled.

  Easy to reproduce by starting `bitcoin-qt --regtest --nowallet -usehd=0` then in the console enter `loadwallet wallet.dat`.

  This PR will make sure only correctly initialised (loaded) wallets will appear in the UI.

Tree-SHA512: 3139545e852d53b117182b579f45259c198d1c25c1a6fa4e0108f942d45f6fe2691e6bfcbbae2e18c33ad0174a520f379c17867b1eb87f950d830a5f519fec4f
xdustinface pushed a commit to xdustinface/dash that referenced this pull request Apr 13, 2021
3a03d2a Qt: load wallet in UI after possible init aborts (Jonas Schnelli)

Pull request description:

  Bug was introduced in bitcoin#13063 (80b4910) where bitcoin#13097 made possible to get "hit" by that bug. Reported by @ken2812221 (bitcoin#13097 (comment)).

  Dynamically loading a wallet informs the UI (and therefore makes the instance accessible) about the new wallet before all possible error cases where handled.

  Easy to reproduce by starting `bitcoin-qt --regtest --nowallet -usehd=0` then in the console enter `loadwallet wallet.dat`.

  This PR will make sure only correctly initialised (loaded) wallets will appear in the UI.

Tree-SHA512: 3139545e852d53b117182b579f45259c198d1c25c1a6fa4e0108f942d45f6fe2691e6bfcbbae2e18c33ad0174a520f379c17867b1eb87f950d830a5f519fec4f
@bitcoin bitcoin locked as resolved and limited conversation to collaborators Feb 15, 2022
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
Projects
No open projects
Development

Successfully merging this pull request may close these issues.

None yet

9 participants