Git Product home page Git Product logo

ethereum-client-binaries's Introduction

Archival Notice

This repository is an archive. Please see https://ethereum.org/ and specifically the https://ethereum.org/en/developers/docs/nodes-and-clients/ for actual information on clients.

Original README.md

ethereum-client-binaries

Build Status NPM module

Download Ethereum client binaries for your OS.

When you wish to run a local Ethereum client node it would be beneficial to first scan for existing node client binaries on the machine and then download appropriate client binaries if none found. This package does both.

It is structured so that it can be optionally be used in conjunction with a UI, e.g. if one wishes to allow a user to select the client software they wish to download.

Features:

  • Configurable client types (Geth, Eth, Parity, etc)
  • Security: Binary sanity checks, URL regex checks, SHA256 hash checks
  • Can scan and download to specific folders
  • Logging can be toggled on/off at runtime
  • Can be integrated into Electron.js apps

Installation

npm install --save ethereum-client-binaries

Usage

Config object

First a config object needs to be defined. This specifies the possible clients and the platforms they support.

For example, a config object which specifies the Geth client for only 64-bit Linux platforms and the Parity client for only 32-bit Windows platforms might be:

const config = {
  "clients": {
    "Geth": {
      "platforms": {
        "linux": {
          "x64": {
            "download": {
              "url": "https://geth.com/latest.tgz",
              "type": "tar",
              "bin": "geth-linux-x64",
              "sha256": "8359e8e647b168dbd053ec56438ab4cea8d76bd5153d681d001c5ce1a390401c",
            },
            "bin": "geth",
            "commands": {
              "sanity": {
                "args": ["version"],
                "output": [ "Geth", "1.4.12" ]
              }                
            }
          },
        }
      }
    },
    "Parity": {
      "platforms": {
        "win": {
          "ia32": {
            "download": {
              "url": "https://parity.com/latest.zip",
              "type": "zip"
            },
            "bin": "parity",
            "commands": {
              "sanity": {
                "args": ["version"],
                "output": [ "Parity", "11.0" ]
              }                
            }
          },
        }
      }      
    }
  }
}

Every client must specify one or more platforms, each of which must specify one or more architectures. Supported platforms are as documented for Node's process.platform except that mac is used instead of darwin and win is used instead of win32. Supported architectures are as documented for Node's process.arch.

Each platform-arch entry needs to specify a bin key which holds the name of the executable on the system, a download key which holds info on where the binary can be downloaded from if needed, and a commands key which holds information on different kinds of commands that can be run against the binary.

The download key holds the download url, the type of archive being downloaded, and - optionally - the filename of the binary (bin) inside the archive in case it differs from the expected filename of the binary. As a security measure, a sha256 key equalling the SHA256 hash calculation of the downloadable file may be provided, in which the downloaded file's hash is tested for equality with this value.

The sanity command is mandatory and is a way to check a found binary to ensure that is is actually a valid client binary and not something else. In the above config the sanity command denotes that running geth version should return output containing both Geth and 1.4.12.

Now we can construct a Manager with this config:

const Manager = require('ethereum-client-binaries').Manager;

// construct
const mgr =  new Manager(config);

Note: If no config is provided then the default config (src/config.json) gets used.

Scanning for binaries

Initialising a manager tells it to scan the system for available binaries:

// initialise (scan for existing binaries on system)
mgr.init()
.then(() => {
  console.log( 'Client config: ', mgr.clients );
})
.catch(process.exit);

Let's say the current platform is linux with an x64 architecture, and that geth has been resolved successfully to /usr/local/bin/geth, the mgr.clients property will look like:

/*
[
  {
    id: 'Geth',
    state: {
      available: true,
    },
    platforms: { .... same as original ... }
    activeCli: {
      "download": {
        "url": "https://geth.com/latest.tgz",
        "type": "tar"
      },
      "bin": "geth",
      "commands": {
        "sanity": {
          "args": ["version"],
          "output": [ "Geth", "1.4.12" ]
        }                
      },
      fullPath: '/usr/local/bin/geth'
    }
  }
]
*/

The state.available property is the key property to check. If false then state.failReason will also be set. There are currently two possible values for state.failReason:

  1. notFound - a binary with matching name (geth in above example) could not be found.
  2. sanityCheckFail - a binary with matching name was found, but it failed the sanity check when executed.

The activeCli.fullPath property denotes the full path to the resolved client binary - this is only valid if state.available is true.

NOTE: The Parity client isn't present in mgr.clients shown above because there is no linux-x64 entry specified in the Parity config shown earlier. Thus, only possible clients (as per the original config) will be present in mgr.clients.

Scan additional folders

