Git Product home page Git Product logo

snaps's Introduction

snaps's People

Contributors

bentobox19 avatar bowensanders avatar danroc avatar david0xd avatar dependabot[bot] avatar eligioo avatar elli610 avatar forcedebug avatar frederikbolding avatar github-actions[bot] avatar gudahtt avatar guillaumerx avatar hmalik88 avatar kumavis avatar legobeat avatar mario-christopher avatar matthewwalsh0 avatar metamaskbot avatar montoya avatar mpetrunic avatar mrtenz avatar rekmarks avatar rickycodes avatar ritave avatar shanejonas avatar vid201 avatar weizman avatar witmicko avatar x86nop avatar ziad-saab 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  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

snaps's Issues

Refactor Snap RPC message handling

#105 introduces a change where a new function is instantiated whenever an RPC request is received for a Snap. To avoid this, we should replace getRpcMessageHandler with a new method, handleRpcMessageFor, that accepts the RPC request object, gets the RPC message handler from the execution environment service (erroring if it's not found), performs any bookkeeping we want to do, and returns the result of the handler function.

Add ability to enable / disable snaps

Snaps should have a boolean state property called enabled. This indicates whether the snap is allowed to be started. We plan to allow users to toggle this state via snap settings in the UI, and potentially set snaps that crash repeatedly to disabled.

Make compatible with Windows

snaps-cli should be compatible with Windows. This is mostly of ensuring that it can handle both the Windows and *nix filesystems. Currently, paths are hardcoded to assume a Unix platform.

Monitor snap busy and idle time

Per #56, we need to monitor snap busy and idle time. A snap is busy if it's processing a request, and idle if it's not. A snap is "processing a request" during the interval between receiving a request and responding to it.

Standardize snap-related errors

We should standardize all common snap-related errors. This means that we should choose error codes and standard messages, and probably add them to our eth-rpc-errors library. If we can reuse existing error standards, we should do so.

Before we start an implementation, a proposal should be drafted (in written form, anywhere) of the different kinds of errors that exist and what error codes and messages they should have.

Implement Flask v1 Snap permissions

Includes the permission to:

  • #107
  • #108
  • #109
    • i.e. get some key in localStorage
    • Unencrypted for MVP
    • Data stored as string, limited by length
  • #110
    • i.e. use window.fetch
    • In the future: limit by origin
    • This requires changes to the execution environment packages so that we can programmatically include / exclude the window.fetch global.

These should be implemented as restricted methods in @mm-snap/rpc-methods.

Refactor proposal: Make an object to represent a single snap

The SnapsController (and execution environment services) has a series of maps that each point to the snaps that it manages.

This means when we want to do things like unregister event listeners, we end up going down each of these maps, and unsetting them, and in general it means that data that really is per-snap is sprawled across the code that applies to the entire snap controller.

I think there is a cleanup/refactor we could do where we create a Snap class that represents a single initialized snap. This would allow us to keep initialization and teardown steps very neatly isolated to the object being handled, and makes it easier to make further changes to our model (for example, if we decide to initialize a snap per persona).

This isn't urgent, but it's a refactor that I've consistently found myself wanting.

Handle non-terminal errors from plugins

We should handle non-terminal errors from plugins, i.e. errors that bubble up to the parent realm but do not stop the plugin from executing, for example errors thrown in a setTimeout handler.

These errors should be logged such that they can be reported to plugin developers.

Handle errors thrown by Compartment.evaluate

We should handle errors from the plugin that are re-thrown by Compartment.evaluate. These errors will always stop plugin execution, and single-plugin workers should be terminated when they occur.

Implement ephemeral lifecycle for Flask v1

TODO

Future TODO

Specification

  • Under normal circumstances, MetaMask will never terminate a snap while it's processing a request, before the processing time limit has expired.
    • The processing time in v1 of the MVP will be on the order of 30-60 seconds.
  • MetaMask may terminate a snap immediately after the processing time limit has expired, or once processing has completed, which we define as when MetaMask observes the snap sending a response to a particular request.
  • Under abnormal circumstances, MetaMask may be forced to terminate a snap while it's processing a request, but will only do so if absolutely necessary.
    • Such circumstances include:
      • If the snap is consuming too many resources, where the threshold for "too many" may vary with the number of snaps running concurrently, and other factors.
      • If the snap "hangs" and its worker becomes unresponsive.
      • If the user force-quits the snap.
  • Regardless of when and how a snap is terminated, it should gracefully start back up.
    • If a snap's state becomes so corrupted that it cannot be restarted, the user may have limited options for resolving the matter, short of reinstalling the snap.

Terminate idle and/or misbehaving snaps

Per #56 and #62, we should continually monitor running snaps, and terminate them when:

  • they've been idle for a certain period of time (pulling a number out of a hat, on the order of 2 < 10 minutes)
  • they and/or their workers aren't responding to health checks for a certain period of time (on the order of 5 - 10 seconds)

Migrate packages to MetaMask npm org

