Skip to content

Commit

Permalink
feat: Log the validity of the keyringController in the top 3 Migratio…
Browse files Browse the repository at this point in the history
…ns that appear in Sentry (MetaMask#9785)

…migrations that have been reporting errors

<!--
Please submit this PR as a draft initially.
Do not mark it as "Ready for review" until the template has been
completely filled out, and PR status checks have passed at least once.
-->

## **Description**

<!--
Write a short description of the changes included in this pull request,
also include relevant motivation and context. Have in mind the following
questions:
1. What is the reason for the change?
2. What is the improvement/solution?
-->

As part of the Vault Corruption Tactics:
https://www.notion.so/metamask-consensys/Vault-Corruption-98cdfc486e75419fa3e53b7bfe244060

We have to increase our logging around possible areas that could be
leading to Vault Corruption, to gather more information.

Add Sentry logs to log the validity of the keyringController in the top
3 Migrations that appear in Sentry, with the highest number of issues.

Issue: MetaMask/mobile-planning#1712

Fixes: vault check in EngineService

## **Related issues**



## **Manual testing steps**

1. Go to this page...
2.
3.

## **Screenshots/Recordings**

<!-- If applicable, add screenshots and/or recordings to visualize the
before and after of your change. -->

### **Before**

<!-- [screenshots/recordings] -->

### **After**

<!-- [screenshots/recordings] -->

## **Pre-merge author checklist**

- [ ] I’ve followed [MetaMask Coding
Standards](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/CODING_GUIDELINES.md).
- [ ] I've completed the PR template to the best of my ability
- [ ] I’ve included tests if applicable
- [ ] I’ve documented my code using [JSDoc](https://jsdoc.app/) format
if applicable
- [ ] I’ve applied the right labels on the PR (see [labeling
guidelines](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/LABELING_GUIDELINES.md)).
Not required for external contributors.

## **Pre-merge reviewer checklist**

- [ ] I've manually tested the PR (e.g. pull and build branch, run the
app, test code being changed).
- [ ] I confirm that this PR addresses all acceptance criteria described
in the ticket it closes and includes the necessary testing evidence such
as recordings and or screenshots.
  • Loading branch information
MarioAslau authored Jun 19, 2024
1 parent 0dde4fb commit 44c2275
Show file tree
Hide file tree
Showing 9 changed files with 70 additions and 3 deletions.
4 changes: 2 additions & 2 deletions app/core/EngineService/EngineService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -119,7 +119,7 @@ class EngineService {
}

engine?.datamodel?.subscribe?.(() => {
if (!engine.context.KeyringController.vault) {
if (!engine.context.KeyringController.metadata.vault) {
Logger.message('keyringController vault missing for INIT_BG_STATE_KEY');
}
if (!this.engineInitialized) {
Expand All @@ -131,7 +131,7 @@ class EngineService {
controllers.forEach((controller) => {
const { name, key = undefined } = controller;
const update_bg_state_cb = () => {
if (!engine.context.KeyringController.vault) {
if (!engine.context.KeyringController.metadata.vault) {
Logger.message(
'keyringController vault missing for UPDATE_BG_STATE_KEY',
);
Expand Down
10 changes: 10 additions & 0 deletions app/store/migrations/023.js
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,16 @@ import ambiguousNetworks from './migration-data/amibiguous-networks.json';
*
**/
export default function migrate(state) {
const keyringControllerState = state.engine.backgroundState.KeyringController;
if (!isObject(keyringControllerState)) {
captureException(
// @ts-expect-error We are not returning state not to stop the flow of Vault recovery
new Error(
`Migration 23: Invalid vault in KeyringController: '${typeof keyringControllerState}'`,
),
);
}

const networkControllerState = state.engine.backgroundState.NetworkController;
const addressBookControllerState =
state.engine.backgroundState.AddressBookController;
Expand Down
10 changes: 10 additions & 0 deletions app/store/migrations/026.js
Original file line number Diff line number Diff line change
@@ -1,11 +1,21 @@
import { captureException } from '@sentry/react-native';
import { isObject } from '@metamask/utils';

/**
* This migration is to free space of unused data in the user devices
* regarding the phishing list property listState, that is no longer used
*
**/
export default function migrate(state) {
const keyringControllerState = state.engine.backgroundState.KeyringController;
if (!isObject(keyringControllerState)) {
captureException(
// @ts-expect-error We are not returning state not to stop the flow of Vault recovery
new Error(
`Migration 26: Invalid vault in KeyringController: '${typeof keyringControllerState}'`,
),
);
}
const phishingControllerState =
state.engine.backgroundState.PhishingController;
if (phishingControllerState?.listState) {
Expand Down
5 changes: 5 additions & 0 deletions app/store/migrations/026.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ describe('Migration #26', () => {
PhishingController: {
listState: {},
},
KeyringController: { vault: {} },
},
},
};
Expand All @@ -28,6 +29,7 @@ describe('Migration #26', () => {
engine: {
backgroundState: {
PhishingController: {},
KeyringController: { vault: {} },
},
},
});
Expand All @@ -41,6 +43,7 @@ describe('Migration #26', () => {
hotlistLastFetched: 1,
stalelistLastFetched: 1,
},
KeyringController: { vault: {} },
},
},
};
Expand All @@ -53,6 +56,7 @@ describe('Migration #26', () => {
hotlistLastFetched: 0,
stalelistLastFetched: 0,
},
KeyringController: { vault: {} },
},
},
});
Expand All @@ -63,6 +67,7 @@ describe('Migration #26', () => {
engine: {
backgroundState: {
PhishingController: {},
KeyringController: { vault: {} },
},
},
};
Expand Down
7 changes: 7 additions & 0 deletions app/store/migrations/035.ts
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,13 @@ export default async function migrate(stateAsync: unknown) {
return state;
}

const keyringControllerState = state.engine.backgroundState.KeyringController;
if (!isObject(keyringControllerState)) {
captureException(
`Migration 35: Invalid vault in KeyringController: '${typeof keyringControllerState}'`,
);
}

const networkControllerState = state.engine.backgroundState.NetworkController;
const newNetworkControllerState = state.engine.backgroundState
.NetworkController as NetworkState;
Expand Down
15 changes: 14 additions & 1 deletion app/store/migrations/036.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,7 @@ function createMockState(
PreferencesController: {
...preferenceState,
},
KeyringController: { vault: {} },
},
},
};
Expand Down Expand Up @@ -117,6 +118,7 @@ describe('Migration #036', () => {
engine: {
backgroundState: {
PreferencesController: undefined,
KeyringController: { vault: {} },
},
},
};
Expand All @@ -132,6 +134,7 @@ describe('Migration #036', () => {
engine: {
backgroundState: {
PreferencesController: {},
KeyringController: { vault: {} },
},
},
};
Expand All @@ -154,12 +157,12 @@ describe('Migration #036', () => {
selectedAddress: MOCK_ADDRESS_1,
});
const newState = migrate(oldState);

const expectedUuid = getUUIDFromAddressOfNormalAccount(MOCK_ADDRESS_1);
const resultInternalAccount = expectedInternalAccount(
MOCK_ADDRESS_1,
'Account 1',
);

expect(newState).toStrictEqual({
engine: {
backgroundState: {
Expand All @@ -181,6 +184,7 @@ describe('Migration #036', () => {
},
selectedAddress: '0x0',
},
KeyringController: { vault: {} },
},
},
});
Expand Down Expand Up @@ -218,6 +222,7 @@ describe('Migration #036', () => {
},
},
PreferencesController: expect.any(Object),
KeyringController: { vault: {} },
},
},
});
Expand Down Expand Up @@ -247,6 +252,7 @@ describe('Migration #036', () => {
selectedAccount: expectedUuid,
},
},
KeyringController: { vault: {} },
},
},
});
Expand Down Expand Up @@ -282,6 +288,7 @@ describe('Migration #036', () => {
},
},
PreferencesController: expect.any(Object),
KeyringController: { vault: {} },
},
},
});
Expand All @@ -306,6 +313,7 @@ describe('Migration #036', () => {
selectedAccount: '', // Expect no account to be selected
},
},
KeyringController: { vault: {} },
},
},
});
Expand All @@ -332,6 +340,7 @@ describe('Migration #036', () => {
getUUIDFromAddressOfNormalAccount(MOCK_ADDRESS_1),
},
},
KeyringController: { vault: {} },
},
},
});
Expand All @@ -345,6 +354,7 @@ describe('Migration #036', () => {
identities: {},
selectedAddress: '',
},
KeyringController: { vault: {} },
},
},
};
Expand All @@ -359,6 +369,7 @@ describe('Migration #036', () => {
selectedAccount: '',
},
},
KeyringController: { vault: {} },
},
},
});
Expand Down Expand Up @@ -393,6 +404,7 @@ describe('Migration #036', () => {
},
},
},
KeyringController: { vault: {} },
},
},
});
Expand Down Expand Up @@ -436,6 +448,7 @@ describe('Migration #036', () => {
selectedAccount: expectedUuid,
},
},
KeyringController: { vault: {} },
},
},
});
Expand Down
10 changes: 10 additions & 0 deletions app/store/migrations/036.ts
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,16 @@ export default function migrate(state: unknown) {
);
return state;
}

