Skip to content

Conversation

@Nodonisko
Copy link

@Nodonisko Nodonisko commented Nov 25, 2025

This PR adds support for using faster native functions in mobile app environments for cryptographic functions. It's relying on RN Metro bundler internal mechanism where it automatically prefer files with .native.ts suffix.


Note

Introduces React Native native cryptography implementations and a unified getPublicKeyForCurve API, refactoring key/address derivation to use it and updating exports, tests, coverage, and peer deps.

  • Cryptography (Core/API):
    • Add src/cryptography/cryptography.native.ts with native hmacSha512, keccak256, pbkdf2Sha512, sha256, ripemd160, and getPublicKeyForCurve using @metamask/native-utils/react-native-quick-crypto.
    • Introduce getPublicKeyForCurve in src/cryptography/cryptography.ts and export via src/cryptography/index.ts and root src/index.ts.
    • Add src/cryptography/cryptography.types.ts with typed override surface.
  • Derivation Refactors:
    • Replace curve-specific public key derivations with getPublicKeyForCurve in SLIP10Node, derivers/bip39.ts, derivers/cip3.ts, and derivers/bip32.ts.
    • Update publicKeyToEthAddress signature to accept optional CryptographicFunctions; propagate in SLIP10Node.address.
    • Update getFingerprint to accept optional CryptographicFunctions and wire in SLIP10Node.fingerprint.
  • Exports/Tests:
    • Export new cryptography functions from package root and add tests for hashing functions and getPublicKeyForCurve; update index export coverage tests.
  • Tooling/Config:
    • Jest: exclude *.native.ts from coverage collection.
    • Add dev/peer deps: @metamask/native-utils, react-native-quick-crypto with optional peer metadata.

Written by Cursor Bugbot for commit 430bb77. This will update automatically on new commits. Configure here.

@Nodonisko Nodonisko requested a review from a team as a code owner November 25, 2025 10:41
sethkfman pushed a commit to MetaMask/metamask-mobile that referenced this pull request Dec 5, 2025
## **Description**

This PR implements new `@metamask/native-utils` package for C++
cryptography instead of JS implementation. That provides significant
performance improvements all across the app. Most visible improvements
are during app startup and SRP imports, but for example `keccak256`
helps also in many other places.

This PR should also have really nice synergy with
MetaMask/core#6654 that could shave of another
tens of percent for login times.

For now I am patching `@metamask/key-tree`, once
MetaMask/key-tree#223 is done, patch could be
removed, but it may take a while.

### Performance Optimization Results

Device: Pixel 4a 5G
Tested on SRP with 200+ accounts.

| Metric | Before Optimization* | After Optimization | Improvement | %
Faster |
| :--- | :--- | :--- | :--- | :--- |
| **App Loaded to Login screen** | 7s 333ms | **4s 750ms** | ⚡️ 2.58s
faster | **35.2%** |
| **Dashboard Loaded** | 14s 0ms | **6s 333ms** | ⚡️ 7.67s faster |
**54.8%** |
| **App is Responsive (60 FPS)** | 18s 783ms | **12s 166ms** | ⚡️ 6.62s
faster | **35.2%** |
| **SRP Import (Discovery)** | 276s 616ms | **203s 450ms** | ⚡️ 73.17s
faster | **26.5%** |

_* Before optimalization version has `@metamask/native-utils` completely
removed (including secp256k1 that was merged before)._

There should be around 200 - 300ms improvement in account creation time
but I am not including this in result because I did many measurements
but spread was too big to conclude any results from it. Another big
improvement for acccount creation should be
MetaMask/core#6654

## **Changelog**

<!--
If this PR is not End-User-Facing and should not show up in the
CHANGELOG, you can choose to either:
1. Write `CHANGELOG entry: null`
2. Label with `no-changelog`

