Technical Reference

This guide gives an overview on common practices and technical standards shared within the EthereumJS ecosystem.

Source Code

Development Runtime

Node.js Version

Runtime environment for development is node.js.

Development should always be possible running the last two LTS Node.js versions, see Node.js release schedule table.

Node.js 8 Supported
Node.js 10 Supported

Node.js Features

TODO

Notes on Buffer, safe-buffer, stuff like that.

Node.js Best Practices

Currently agreed-upon best practices on Node.js development:

  • Do not use lock files (package-lock.json) on repositories (instead add to .gitignore), see this discussion

Programming Language

We use both JavaScript and TypeScript in our libraries, with a transition of libraries to TypeScript on the way (see: R18-1 Transition to TypeScript).

All libraries are transpiled to a lower common denominator JavaScript version (see section below), this section describes what language features are safe to be used in the non-transpiled source code of the libraries.

Main aspects to consider when choosing language version and features for the development code base are:

  • Node.js compatibility (see also: node.green Website)
  • Support by transpilation tools in-use

Note

Not all libraries have transpilation included, have a closer look along when using new language features!

JavaScript

Features supported, encouraged and discouraged from the different JavaScript versions:

Note

This table does not aim to be complete but just wants to hint to the practically most common pitfall cases!

TypeScript

TODO

Linting and Formatting

JavaScript

All EthereumJS JavaScript libraries use standard.js for code formatting and linting with no extra configuration files added or rules adopted, see the VM repository as an example.

The standard dependency in the devDependencies section of package.json should be upgraded on a regular basis. Count in some time for this, since this normally goes along with some code changes necessary through the introduction of new rules.

Linting can be triggered on the different libraries with an npm run lint command being added to package.json.

Note

For convenience a lint:fix command should be added to the various library package.json files.

TypeScript

