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

Fix: SelectedNetworkController should return globally selected networkClient from getProviderAndBlockTracker when domain not in state #4063

Merged
merged 11 commits into from
Mar 26, 2024

Conversation

adonesky1
Copy link
Contributor

@adonesky1 adonesky1 commented Mar 15, 2024

Explanation

The SelectedNetworkController currently constructs a proxy for any domain that has permissions. Other domains have no associated proxy, so the getProviderAndBlockTracker method would throw an error.

This is problematic because we grab the network client for an origin a single time when constructing an RPC pipeline for that origin in the MetaMask extension. We don't re-create the RPC pipeline when permissions change. That means that the pipeline is setup with the wrong network client (see here for more details on this bug: MetaMask/metamask-extension#23509 )

To resolve this problem, we can instead keep network client proxies for all origins, not just those with permissions. Origins without permissions still should not have a selected network client ID state, but they can have proxies that point at the globally selected network client. That way, when the origin is granted permissions, we can redirect this proxy to the selected network client and everything works smoothly, without needing to reconstruct the RPC pipeline.

This PR should be merged shortly after #4104

References

Fixes: #4062
See: #4104

Changelog

@metamask/network-controller

  • ADDED: Add getSelectedNetworkClient() method that returns the provider and blockTracker for the currently selected network
  • ADDED: Add 'NetworkController:getSelectedNetworkClient' action

@metamask/selected-network-controller

  • BREAKING: SelectedNetworkController now requires the NetworkController:getSelectedNetworkClient messenger action
  • CHANGED: Previously when a domain became no longer permissioned, it's network client proxy would continue to point at the networkClientId it was last set to. Now it is set to follow the globally selected network
  • CHANGED: SelectedNetworkController. getProviderAndBlockTracker() no longer throws an error if the useRequestQueue flag is false
  • CHANGED: Previously SelectedNetworkController. getProviderAndBlockTracker() threw an error if there was no networkClientId set for the passed domain. Now it returns a proxy that follows the globally selected network instead.

Checklist

  • I've updated the test suite for new or updated code as appropriate
  • I've updated documentation (JSDoc, Markdown, etc.) for new or updated code as appropriate
  • I've highlighted breaking changes using the "BREAKING" category above as appropriate

@adonesky1
Copy link
Contributor Author

@metamaskbot publish-preview

Copy link
Contributor

Preview builds have been published. See these instructions for more information about preview builds.

Expand for full list of packages and versions.
{
  "@metamask-previews/accounts-controller": "12.0.1-preview-4851cbc9",
  "@metamask-previews/address-book-controller": "4.0.1-preview-4851cbc9",
  "@metamask-previews/announcement-controller": "6.0.1-preview-4851cbc9",
  "@metamask-previews/approval-controller": "6.0.1-preview-4851cbc9",
  "@metamask-previews/assets-controllers": "27.0.1-preview-4851cbc9",
  "@metamask-previews/base-controller": "5.0.1-preview-4851cbc9",
  "@metamask-previews/build-utils": "2.0.1-preview-4851cbc9",
  "@metamask-previews/composable-controller": "6.0.1-preview-4851cbc9",
  "@metamask-previews/controller-utils": "9.0.1-preview-4851cbc9",
  "@metamask-previews/ens-controller": "10.0.1-preview-4851cbc9",
  "@metamask-previews/eth-json-rpc-provider": "3.0.1-preview-4851cbc9",
  "@metamask-previews/gas-fee-controller": "14.0.1-preview-4851cbc9",
  "@metamask-previews/json-rpc-engine": "8.0.1-preview-4851cbc9",
  "@metamask-previews/json-rpc-middleware-stream": "7.0.1-preview-4851cbc9",
  "@metamask-previews/keyring-controller": "14.0.1-preview-4851cbc9",
  "@metamask-previews/logging-controller": "3.0.1-preview-4851cbc9",
  "@metamask-previews/message-manager": "8.0.1-preview-4851cbc9",
  "@metamask-previews/name-controller": "6.0.1-preview-4851cbc9",
  "@metamask-previews/network-controller": "18.0.1-preview-4851cbc9",
  "@metamask-previews/notification-controller": "5.0.1-preview-4851cbc9",
  "@metamask-previews/permission-controller": "9.0.1-preview-4851cbc9",
  "@metamask-previews/permission-log-controller": "2.0.1-preview-4851cbc9",
  "@metamask-previews/phishing-controller": "9.0.1-preview-4851cbc9",
  "@metamask-previews/polling-controller": "6.0.1-preview-4851cbc9",
  "@metamask-previews/preferences-controller": "9.0.1-preview-4851cbc9",
  "@metamask-previews/queued-request-controller": "0.6.1-preview-4851cbc9",
  "@metamask-previews/rate-limit-controller": "5.0.1-preview-4851cbc9",
  "@metamask-previews/selected-network-controller": "10.0.1-preview-4851cbc9",
  "@metamask-previews/signature-controller": "14.0.1-preview-4851cbc9",
  "@metamask-previews/transaction-controller": "25.1.0-preview-4851cbc9",
  "@metamask-previews/user-operation-controller": "6.0.1-preview-4851cbc9"
}