If this PR is End-User-Facing, please write a short User-Facing
description in the past tense like:
`CHANGELOG entry: Added a new tab for users to see their NFTs`
`CHANGELOG entry: Fixed a bug that was causing some NFTs to flicker`

(This helps the Release Engineer do their job more quickly and
accurately)
-->

CHANGELOG entry:

## **Related issues**

Fixes:

## **Manual testing steps**

1. All accounts are discovered
2. Balances for tokens and total balance is correct
3. Correct receive addresses are generated

## **Screenshots/Recordings**
 
### Startup + Login


https://github.com/user-attachments/assets/24c8ca90-5475-4fa8-9062-30f6fa5133b2

### SRP Import

Observe also FPS counter, as you can see optimized version is
maintaining higher FPS (around ~20) compared to non-optimized (around
~10). That should be enough to make app usable even on very slow device
during running accounts discovery. To improve FPS even more we need to
optimize rerenders and some selectors.

In order to reduce discovery total time even more it would require
different strategies of discovery, for example instead doing account
detail requests one by one, until you find empty one, you could for
example request them in batches of 3 which should improve total time
significantly.


https://github.com/user-attachments/assets/9f6c9825-5d97-415e-903c-8f4327273a2d

## **Pre-merge author checklist**

- [ ] I’ve followed [MetaMask Contributor
Docs](https://github.com/MetaMask/contributor-docs) and [MetaMask Mobile
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.


<!-- CURSOR_SUMMARY -->
---

> [!NOTE]
> Replaces JS crypto with native implementations via
@metamask/native-utils, adds runtime perf shims, patches dependencies,
updates iOS pods/Jest config, and optimizes account sorting.
> 
> - **Performance/crypto integration**
> - Add `shimPerf.js` to monkey‑patch `@noble/*` and `js-sha3` with
native `getPublicKey`, `hmacSha512`, and `keccak256` from
`@metamask/native-utils`.
>   - Update `shim.js` to load the new perf shim.
> - **Library patches**
> - Patch `@ethereumjs/util` to export `pubToAddress` from
`@metamask/native-utils`.
> - Patch `@metamask/key-tree` Ed25519 to use
`nativeUtils.getPublicKeyEd25519`.
> - **Encryption**
> - Replace `Buffer.from(..., 'utf-8')` with `TextEncoder().encode(...)`
in `quick-crypto.ts` for key derivation and encryption inputs.
> - **Selectors**
> - Optimize `selectInternalAccounts` sorting by precomputing address
indices to avoid repeated `toFormattedAddress` calls.
> - **Testing**
> - Add Jest mock `app/__mocks__/@metamask/native-utils.js` and map it
in `jest.config.js`; expand `transformIgnorePatterns` for native
modules.
> - **iOS/Pods**
>   - Bump `NativeUtils` pod to `0.8.0`.
> - **Dependencies**
> - Upgrade `@metamask/native-utils` to `^0.8.0`; add `js-sha3@0.9.3`,
`@noble/hashes@1.8.0`.
> - Add Yarn patches/resolutions for `@ethereumjs/util@9.1.0` and
`@metamask/key-tree@10.1.1`; update `yarn.lock`.
> 
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
7ff47ad. This will update automatically
on new commits. Configure
[here](https://cursor.com/dashboard?tab=bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
github-merge-queue bot pushed a commit to MetaMask/metamask-mobile that referenced this pull request Dec 8, 2025
## **Description**

This PR is from an external contributor. Initial review and context
[here](#23270)

Credit @Nodonisko 

This PR implements new `@metamask/native-utils` package for C++
cryptography instead of JS implementation. That provides significant
performance improvements all across the app. Most visible improvements
are during app startup and SRP imports, but for example `keccak256`
helps also in many other places.

This PR should also have really nice synergy with
MetaMask/core#6654 that could shave of another
tens of percent for login times.

For now I am patching `@metamask/key-tree`, once
MetaMask/key-tree#223 is done, patch could be
removed, but it may take a while.

### Performance Optimization Results

Device: Pixel 4a 5G
Tested on SRP with 200+ accounts.

| Metric | Before Optimization* | After Optimization | Improvement | %
Faster |
| :--- | :--- | :--- | :--- | :--- |
| **App Loaded to Login screen** | 7s 333ms | **4s 750ms** | ⚡️ 2.58s
faster | **35.2%** |
| **Dashboard Loaded** | 14s 0ms | **6s 333ms** | ⚡️ 7.67s faster |
**54.8%** |
| **App is Responsive (60 FPS)** | 18s 783ms | **12s 166ms** | ⚡️ 6.62s
faster | **35.2%** |
| **SRP Import (Discovery)** | 276s 616ms | **203s 450ms** | ⚡️ 73.17s
faster | **26.5%** |

_* Before optimalization version has `@metamask/native-utils` completely
removed (including secp256k1 that was merged before)._

There should be around 200 - 300ms improvement in account creation time
but I am not including this in result because I did many measurements
but spread was too big to conclude any results from it. Another big
improvement for acccount creation should be
MetaMask/core#6654

## **Changelog**

<!--
If this PR is not End-User-Facing and should not show up in the
CHANGELOG, you can choose to either:
1. Write `CHANGELOG entry: null`
2. Label with `no-changelog`

If this PR is End-User-Facing, please write a short User-Facing
description in the past tense like:
`CHANGELOG entry: Added a new tab for users to see their NFTs`
`CHANGELOG entry: Fixed a bug that was causing some NFTs to flicker`

(This helps the Release Engineer do their job more quickly and
accurately)
-->

CHANGELOG entry: null

## **Related issues**

Fixes:

## **Manual testing steps**

1. All accounts are discovered
2. Balances for tokens and total balance is correct
3. Correct receive addresses are generated

## **Screenshots/Recordings**
 
### Startup + Login



https://github.com/user-attachments/assets/24c8ca90-5475-4fa8-9062-30f6fa5133b2

### SRP Import

Observe also FPS counter, as you can see optimized version is
maintaining higher FPS (around ~20) compared to non-optimized (around
~10). That should be enough to make app usable even on very slow device
during running accounts discovery. To improve FPS even more we need to
optimize rerenders and some selectors.

In order to reduce discovery total time even more it would require
different strategies of discovery, for example instead doing account
detail requests one by one, until you find empty one, you could for
example request them in batches of 3 which should improve total time
significantly.



https://github.com/user-attachments/assets/9f6c9825-5d97-415e-903c-8f4327273a2d

## **Pre-merge author checklist**

- [ ] I’ve followed [MetaMask Contributor
Docs](https://github.com/MetaMask/contributor-docs) and [MetaMask Mobile
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.



<!-- CURSOR_SUMMARY -->
---

> [!NOTE]
> Replaces JS crypto with native implementations via
@metamask/native-utils, adds perf shims, patches key libs, and updates
tests/config to support it.
> 
> - **Crypto performance**:
> - Add `shimPerf` to monkey-patch `@noble` and `js-sha3`
(`secp256k1.getPublicKey`, `hmacSha512`, `keccak256`) to use native C++
via `@metamask/native-utils`.
>   - Update `shim.js` to load `shimPerf`.
> - Switch `quick-crypto` string encoding to `TextEncoder` for key
derivation/encryption.
> - **Library patches**:
> - Patch `@ethereumjs/util` to export `pubToAddress` from
`@metamask/native-utils`.
> - Patch `@metamask/key-tree` `ed25519` to use
`native-utils.getPublicKeyEd25519`.
> - **Selectors**:
> - Optimize `selectInternalAccounts` sorting to pre-compute indices and
reduce `toFormattedAddress` calls.
> - **Testing/config**:
> - Add Jest mock `app/__mocks__/@metamask/native-utils.js` and map in
`jest.config.js`; extend `transformIgnorePatterns`.
> - **Dependencies/Pods/Lockfiles**:
> - Bump `@metamask/native-utils` to `^0.8.0` (iOS `NativeUtils` pod
0.8.0).
> - Add `js-sha3@0.9.3`, pin `@noble/hashes@1.8.0`, add Yarn
patches/locks for `@ethereumjs/util@9.1.0` and
`@metamask/key-tree@10.1.1`.
> 
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
95728ed. This will update automatically
on new commits. Configure
[here](https://cursor.com/dashboard?tab=bugbot).</sup>
<!-- /CURSOR_SUMMARY -->



<!--
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?
-->

## **Changelog**

<!--
If this PR is not End-User-Facing and should not show up in the
CHANGELOG, you can choose to either:
1. Write `CHANGELOG entry: null`
2. Label with `no-changelog`

If this PR is End-User-Facing, please write a short User-Facing
description in the past tense like:
`CHANGELOG entry: Added a new tab for users to see their NFTs`
`CHANGELOG entry: Fixed a bug that was causing some NFTs to flicker`

(This helps the Release Engineer do their job more quickly and
accurately)
-->

CHANGELOG entry:

## **Related issues**

Fixes:

## **Manual testing steps**

```gherkin
Feature: my feature name

  Scenario: user [verb for user action]
    Given [describe expected initial app state]

    When user [verb for user action]
    Then [describe expected outcome]
```

## **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 Contributor
Docs](https://github.com/MetaMask/contributor-docs) and [MetaMask Mobile
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.

---------

Co-authored-by: Daniel Suchý <suchydan@gmail.com>
abretonc7s pushed a commit to MetaMask/metamask-mobile that referenced this pull request Dec 15, 2025
## **Description**

This PR is from an external contributor. Initial review and context
[here](#23270)

Credit @Nodonisko 

This PR implements new `@metamask/native-utils` package for C++
cryptography instead of JS implementation. That provides significant
performance improvements all across the app. Most visible improvements
are during app startup and SRP imports, but for example `keccak256`
helps also in many other places.

This PR should also have really nice synergy with
MetaMask/core#6654 that could shave of another
tens of percent for login times.

For now I am patching `@metamask/key-tree`, once
MetaMask/key-tree#223 is done, patch could be
removed, but it may take a while.

### Performance Optimization Results

Device: Pixel 4a 5G
Tested on SRP with 200+ accounts.

| Metric | Before Optimization* | After Optimization | Improvement | %
Faster |
| :--- | :--- | :--- | :--- | :--- |
| **App Loaded to Login screen** | 7s 333ms | **4s 750ms** | ⚡️ 2.58s
faster | **35.2%** |
| **Dashboard Loaded** | 14s 0ms | **6s 333ms** | ⚡️ 7.67s faster |
**54.8%** |
| **App is Responsive (60 FPS)** | 18s 783ms | **12s 166ms** | ⚡️ 6.62s
faster | **35.2%** |
| **SRP Import (Discovery)** | 276s 616ms | **203s 450ms** | ⚡️ 73.17s
faster | **26.5%** |

_* Before optimalization version has `@metamask/native-utils` completely
removed (including secp256k1 that was merged before)._

There should be around 200 - 300ms improvement in account creation time
but I am not including this in result because I did many measurements
but spread was too big to conclude any results from it. Another big
improvement for acccount creation should be
MetaMask/core#6654

## **Changelog**

<!--
If this PR is not End-User-Facing and should not show up in the
CHANGELOG, you can choose to either:
1. Write `CHANGELOG entry: null`
2. Label with `no-changelog`

If this PR is End-User-Facing, please write a short User-Facing
description in the past tense like:
`CHANGELOG entry: Added a new tab for users to see their NFTs`
`CHANGELOG entry: Fixed a bug that was causing some NFTs to flicker`

(This helps the Release Engineer do their job more quickly and
accurately)
-->

CHANGELOG entry: null

## **Related issues**

Fixes:

## **Manual testing steps**

1. All accounts are discovered
2. Balances for tokens and total balance is correct
3. Correct receive addresses are generated

## **Screenshots/Recordings**
 
### Startup + Login



https://github.com/user-attachments/assets/24c8ca90-5475-4fa8-9062-30f6fa5133b2

### SRP Import

Observe also FPS counter, as you can see optimized version is
maintaining higher FPS (around ~20) compared to non-optimized (around
~10). That should be enough to make app usable even on very slow device
during running accounts discovery. To improve FPS even more we need to
optimize rerenders and some selectors.

In order to reduce discovery total time even more it would require
different strategies of discovery, for example instead doing account
detail requests one by one, until you find empty one, you could for
example request them in batches of 3 which should improve total time
significantly.



https://github.com/user-attachments/assets/9f6c9825-5d97-415e-903c-8f4327273a2d

## **Pre-merge author checklist**

- [ ] I’ve followed [MetaMask Contributor
Docs](https://github.com/MetaMask/contributor-docs) and [MetaMask Mobile
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.



<!-- CURSOR_SUMMARY -->
---

> [!NOTE]
> Replaces JS crypto with native implementations via
@metamask/native-utils, adds perf shims, patches key libs, and updates
tests/config to support it.
> 
> - **Crypto performance**:
> - Add `shimPerf` to monkey-patch `@noble` and `js-sha3`
(`secp256k1.getPublicKey`, `hmacSha512`, `keccak256`) to use native C++
via `@metamask/native-utils`.
>   - Update `shim.js` to load `shimPerf`.
> - Switch `quick-crypto` string encoding to `TextEncoder` for key
derivation/encryption.
> - **Library patches**:
> - Patch `@ethereumjs/util` to export `pubToAddress` from
`@metamask/native-utils`.
> - Patch `@metamask/key-tree` `ed25519` to use
`native-utils.getPublicKeyEd25519`.
> - **Selectors**:
> - Optimize `selectInternalAccounts` sorting to pre-compute indices and
reduce `toFormattedAddress` calls.
> - **Testing/config**:
> - Add Jest mock `app/__mocks__/@metamask/native-utils.js` and map in
`jest.config.js`; extend `transformIgnorePatterns`.
> - **Dependencies/Pods/Lockfiles**:
> - Bump `@metamask/native-utils` to `^0.8.0` (iOS `NativeUtils` pod
0.8.0).
> - Add `js-sha3@0.9.3`, pin `@noble/hashes@1.8.0`, add Yarn
patches/locks for `@ethereumjs/util@9.1.0` and
`@metamask/key-tree@10.1.1`.
> 
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
95728ed. This will update automatically
on new commits. Configure
[here](https://cursor.com/dashboard?tab=bugbot).</sup>
<!-- /CURSOR_SUMMARY -->



<!--
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?
-->

## **Changelog**

<!--
If this PR is not End-User-Facing and should not show up in the
CHANGELOG, you can choose to either:
1. Write `CHANGELOG entry: null`
2. Label with `no-changelog`

If this PR is End-User-Facing, please write a short User-Facing
description in the past tense like:
`CHANGELOG entry: Added a new tab for users to see their NFTs`
`CHANGELOG entry: Fixed a bug that was causing some NFTs to flicker`

(This helps the Release Engineer do their job more quickly and
accurately)
-->

CHANGELOG entry:

## **Related issues**

Fixes:

## **Manual testing steps**

```gherkin
Feature: my feature name

  Scenario: user [verb for user action]
    Given [describe expected initial app state]

    When user [verb for user action]
    Then [describe expected outcome]
```

## **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 Contributor
Docs](https://github.com/MetaMask/contributor-docs) and [MetaMask Mobile
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.

---------

Co-authored-by: Daniel Suchý <suchydan@gmail.com>
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.

1 participant