Giter Club home page Giter Club logo

keyringcontroller's Introduction

Eth Keyring Controller

Warning

This package has been merged with @metamask/keyring-controller. This repository is in maintenance mode and PRs will no longer be accepted, with the exception of security changes.

A module for managing groups of Ethereum accounts called "Keyrings", defined originally for MetaMask's multiple-account-type feature.

To add new account types to a KeyringController, just make sure it follows The Keyring Class Protocol.

The KeyringController has three main responsibilities:

  • Initializing & using (signing with) groups of Ethereum accounts ("keyrings").
  • Keeping track of local nicknames for those individual accounts.
  • Providing password-encryption persisting & restoring of secret information.

Installation

yarn add @metamask/eth-keyring-controller

This library uses the Node.js events API. If you are using this library outside of a Node.js context, ensure that you have a polyfill for the events API (this is built-in to browserify).

Usage

const { KeyringController } = require('@metamask/eth-keyring-controller');
const SimpleKeyring = require('@metamask/eth-simple-keyring');

const keyringController = new KeyringController({
  keyringTypes: [SimpleKeyring], // optional array of types to support.
  initState: initState.KeyringController, // Last emitted persisted state.
  encryptor: {
    // An optional object for defining encryption schemes:
    // Defaults to Browser-native SubtleCrypto.
    encrypt(password, object) {
      return new Promise('encrypted!');
    },
    decrypt(password, encryptedString) {
      return new Promise({ foo: 'bar' });
    },
  },
});

// The KeyringController is also an event emitter:
this.keyringController.on('newAccount', (address) => {
  console.log(`New account created: ${address}`);
});
this.keyringController.on('removedAccount', handleThat);

Methods

Currently the methods are heavily commented in the source code, so it's the best place to look until we aggregate it here as well.

Contributing

Setup

  • Install Node.js version 18
    • If you are using nvm (recommended) running nvm use will automatically choose the right node version for you.
  • Install Yarn v3
  • Run yarn install to install dependencies and run any required post-install scripts

Testing and Linting

Run yarn test to run the tests once.

Run yarn lint to run the linter, or run yarn lint:fix to run the linter and fix any automatically fixable issues.

Release & Publishing

The project follows the same release process as the other libraries in the MetaMask organization. The GitHub Actions action-create-release-pr and action-publish-release are used to automate the release process; see those repositories for more information about how they work.

  1. Choose a release version.

    • The release version should be chosen according to SemVer. Analyze the changes to see whether they include any breaking changes, new features, or deprecations, then choose the appropriate SemVer version. See the SemVer specification for more information.
  2. If this release is backporting changes onto a previous release, then ensure there is a major version branch for that version (e.g. 1.x for a v1 backport release).

    • The major version branch should be set to the most recent release with that major version. For example, when backporting a v1.0.2 release, you'd want to ensure there was a 1.x branch that was set to the v1.0.1 tag.
  3. Trigger the workflow_dispatch event manually for the Create Release Pull Request action to create the release PR.

    • For a backport release, the base branch should be the major version branch that you ensured existed in step 2. For a normal release, the base branch should be the main branch for that repository (which should be the default value).
    • This should trigger the action-create-release-pr workflow to create the release PR.
  4. Update the changelog to move each change entry into the appropriate change category (See here for the full list of change categories, and the correct ordering), and edit them to be more easily understood by users of the package.

    • Generally any changes that don't affect consumers of the package (e.g. lockfile changes or development environment changes) are omitted. Exceptions may be made for changes that might be of interest despite not having an effect upon the published package (e.g. major test improvements, security improvements, improved documentation, etc.).
    • Try to explain each change in terms that users of the package would understand (e.g. avoid referencing internal variables/concepts).
    • Consolidate related changes into one change entry if it makes it easier to explain.
    • Run yarn auto-changelog validate --rc to check that the changelog is correctly formatted.
  5. Review and QA the release.

    • If changes are made to the base branch, the release branch will need to be updated with these changes and review/QA will need to restart again. As such, it's probably best to avoid merging other PRs into the base branch while review is underway.
  6. Squash & Merge the release.

    • This should trigger the action-publish-release workflow to tag the final release commit and publish the release on GitHub.
  7. Publish the release on npm.

    • Wait for the publish-release GitHub Action workflow to finish. This should trigger a second job (publish-npm), which will wait for a run approval by the npm publishers team.
    • Approve the publish-npm job (or ask somebody on the npm publishers team to approve it for you).
    • Once the publish-npm job has finished, check npm to verify that it has been published.

keyringcontroller's People

Contributors