After the MVP, we should either migrate the packages in this repo to the MetaMask npm org (as their own packages or as part of existing ones), or delete them:

  • @mm-snaps/controllers: #12
  • @mm-snaps/post-message-stream
  • @mm-snaps/workers
    • Make compatible with above WebWorkerController changes.
  • @mm-snaps/rpc-methods
    • We can't do anything with this until after the controllers have been migrated. It may serve as a useful point of reference for the methods that the controllers will need to provide.
    • It should probably continue to be its own package.
  • @mm-snaps/types
    • Determine whether this package makes sense after everything else is migrated or if we should just get rid of it.

snap-controllers: Create abstract Execution Environment Service base class

There is a lot of duplication in code between the WebWorkerExecutionEnvironmentService and IframeExecutionEnvironmentService classes. We should create a single, abstract base class and move all duplicated code into it. In addition, we may want to consider changing ExecutionEnvironmentService to ExecutionService for brevity.

Refactor @mm-snaps/controllers

  • @mm-snaps/controllers
    • All controllers should be migrated to the v2 BaseController and moved to @metamask/controllers. (This is a longer-term item.)
    • PluginController
      • Define a generic, asynchronous interface for communicating with snaps/plugins.
      • Make completely agnostic of the snaps execution environment.
        • It currently assumes that plugins are executed in dedicated web workers.
    • WebWorkerController
      • Support the generic snaps communication interface mentioned above.
      • Replace internal CommandEngine module with json-rpc-engine.

Specify Execution Environment JSON-RPC API in OpenRPC

There is a set of JSON-RPC methods that we expect every conceivable execution environment to implement. This includes:

  • executePlugin, formerly known as installPlugin, for executing plugin source code
  • handshake, formerly known as ping, for confirming that a connection has been established with the worker
  • pluginRpc, for routing RPC messages to a plugin running in the execution environment

Implement snaps debugger using the iframe execution environment

The iframe execution environment enables us to create an outstanding debugging environment for snaps by integrating said environment with the OpenRPC toolchain. In its most basic form, it enables us to test if a snap will execute in SES, and whether its JSON-RPC API is working. In this form, the snap won't have access to the API MetaMask exposes to snaps in production, and we may have to stub those methods. However, with some additional work, we can actually add snaps to MetaMask and execute them inside an iframe created by the OpenRPC inspector playground.

  • Implement iframe execution environment OpenRPC inspector transport
  • Do one or none of the following
    • Create a mock MetaMask snaps provider to pass to plugins executing in the OpenRPC inspector
    • Wire up the OpenRPC inspector as an actual execution environment that can be used for snaps added to MetaMask

Work on the execution environment itself is tracked in #24.

Add Snap request processing queue

Once we have established a configurable Snap concurrency limit (#59), we should implement a queue for JSON-RPC requests for snaps that are stopped. As running snaps are stopped and concurrency "slots" (we have yet to pick a word for this) become available, snaps with queued requests should be started in a FIFO manner, and receive all of their requests once booted.

Auto generate permissions requests from static analysis

Builds on #78:

Once we can generate a list of required globals by closing #78, we have two additional ways we can act:

  • Warn the developer about globals that are strictly prohibited, suggesting strategies of refining their dependency graph around that API.
  • Offer to automatically add this API to the requested permissions object (if it isn't already added to this object).

These can be interactive prompts from the build command, and if done right, would result in a perfectly working, consent-requesting plugin right out of the build, regardless of the authority that the dependency tree required.

Add warnings at build about access to globals

The same way we see is done in lava-moat examples, the lavamoat tool uses tofu, which can generate a file that emits every global variable that a module obviously requires to operate.

Many snap developers have found themselves hitting points where a module would not fully operate under SES because of some deeply-hidden setTimeout or Uint8Array in one of their dependencies.

We could add a tofu pre-process to the build step, and proactively warn developers when a module had some global requirement, and link to a blog post demonstrating how to do it.

For example:

Ref: MetaMask/snaps-cli#46

Rate-limit requests to snaps

Dapps should be rate-limited in terms of the number of requests they can send to a snap. We may need to arrive at this number experimentally. Our RPC stack should support rate-limiting.

Try out agoric's bundle-source and import-bundle

As part of endo, agoric is developing bundle-source and import-bundle, which is intended to do a lot of what our Snaps bundle format is doing, but preserves much better debugging (like preserving line numbers).

We are unsure if these tools will work (and expect they have some issues in them!), and so Agoric requests that we try them out, and let them know what issues (if any) we hit.

They recommend we:

  • Copy these packages to the endo org from the agoric-sdk monorepo
  • Try to generalize them for our purposes
  • Finalize their interfaces

Add configurable Snap request processing time limit

Per #56, we need to be able to monitor snap request processing times and terminate non-compliant snaps. This should be implemented as a configurable request processing time limit in the PluginController. The implementation should rely on setTimeout and Promise.race for each incoming JSON-RPC request.

Add ControllerMessenger events and actions to SnapController

The SnapController should use ControllerMessenger events and actions to their full effect. Currently, it doesn't define any actions or events in addition to stateChange.

This is a refactoring ticket that we should undertake after the permissions controller changes are landed.

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.