globallySelectedNetworkClient.blockTracker,
);
} else if (networkProxy) {
this.#proxies.delete(domain);
Copy link
Contributor Author

Choose a reason for hiding this comment

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

we still need to destroy the proxies to avoid a memory leak.

From @Gudahtt :

We can counteract this by storing the proxies as WeakRefs using the strategy described here: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Memory_management#weakrefs_and_finalizationregistry

@adonesky1 adonesky1 changed the title Selected network bug fix wip Fix: SelectedNetworkController should return globally selected networkClient from getProviderAndBlockTracker when domain not in state Mar 18, 2024
tsconfig.packages.json Outdated Show resolved Hide resolved
@jiexi
Copy link
Contributor

jiexi commented Mar 20, 2024

@metamaskbot publish-preview

Copy link
Contributor

Preview builds have been published. See these instructions for more information about preview builds.

Expand for full list of packages and versions.
{
  "@metamask-previews/accounts-controller": "12.0.1-preview-59bf6d5d",
  "@metamask-previews/address-book-controller": "4.0.1-preview-59bf6d5d",
  "@metamask-previews/announcement-controller": "6.0.1-preview-59bf6d5d",
  "@metamask-previews/approval-controller": "6.0.1-preview-59bf6d5d",
  "@metamask-previews/assets-controllers": "27.2.0-preview-59bf6d5d",
  "@metamask-previews/base-controller": "5.0.1-preview-59bf6d5d",
  "@metamask-previews/build-utils": "2.0.1-preview-59bf6d5d",
  "@metamask-previews/composable-controller": "6.0.1-preview-59bf6d5d",
  "@metamask-previews/controller-utils": "9.0.2-preview-59bf6d5d",
  "@metamask-previews/ens-controller": "10.0.1-preview-59bf6d5d",
  "@metamask-previews/eth-json-rpc-provider": "3.0.1-preview-59bf6d5d",
  "@metamask-previews/gas-fee-controller": "14.0.1-preview-59bf6d5d",
  "@metamask-previews/json-rpc-engine": "8.0.1-preview-59bf6d5d",
  "@metamask-previews/json-rpc-middleware-stream": "7.0.1-preview-59bf6d5d",
  "@metamask-previews/keyring-controller": "14.0.1-preview-59bf6d5d",
  "@metamask-previews/logging-controller": "3.0.1-preview-59bf6d5d",
  "@metamask-previews/message-manager": "8.0.1-preview-59bf6d5d",
  "@metamask-previews/name-controller": "6.0.1-preview-59bf6d5d",
  "@metamask-previews/network-controller": "18.0.1-preview-59bf6d5d",
  "@metamask-previews/notification-controller": "5.0.1-preview-59bf6d5d",
  "@metamask-previews/permission-controller": "9.0.2-preview-59bf6d5d",
  "@metamask-previews/permission-log-controller": "2.0.1-preview-59bf6d5d",
  "@metamask-previews/phishing-controller": "9.0.1-preview-59bf6d5d",
  "@metamask-previews/polling-controller": "6.0.1-preview-59bf6d5d",
  "@metamask-previews/preferences-controller": "9.0.1-preview-59bf6d5d",
  "@metamask-previews/queued-request-controller": "0.6.1-preview-59bf6d5d",
  "@metamask-previews/rate-limit-controller": "5.0.1-preview-59bf6d5d",
  "@metamask-previews/selected-network-controller": "10.0.1-preview-59bf6d5d",
  "@metamask-previews/signature-controller": "14.0.1-preview-59bf6d5d",
  "@metamask-previews/transaction-controller": "25.2.0-preview-59bf6d5d",
  "@metamask-previews/user-operation-controller": "6.0.2-preview-59bf6d5d"
}

],
);