adonesky1 avatar andrepimenta avatar bergarces avatar bitpshr avatar brad-decker avatar brunobar79 avatar cryptodev-2s avatar cshung1994 avatar danfinlay avatar danjm avatar danroc avatar darkwing avatar dependabot[bot] avatar frankiebee avatar gantunesr avatar github-actions[bot] avatar gudahtt avatar jpuri avatar kumavis avatar legobeat avatar logvik avatar mikesposito avatar rekmarks avatar rickycodes avatar ryanml avatar shuoer86 avatar soralit avatar timtinkers avatar ukstv avatar whymarrh avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

keyringcontroller's Issues

Entering password causes keyring to be duplicated.

MetaMask does not currently support multiple keyrings.
Still, the keyring array can contain more than one HD keyring.

What I believe is a bug, when entering a password, the keyring does duplicate in the array, because submitPassword() calls unlockKeyrings() calls restoreKeyring() calls this.keyrings.push(), leading to duplicate keyrings.

See this scenario:

const password = 'abcd';
const keyringController = new KeyringController({
        initState: clone(firstTimeState),
        encryptor: mockEncryptor,
})

await keyringController.createNewVaultAndKeychain(password)
await keyringController.persistAllKeyrings()

// keyringController.keyrings.length = 1
await keyringController.submitPassword(password + 'a')
// keyringController.keyrings.length) = 2
await keyringController.submitPassword('')
// keyringController.keyrings.length) = 3

While I believe this currently does not cause any malfunction in MetaMask, I believe it is unintended and potentially dangerous:

  • MetaMask does only support 1 HD keyring and hardcodes it so it always shows the seed phrase for the first keyring. So there is the possibility to show the wrong seed phrase. However currently it is not the case because it's the same keyring who is duplicated.

  • This is also a memory leak and leads to higher memory usage for the user.

Call `persistAllKeyrings` in `setLocked`?

GridPlus' keyring recently added a state caching mechanism under a mistaken assumption that serialize would be called when the MetaMask extension locked. Since the Lattice is an internet-connected device with its own state, we would normally need to asynchronously connect to the device in order to sync state, which takes 2-4 seconds, depending on internet connection. With the latest changes, we can now dry state and rehydrate a connection without having to do any asynchronous calls.

However, this is dependent on they keyring controller persisting keyring state or else every time the extension locks, we will lose our most recent state data and we will need to asynchronously reconnect with a retry mechanism (which is actually slower than initially forcing asynchronous resync like we were doing before, since it adds another call that ends up failing and forcing the resync). This would not be an issue if setLocked called persistAllKeyrings to save state.

Is there any reason you do not call persistAllKeyrings in setLocked? And if the answer is no, would you be open to adding that serialization hook?

Action required: Greenkeeper could not be activated 🚨

🚨 You need to enable Continuous Integration on all branches of this repository. 🚨

To enable Greenkeeper, you need to make sure that a commit status is reported on all branches. This is required by Greenkeeper because we are using your CI build statuses to figure out when to notify you about breaking changes.

Since we did not receive a CI status on the greenkeeper/initial branch, we assume that you still need to configure it.

If you have already set up a CI for this repository, you might need to check your configuration. Make sure it will run on all new branches. If you don’t want it to run on every branch, you can whitelist branches starting with greenkeeper/.

We recommend using Travis CI, but Greenkeeper will work with every other CI service as well.

Once you have installed CI on this repository, you’ll need to re-trigger Greenkeeper’s initial Pull Request. To do this, please delete the greenkeeper/initial branch in this repository, and then remove and re-add this repository to the Greenkeeper integration’s white list on Github. You'll find this list on your repo or organization’s settings page, under Installed GitHub Apps.

Question: regarding getEncryptionPublicKey

Is the key returned by getEncryptionPublicKey intended to be the wallet public key? Or is it something else?

In other words, should this test be green:

      await keyring.deserialize([testAccount.key]);

      const encryptionPublicKeyB64 = await keyring.getEncryptionPublicKey(testAccount.address);
      const encryptionPublicKey = Buffer.from(naclUtil.decodeBase64(encryptionPublicKeyB64));
      
      const address = ethUtil.publicToAddress(encryptionPublicKey);
      const addressHex = ethUtil.bufferToHex(address);
      expect(addressHex).toBe(testAccount.address);

Migrate to TypeScript

We want to migrate this package to TypeScript to reduce regressions and improve compatibility with our other TypeScript projects.

Need to update Readme

In Readme under Installation section
yarn install eth-keyring-controller --save should be replaced with yarn add eth-keyring-controller

Question: How to fork and build this package locally to edit and use within the metamask-extension