const keyringControllerState = state.engine.backgroundState.KeyringController;
if (!isObject(keyringControllerState)) {
captureException(
new Error(
`Migration 36: Invalid vault in KeyringController: '${typeof keyringControllerState}'`,
),
);
}

if (!isObject(state.engine.backgroundState.PreferencesController)) {
captureException(
new Error(
Expand Down
2 changes: 2 additions & 0 deletions app/store/migrations/037.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,7 @@ describe('Migration #37', () => {
NetworkController: {
networkId: '1',
},
KeyringController: { vault: {} },
},
},
};
Expand All @@ -77,6 +78,7 @@ describe('Migration #37', () => {
engine: {
backgroundState: {
NetworkController: {},
KeyringController: { vault: {} },
},
},
};
Expand Down
10 changes: 10 additions & 0 deletions app/store/migrations/037.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,16 @@ export default async function migrate(stateAsync: unknown) {
);
return state;
}

const keyringControllerState = state.engine.backgroundState.KeyringController;
if (!isObject(keyringControllerState)) {
captureException(
new Error(
`Migration 37: Invalid vault in KeyringController: '${typeof keyringControllerState}'`,
),
);
}

const networkControllerState = state.engine.backgroundState.NetworkController;

if (!isObject(networkControllerState)) {
Expand Down

0 comments on commit 44c2275

Please sign in to comment.