By default the manager only scan the system PATH for available binaries, i.e. it doesn't do a full-disk scan. You can specify additional folders to scan using the folders option:

mgr.init({
  folders: [
    '/path/to/my/folder/1',
    '/path/to/my/folder/2'
  ]
})
.then(...)
.catch(...)

This features is useful if you have previously downloaded the client binaries elsewhere or you already know that client binaries will be located within specific folders.

Download client binaries

Client binaries can be downloaded whether already available on the system or not. The downloading mechanism supports downloading and unpacking ZIP and TAR files.

The initial config object specifies where a package can be downloaded from, e.g:

"download": {
  "url": "https://geth.com/latest.tgz",
  "type": "tar"
},

To perform the download, specify the client id:

mgr.download("Geth")
.then(console.log)
.catch(console.error);

The returned result will be an object which looks like:

{
  downloadFolder: /* where archive got downloaded */,
  downloadFile: /* the downloaded archive file */,
  unpackFolder: /* folder archive was unpacked to */,
  client: {
    id: 'Geth',
    state: {...},
    platforms: {...},
    activeCli: {...},
  }
}

The client entry in the returned info will be the same as is present for the given client within the mgr.clients property (see above).

After downloading and unpacking the client binary the sanity check is run against it to check that it is indeed the required binary, which means that the client's state.available and state.failReason keys will be updated with the results.

Download to specific folder

By default the client binary archive will be downloaded to a temporarily created folder. But you can override this using the downloadFolder option:

mgr.download("Geth", {
  downloadFolder: '/path/to/my/folder'
})
.then(...)
.catch(...)

If download and unpacking is successful the returned object will look something like:

{
  downloadFolder: '/path/to/my/folder',
  downloadFile: '/path/to/my/folder/archive.tgz',
  unpackFolder: '/path/to/my/folder/unpacked',
}

The next time you initialise the manager you can pass in /path/to/my/folder/unpacked as an additional folder to scan for binaries in:

mgr.init({
  folders: [
    `/path/to/my/folder/unpacked`
  ]
});

URL regular expression (regex) check

Even though you can check the SHA 256 hash of the downloaded package (as shown above) you may additionally wish to ensure that the download URL points to a domain you control. This is important if for example you are obtaining the initial JSON config object from a remote server.

This is how you use it:

mgr.download("Geth", {
  urlRegex: /^https:\/\/ethereum.org\/.+$/
})
.then(...)
.catch(...)

The above regex states that ONLY download URLs beginning with https://ethereum.org/ are valid and allowed.

### Logging

By default internal logging is silent. But you can turn on logging at any time by setting the logger property:

mgr.logger = console;    /* log everything to console */

The supplied logger object must have 3 methods: info, warn and error. If any one of these methods isn't provided then the built-in method (i.e. silent method) get used. For example:

// let's output only the error messages
mgr.logger = {
  error: console.error.bind(console)
}

Development

To build and run the tests:

$ npm install
$ npm test

Contributions

Contributions welcome - see CONTRIBUTING.md

License

MIT - see LICENSE.md

ethereum-client-binaries's People

Contributors

aldekein avatar evertonfraga avatar frozeman avatar hiddentao avatar luclu 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

Watchers

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

ethereum-client-binaries's Issues

The Travis build badge says "build unknown"

It's imperative that tests are running for this module. Please setup a Travis build for this (the .travis.yml file is already present) and then update the badge in the README.

ClientBinaryManager not resolve with ethereumwallet

[2018-06-06T18:49:52.344] [INFO] ClientBinaryManager - Initializing...
[2018-06-06T18:49:52.346] [INFO] ClientBinaryManager - Checking for new client binaries config from: https://raw.githubusercontent.com/ethereum/mist/master/clientBinaries.json
[2018-06-06T18:49:52.733] [INFO] updateChecker - App is up-to-date.
[2018-06-06T18:49:52.930] [INFO] ClientBinaryManager - No "skippedNodeVersion.json" found.
[2018-06-06T18:49:52.931] [INFO] ClientBinaryManager - Initializing...
[2018-06-06T18:49:52.931] [INFO] ClientBinaryManager - Resolving platform...
[2018-06-06T18:49:52.932] [INFO] ClientBinaryManager - Calculating possible clients...
[2018-06-06T18:49:52.933] [INFO] ClientBinaryManager - 1 possible clients.
[2018-06-06T18:49:52.934] [INFO] ClientBinaryManager - Verifying status of all 1 possible clients...
[2018-06-06T18:49:52.935] [INFO] ClientBinaryManager - Verify Geth status ...
[2018-06-06T18:49:52.947] [ERROR] ClientBinaryManager - Unable to resolve Geth executable: geth
[2018-06-06T18:49:52.950] [INFO] ClientBinaryManager - Download binary for Geth ...