// TODO(JL): replace this with a test that the proxy is removed from cache when the domainProxyMap PR is merged
Copy link
Contributor

Choose a reason for hiding this comment

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

TODO after #4104 is merged

@jiexi jiexi marked this pull request as ready for review March 22, 2024 22:56
@jiexi jiexi requested a review from a team as a code owner March 22, 2024 22:56
@@ -654,6 +665,21 @@ export class NetworkController extends BaseController<
};
}

getSelectedNetworkClient():
Copy link
Member

Choose a reason for hiding this comment

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

This method should have a JSDoc description.

Maybe also worth adding a @deprecated tag on getProviderAndBlockTracker (it's equivalent to this, except more difficult to work with because of the return type)

Copy link
Contributor Author

@adonesky1 adonesky1 Mar 26, 2024

Choose a reason for hiding this comment

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

done here: b0f1670


this.update((state) => {
state.domains[domain] = networkClientId;
});
}

#unsetNetworkClientIdForDomain(domain: Domain) {
Copy link
Member

Choose a reason for hiding this comment

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

Nit: Could use a JSDoc description here as well

Copy link
Contributor Author

@adonesky1 adonesky1 Mar 26, 2024

Choose a reason for hiding this comment

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

done here: b0f1670

adonesky1 added a commit that referenced this pull request Mar 26, 2024
…ructor params (#4104)

## Explanation

In a [preceding PR](#4063), the
SelectedNetworkController will start to keep proxy instances for all
domains seen without a way to remove them when they become stale. This
PR exposes the private proxies cache map as a constructor param which
will enable callers to implement their own cache invalidation strategies
without needing to concern the SelectedNetworkController of the
implementation details themselves. This is needed because Mobile and
Extension will need to follow different cache invalidation strategies.

This PR should be merged before
#4063

## References

Fixes: #4062
See: #4063

## Changelog

### `@metamask/selected-network-controller`

- **BREAKING**: `SelectedNetworkController` now expects the
`domainProxyMap` param which is a `Map` of `Domain` to `NetworkProxy`
- **ADDED**: exports the `Domain` type

## Checklist

- [ ] I've updated the test suite for new or updated code as appropriate
- [ ] I've updated documentation (JSDoc, Markdown, etc.) for new or
updated code as appropriate
- [ ] I've highlighted breaking changes using the "BREAKING" category
above as appropriate

---------

Co-authored-by: Alex Donesky <adonesky@gmail.com>
Co-authored-by: Mark Stacey <markjstacey@gmail.com>
@adonesky1 adonesky1 force-pushed the selected-network-bug-fix-wip branch 2 times, most recently from 5828800 to f3fd820 Compare March 26, 2024 14:45
@adonesky1 adonesky1 force-pushed the selected-network-bug-fix-wip branch from f3fd820 to af622c6 Compare March 26, 2024 14:58
@adonesky1 adonesky1 force-pushed the selected-network-bug-fix-wip branch from af622c6 to b0f1670 Compare March 26, 2024 14:59
@adonesky1 adonesky1 requested review from jiexi and Gudahtt March 26, 2024 15:15
Copy link
Member

@Gudahtt Gudahtt left a comment

Choose a reason for hiding this comment

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

LGTM!

@adonesky1 adonesky1 merged commit 0e0ee52 into main Mar 26, 2024
139 checks passed
@adonesky1 adonesky1 deleted the selected-network-bug-fix-wip branch March 26, 2024 15:34
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

Successfully merging this pull request may close these issues.

[selected-network-controller] Proxy all domains, even those without permissions
3 participants