TypeScript libraries are using TSLint for linting and Prettier for code formatting. See the RLP library for a first example (changes might still be located in TypeScript transition PR #37).

Note

It is intended to integrate both linting and formatting config into a shared ethereumjs-config library (see: ethereumjs-config), this effort is still ongoing.

Distribution

Transpilation

Current transpilation target: ES5-compatible JavaScript code

JavaScript

For JavaScript libraries, Babel is used for transpilation, probably the most up-to-date example can be found in the merkle-patricia-tree library.

Note

TODO: This section has to be expanded.

TypeScript

For TypeScript libraries, transpilation is done through the TypeScript compiler tsc command line tool.

Note

TODO: This section has to be expanded.

Browser Compatibility

TODO

Releases

Releases on libraries follow Semantic Versioning, normally releases are published on npm and as a tagged release on GitHub in the Releases section.

Every library contains a CHANGELOG.md file in the root directory, listing the changes on the respective release versions (see e.g. CHANGELOG.md of the ethereumjs-util library), the changelog entry is copied to the GitHub release section on publication of a new release.

Releases go through a PR (see example PR <https://github.com/ethereumjs/ethereumjs-util/pull/155/files> on ethereumjs-util v6.0.0 release), containing the package.json version number update, a new CHANGELOG entry and eventually some update on the docs.

Git Workflow

Branching Model

We are using a feature-centric branching model, the GitHub flow model is coming very much close.

Development of new features is taking place on a dedicated branch and should have some descriptive name for the work done (e.g. api-doc-fixes, remove-vm-accesses-to-statemanager-trie-cache, new-bloom-filter-tests).

Once work on the feature branch is completed and all tests and checks from CI (see Continuous Integration (CI)) pass it goes through a review and eventually discussion process and is afterwards merged into a protected master branch. The master branch should always be stable and theoretically ready for deployment.

Git Guidelines

Some guidelines for the EthereumJS libraries when working with Git version control:

Feature branch for all PRs

Always do your work on a separate feature branch (see Branching Model), this also applies when doing work from an own fork of a library.

This makes it easier for reviewers and others interested to test your code locally by fetching your code changes from your remote feature branch.

Separate PRs for separate Features

If you have separate things you want to change on a library, do separate PRs for this. So if you e.g. have some ideas for how to improve the build process and want to fix some bug from an issue, theses are two separate PRs.

This is a precondition for a successful review of a PR, since a reviewer has a smaller subset of changes and can connect changes undoubtfully to a certain feature. It also avoids the situation where unexpected discussions and disagreements on a certain subfeature set blocks the whole PR with all other changes.

Meaningful Commit History

Make sure that you end up with a meaningful commit history on your work:

  • Choose self-descriptive commit messages
  • Avoid inconsistent state between commits
  • If you do changes correcting your prior committed work, rebase and squash commits afterwards

Note

Rebasing can be a hairy process, if you do for the first time it is highly recommended to do a local backup of your repository.

Note

Rebase work like the above can normally be done with git rebase -i master from the feature branch with an up-to-date master branch.

Regular Master Rebase

PRs are only reviewed if the branch is up-to-date on the latest master changes. Rebase your branch often (with git rebase master) and force-push the changes, to make sure that your changes work well on top of the latest commits and tests keep passing.

Workflow Best Practices

Some best practices which turned out to be practical over time and should be followed when working on a new feature:

In doubt: Issue before PR

If you are planning on introducing major feature changes on a library file an issue and describe what you are up to before directly work on a PR. This gives others the chance to discuss around your intended changes and avoids potential further conflicts along the road.

This especially applies for stuff like:

  • Introducing new language features (Promises,…)
  • Changing the API of a library
  • Planning security-sensitive changes
  • Switch or introduce new tooling

Describe your Work

Take some time to make both the scope of your work and your work process transparent for others. This will ease both discussions and the review process around the work being done.

In particular:

  • Do a proper and complete task description on your issue or PR
  • Give some regular updates on the current status of your work
  • Especially: drop a note once you are ready

Pull Request Reviews

All PRs making changes to the production code base are going through a review process. This will normally take some time and will come along with some back-and-forth between contributor and reviewer until everyone is happy.

Code Quality

Testing

Test Framework

Most EthereumJS libaries use tape for running tests. Have a look at one of the libraries (e.g. merkle-patricia-tree) for reference.

Note

It should be examined if this is a good choice and eventually Mocha should be preferred, see e.g. this comparison.

Code Coverage

For coverage runs nyc is used. Results are passed on to the coveralls.io service for coverage reports on CI runs.

Note

If you stumble over libraries still using istanbul as a coverage runner, do an update to nyc!

Documentation

On many libraries documentation.js is used for generating an API documentation from JSDoc comments.

Beyond the following documentation should be kept up-to-date:

  • README with setup and installation instructions
  • Usage instructions, up-to-date code examples

Continuous Integration (CI)

Most EthereumJS libraries use Travis CI <https://travis-ci.org/> for CI runs on every PR submitted. Have a look at a .travis.yml file in the repository you are interested in to get an overview on what is run during the CI process.

One exception is the EthereumJS VM which is using CircleCI as a platform for performance reasons.

Security

Security aspects around the EthereumJS libraries should be taken seriously, since many of the libraries are used in production in security-sensitive environments.

Dependency Management

Dependencies are a main source for also importing security vulnerabilities on a library, so the set of dependencies on the libraries should be actively managed and regularly reviewed.

Some guidelines:

Minimal Dependencies

Every introduction of a new dependency on a library should be carefully considered and there has to be solid argument why a new dependency is necessary. This primarily applies for production but also for development dependencies. Dependencies listed in package.json should be reviewed on a regular basis if they are still necessary or could be removed.

Established and maintained Dependencies

Only (somewhat) established and actively maintained dependencies should be used on the libraries. Some indicators for a not-so-established dependency:

  • Low number of GitHub stars or a similar metric
  • No commit activity for a longer period of time
  • Low download rate on npm

Regular Dependency Updates

Dependency versions should be updated on a regular basis, this is also very welcome to be done as a first-time-contributor PR. Don’t underestimate this task though, since a dependency update almost always come along with some necessary changes on a library. It is recommended to always only do one dependency at a time, since it becomes easier to attribute if things break at some point.

Shared Library Ressources

The following libraries set up some shared infrastructure for certain purposes.

ethereumjs-testing

The ethereumjs-testing library is a proxy library for the common Ethereum Tests <https://github.com/ethereum/tests>_ consensus tests. There are additional methods for easily select a specific subset of the tests.

The common test library is integrated as a submodule and there are tagged releases (no publishing to npm due to size constraints) which can be used for running the latest tests in JavaScript libraries.

ethereumjs-common

The ethereumjs-common library provides access to chain and hardfork specific parameters as well as utilities to easier manage hardfork-specific logic within other EthereumJS libraries.

ethereumjs-config

[IN DEVELOPMENT]

The ethereumjs-config library aims to reduce redundancy on library configuration by providing a unified set of configuration options (e.g. on linting or code formatting) which can be integrated within other libraries.