There is the file, geth. What is a problem, md5 checksum or what?

$ geth version
Geth
Version: 1.8.10-stable
Git Commit: eae63c511ceafab14b92e274c1b18bf1700e2d3d
Architecture: amd64
Protocol Versions: [63 62]
Network Id: 1
Go Version: go1.10
Operating System: linux
$ which geth
/usr/bin/geth

I tried this one.

$ ./ethereumwallet --node "geth" --gethpath "/usr/bin/geth" --network "private" --node-rpc-port 8549 --node-network 19 --node-datadir "./private-data"

"npm test" failed

user@user-VirtualBox:~/ethereum-client-binaries$ npm test

> [email protected] test /home/user/ethereum-client-binaries
> mocha --timeout 180000 --ui exports --reporter spec test/*.test.js



 checkAvailability.test.js
   tests
     ✓ no clients
     ✓ client not supported on architecture
     ✓ client not supported on platform
     ✓ unable to resolve binary
     1) sanity check failed
     2) sanity check passed
     3) sanity check is mandatory
     4) client config returned
     ✓ search additional folders

 config.test.js
   tests
     ✓ DefaultConfig
     ✓ no config given
     ✓ config override

 download.test.js
   tests
      ✓ no clients
     ✓ client not supported on architecture
     ✓ client not supported on platform
     ✓ download info not available
     ✓ download url not available
     ✓ download unpack command not available
     ✓ download fails
     ✓ unsupported archive type
     ✓ hash sha256 mismatch
     ✓ hash md5 mismatch
     ✓ url regex mismatch
     ✓ unpacks and verifies ok
     ✓ unpacked but no binary found
     ✓ unpacked but sanity check failed
     ✓ unpacked and set to required name
     ✓ unpacked updated version and copied over old version
     ✓ hash sha256 match
     ✓ hash md5 match
     custom unpack handler
       ✓ success
       ✓ fail

 logger.test.js
   tests
     ✓ nothing by default
test logging
     ✓ turn on and off
     ✓ must be valid logger


 31 passing (2s)
 4 failing

 1) checkAvailability.test.js tests sanity check failed:

     AssertionError: expected 'notFound' to deeply equal 'sanityCheckFail'
     + expected - actual

     -notFound
     +sanityCheckFail

     at Context.test.sanity check failed (test/checkAvailability.test.js:153:34                                                                                                                                                                                               )
     at test.sanity check failed.next (<anonymous>)
     at onFulfilled (node_modules/co/index.js:65:19)
     at <anonymous>
     at process._tickCallback (internal/process/next_tick.js:188:7)

 2) checkAvailability.test.js tests sanity check passed:
    AssertionError: expected false to be true
     at Context.test.sanity check passed (test/checkAvailability.test.js:188:36                                                                                                                                                                                               )
     at test.sanity check passed.next (<anonymous>)
     at onFulfilled (node_modules/co/index.js:65:19)
     at <anonymous>
     at process._tickCallback (internal/process/next_tick.js:188:7)

 3) checkAvailability.test.js tests sanity check is mandatory:

     AssertionError: expected 'notFound' to deeply equal 'sanityCheckFail'
     + expected - actual

     -notFound
     +sanityCheckFail

     at Context.test.sanity check is mandatory (test/checkAvailability.test.js:                                                                                                                                                                                               219:34)
     at test.sanity check is mandatory.next (<anonymous>)
     at onFulfilled (node_modules/co/index.js:65:19)
     at <anonymous>
     at process._tickCallback (internal/process/next_tick.js:188:7)

 4) checkAvailability.test.js tests client config returned:

     AssertionError: expected { Object (homepage, version, ...) } to deeply equ                                                                                                                                                                                               al { Object (homepage, version, ...) }
     + expected - actual

                "good:test"
              ]
            }
          }
     +    "fullPath": "/home/user/ethereum-client-binaries/test/bin/maga"
          "url": "http://badgerbadgerbadger.com"
        }
        "foo": "bar"
        "homepage": "http://badgerbadgerbadger.com"
            }
          }
        }
        "state": {
     -    "available": false
     -    "failReason": "notFound"
     +    "available": true
        }
        "version": "1.0.0"
        "versionNotes": "http://badgerbadgerbadger.com"
      }

     at Context.test.client config returned (test/checkAvailability.test.js:255                                                                                                                                                                                               :17)
     at test.client config returned.next (<anonymous>)
     at onFulfilled (node_modules/co/index.js:65:19)
     at <anonymous>
     at process._tickCallback (internal/process/next_tick.js:188:7)



npm ERR! Test failed.  See above for more details.

Any Ideas?

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.