Hello, I'm trying to fork and build this package locally to edit and use as a dependency within the metamask-extension repo. Unfortunately I've failed to do so.

I've tried linking it within the package json using yarn install <filepath> which successfully creates a link to the local module however when running yarn start on the metamask-extension repo it produces an error: TypeError: Tried to access an environmental variable "_nodeLRUCacheForceNoSymbol" that wasn't declared in builds.yml I did try adding the env like it says however it keeps asking for envs to add to builds.yml which ultimately doesn't work.

I've also tried just putting the package directly inside the metamask-extension repo and change the imports to the filepath of the local package. But this caused many dependency issues.

Is there a better way to go about this? If you have any ideas I'd love to know. Thanks.

npm i eth-keyring-controller npm ERR! code ENOSELF

npm ERR! code ENOSELF
npm ERR! Refusing to install package with name "eth-keyring-controller" under a package
npm ERR! also called "eth-keyring-controller". Did you name your project the same
npm ERR! as the dependency you're installing?
npm ERR!
npm ERR! For more information, see:
npm ERR! https://docs.npmjs.com/cli/install#limitations-of-npms-install-algorithm

npm ERR! A complete log of this run can be found in:
npm ERR! /Users/zhangyi/.npm/_logs/2018-03-29T09_50_04_581Z-debug.log

Improve vault encryption

Description

As part of the new KeyringController API, there's a need to improve the current encryption logic for the vault.

Today the user's password directly encrypts the vault, there's an improvement opportunity where the KeyringController can use an encryption key to encrypt the vault. Next is presented the specific steps for two use cases,

Use Case: Lock the vault

  1. Create or get encryption-key
  2. Encrypt vault with encryption-key
  3. Encrypt encryption-key with password

Use Case: Unlock the vault

  1. Decrypt encryption-key with password
  2. Decrypt vault with encryption-key

Acceptance Criteria

  • The encryption key must have a defined use policy
  • All new code must have tests
  • All new code must be document

Reference

Increase code coverage to 100% and enable `jest-it-up`

After the TS refactor the current code coverage is,

----------------------|---------|----------|---------|---------|----------------------------------------------------------------------------------------------
File                  | % Stmts | % Branch | % Funcs | % Lines | Uncovered Line #s                                                                            
----------------------|---------|----------|---------|---------|----------------------------------------------------------------------------------------------
All files             |   90.43 |    68.67 |   92.59 |    90.2 |                                                                                              
 KeyringController.ts |    89.3 |    67.09 |   95.83 |   89.18 | 285,305,391-397,421,449,473,493-499,522,542,562,601,606,678,761,819,825,863,891,906,939,1034 
 constants.ts         |     100 |      100 |     100 |     100 |                                                                                              
 index.ts             |     100 |      100 |      50 |     100 |                                                                                              
----------------------|---------|----------|---------|---------|----------------------------------------------------------------------------------------------

The code coverage needs to be increased to a 100% and to keep it at that level it's also needed to enable jest-it-up.

`encryptor` lacks sufficient typing

Currently, the encryptor class variable (and the corresponding constructor option) is typed with any.
As a controller client can inject its own encryptor methods, the minimum encryptor interface needed by the controller should be clear.

Moreover, the solution should take into account that:

  • MetaMask extension and mobile use different encryptors
    • MetaMask extension uses the default encryptor value, provided by KeyringController, which is @metamask/browser-passworder
    • MetaMask mobile injects its own encryptor.
  • When cacheEncryptionKey options is set to true, KeyringController needs an encryptor capable of exporting the encryption key string along with encrypted/decrypted strings. This is only needed by the extension, when using MV3
    • This means that when cacheEncryptionKey is set to true, the encryptor must implement additional methods specific for this

Two keyrings get created in an unintended way

This is another issue that I think does not lead to a bug in the end product, but I think is unintended and could potentially be dangerous when developing the extension further.

On line 160 and onwards:

const keyring = new Keyring(opts)
return keyring.deserialize(opts)
.then((accounts) => {
  return this.checkForDuplicate(type, accounts)
})

I don't know if you realize that you create a keyring assign it to a variable and then override it immediately (assuming an HD Key).

What I fear is that by accident the wrong seed phrase can be read, like this:

const keyring = new Keyring(opts)
// This seed will be overidden by the next line
const seed = keyring.mnemonic
return keyring.deserialize(opts)
.then((accounts) => {
  const seed2 = keyring.mnemonic
  // Not anymore the same as above
  // seed !== seed2
})

Why this happens is pretty obvious when reading the eth-hd-keyring source code.

It also does the unncecessary work of generating a seed, private key etc. twice.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.