ethereumjs-client v0.0.6
SYNOPSIS
This is the work repository for the EthereumJS client project targetting both Node.js and the browser as a platform.
See Technical Guidelines if you directly want to dive into development info.
Current development stage: EARLY DEVELOPMENT
PROJECT SUMMARY
Project summary from this document is currently outdated. Please refer to our communication channels for some information on the current state of client development.
TECHNICAL GUIDELINES
Client Setup
Installing the Client
npm install ethereumjs-clientFor the ethereumjs CLI command to work run:
npm linkNote: you can also fallback to invoking the client by using ./bin/cli.js.
Running the Client
Some building blocks for the client have already been implemented or outlined to further build upon.
You can run the current state of the client with:
ethereumjs --network=mainnet [--loglevel=debug]For development you might want to connect to rinkeby as the network with the currently
most reliable connection:
ethereumjs --network rinkebyThe help can be shown with:
ethereumjs --helpIf you want to have verbose logging output for the p2p communication you can use...
DEBUG=*,-babel [CLIENT_START_COMMAND]for all output or something more targeted by listing the loggers like
DEBUG=devp2p:rlpx,devp2p:eth,-babel [CLIENT_START_COMMAND]API
See also this diagram for an overview of the client structure with the initialization and message flow.
JSON-RPC
Overview
You can expose a JSON-RPC interface along a client run with:
ethereumjs --rpcTo run just the server without syncing:
ethereumjs --rpc --maxPeers=0Currently only a small subset of RPC methods are implemented.(*) You can have a look at the
./lib/rpc/modules/ source folder or the tracking issue
#17 for an overview.
() Side note: implementing RPC methods is actually an extremely thankful task for a first-time contribution on the project hint* hint. 😄
API Examples
You can use cURL to request data from an API endpoint. Here is a simple example for
web3_clientVersion:
curl -X POST -H "Content-Type: application/json" --data '{"jsonrpc":"2.0","id":1,"method":"web3_clientVersion", "params": []}' http://localhost:8545Note that "params": [] can also be omitted in this case.
Or - somewhat more convenient and with formatted output - with a tool like httpie:
http POST http://localhost:8545 jsonrpc=2.0 id=1 method=web3_clientVersion params:=[]Note the := separator for the params parameter to
indicate raw JSON as an input.
This will give you an output like the following:
{
"id": "1",
"jsonrpc": "2.0",
"result": "EthereumJS/0.0.5/darwin/node12.15.0"
}Here an example for a call on an endpoint with the need for parameters. The following call uses
the eth_getBlockByNumer endpoint
to request data for block number 436 (you can use an tool like
RapidTables for conversion to hex):
curl -X POST -H "Content-Type: application/json" --data '{"jsonrpc":"2.0","method":"eth_getBlockByNumber","params":["0x1b4", true],"id":1}' http://127.0.0.1:8545Same with httpie:
http POST http://localhost:8545 jsonrpc=2.0 id=1 method=eth_getBlockByNumber params:='["0x1b4",true]'Output:
{
"id": "1",
"jsonrpc": "2.0",
"result": {
"header": {
"bloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
"coinbase": "0xbb7b8287f3f0a933474a79eae42cbca977791171",
"difficulty": "0x04ea3f27bc",
"extraData": "0x476574682f4c5649562f76312e302e302f6c696e75782f676f312e342e32",
"gasLimit": "0x1388",
"gasUsed": "0x",
"mixHash": "0x4fffe9ae21f1c9e15207b1f472d5bbdd68c9595d461666602f2be20daf5e7843",
"nonce": "0x689056015818adbe",
"number": "0x01b4",
"parentHash": "0xe99e022112df268087ea7eafaf4790497fd21dbeeb6bd7a1721df161a6657a54",
"receiptTrie": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
"stateRoot": "0xddc8b0234c2e0cad087c8b389aa7ef01f7d79b2570bccb77ce48648aa61c904d",
"timestamp": "0x55ba467c",
"transactionsTrie": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
"uncleHash": "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347"
},
"transactions": [],
"uncleHeaders": []
}
}EXAMPLES
Example 1: Light sync
In this example, we will run two ethereumjs-clients. The first will be a fast sync client that will connect to the rinkeby network and start downloading the blockchain. The second will be a light client that connects to the first client and syncs headers as they are downloaded.
The first client will use RLPx to connect to the rinkeby network, but will also provide a libp2p listener. The second client will use libp2p to connect to the first client.
Run the first client and start downloading blocks:
ethereumjs --syncmode fast --lightserv true --datadir first --network rinkeby --transports rlpx libp2p:multiaddrs=/ip4/127.0.0.1/tcp/50505/wsOutput:
Copy the libp2p URL from the output. In this example, the url is /ip4/127.0.0.1/tcp/50505/ws/ipfs/QmYAuYxw6QX1x5aafs6g3bUrPbMDifP5pDun3N9zbVLpEa but it will be different in your case.
Wait until a few thousand blocks are downloaded and then run the second client in a new terminal, using the url above to connect to the first client:
Notice that we have to run the second client on port 50506 using the multiaddrs=/ip4/0.0.0.0/tcp/50506 libp2p option to avoid port conflicts.
Example 2: Light sync from within a browser
In this example, we will again perform a light sync by connecting to the first client from above. However, this time we will connect directly to the first client from within a browser window using libp2p websockets.
First, let's set up the browserify bundle:
git clone https://github.com/ethereumjs/ethereumjs-client
cd ethereumjs-client
npm i
npm run buildThis will create a new file (dist/bundle.js) in your source tree. Now, we will create an index.html file that loads dist/bundle.js and then serves it up on http://localhost:8080.
echo '<script src="/dist/bundle.js"></script>' > index.html
npm i -g http-server
http-serverNow, open a new browser window and navigate to http://localhost:8080. Open the developer console in your browser and run the following command to start syncing to the first client. Again, remember to change the value of bootnodes to match the url of the first client from above:
ethereumjs.run({ network: 'rinkeby', syncmode: 'light', bootnodes: '/ip4/127.0.0.1/tcp/50505/ws/ipfs/QmYAuYxw6QX1x5aafs6g3bUrPbMDifP5pDun3N9zbVLpEa' })That's it! Now, you should start seeing headers being downloaded to the local storage of your browser. Since IndexDB is being used, even if you close and re-open the browser window, the headers you'll already downloaded will be saved.

Design
Goals
Contributors should aim to achieve the following goals when making design decisions:
- Loosely coupled components: Components should require as little knowledge of the definitions of other components as possible. This reduces dependencies between PRs and encourages contributors to work in parallel. It also improves extensibility of the code as new features like sharding and libp2p support are added.
- Easily tested: The design should make testing of individual components as easy as possible. This goes hand in hand with the previous goal of loose coupling.
- Readable code: More readable code should encourage more contributions from the community and help with bug fixing.
- Well documented: Similar to above, this will help both contributors and users of the project.
The current design tries to achieves the goals of loose coupling and ease of testing by using an event-driven architecture where possible. Readability is improved by using features of JavaScript ES6 such as classes, async/await, promises, arrow functions, for...of, template literals and destructuring assignment among others. Shorter names are used when possible and long functions are broken up into smaller helpers, along with JSDoc annotations for most methods and parameters. Documentation is auto-generated from JSDoc comments and many examples of usage are provided (TO DO).
We will now briefly describe the directory structure and main components of the Ethereumjs client to help contributors better understand how the project is organized.
Directory structure
/binContains the CLI script for theethereumjscommand/docsContains auto-generated API docs as well as other supporting documentation/lib/blockchainContains theChainclass./lib/netContains all of the network layer classes includingPeer,Protocoland its subclasses,Serverand its subclasses, andPeerPool./lib/serviceContains the main Ethereum services (FastEthereumServiceandLightEthereumService)/lib/rpcContains the RPC server (optionally) embedded in the client./lib/syncContains the various chain synchronizers andFetcherhelpers./testsContains test cases, testing helper functions, mocks and test data
Components
ChainIn Progress This class represents the blockchain and is a wrapper aroundethereumjs-blockchain. It handles creation of the data directory, provides basic blockchain operations and maintains an updated current state of the blockchain, including current height, total difficulty, and latest block.ServerThis class represents a server that discovers new peers and handles incoming and dropped connections. When a new peer connects, theServerclass will negotiate protocols and emit aconnectedevent with a newPeerinstance. The peer will have properties corresponding to each protocol. For example, if a new peer understands theethprotocol, it will contain anethproperty that provides allethprotocol methods (for example:peer.eth.getBlockHeaders()) -RlpxServerIn Progress Subclass ofServerthat implements thedevp2p/rlpxtransport. -Libp2pServerIn Progress Subclass ofServerthat implements thelibp2ptransport.PeerRepresents a network peer. Instances ofPeerare generated by theServersubclasses and contain instances of supported protocol classes as properties. Instances ofPeersubclasses can also be used to directly connect to other nodes via theconnect()method. Peers emitmessageevents whenever a new message is received using any of the supported protocols. -RlpxPeerIn Progress Subclass ofPeerthat implements thedevp2p/rlpxtransport. -Libp2pPeerIn Progress Subclass ofPeerthat implements thelibp2ptransport.ProtocolIn Progress This class and subclasses provide a user-friendly wrapper around the low level ethereum protocols such aseth/62,eth/63andles/2. Subclasses must define the messages provided by the protocol. -EthProtocolIn Progress Implements theeth/62andeth/63protocols. -LesProtocolIn Progress Implements theles/2protocol. -ShhProtocolNot Started Implements the whisper protocol.PeerPoolIn Progress Represents a pool of network peers.PeerPoolinstances emitaddedandremovedevents when new peers are added and removed and also emit themessageevent whenever any of the peers in the pool emit a message. EachServicehas an associatedPeerPooland they are used primarily bySynchronizers to help with blockchain synchronization.SynchronizerSubclasses of this class implements a specific blockchain synchronization strategy. They also make use of subclasses of theFetcherclass that help fetch headers and bodies from pool peers. The fetchers internally make use of streams to handle things like queuing and backpressure. -FastSynchronizerIn Progress Implements fast syncing of the blockchain -LightSynchronizerIn Progress Implements light syncing of the blockchainHandlerSubclasses of this class implements a protocol message handler. Handlers respond to incoming requests from peers.EthHandlerIn Progress Handles incoming ETH requestsLesHandlerIn Progress Handles incoming LES requests
ServiceSubclasses ofServicewill implement specific functionality of aNode. For example, theEthereumServicesubclasses will synchronize the blockchain using the fast or light sync protocols. Each service must specify which protocols it needs and define astart()andstop()function.FastEthereumServiceIn Progress Implementation of ethereum fast sync.LightEthereumServiceIn Progress Implementation of ethereum light sync.WhisperServiceNot Started Implementation of an ethereum whisper node.
NodeIn Progress Represents the top-level ethereum node, and is responsible for managing the lifecycle of included services.RPCManagerIn Progress Implements an embedded JSON-RPC server to handle incoming RPC requests.
Developer
Diagram Updates
To update the structure diagram files in the root folder open the client.drawio file in draw.io, make your changes, and open a PR with the updated files. Export svg and png with border width=20 and transparency=false. For png go to "Advanced" and select 300 DPI.
Environment / Ecosystem
EthereumJS Ecosystem
This project will be embedded in the EthereumJS ecosystem and many submodules already exist and can be used within the project, have a look e.g. at ethereumjs-block, ethereumjs-vm, the merkle-patricia-tree or the ethereumjs-devp2p implementation. Work needs to be done both within this repos and related libraries.
Related issues are labelled with the ethereumjs-client label, see here for an org-wide search.
EthereumJS
See our organizational documentation for an introduction to EthereumJS as well as information on current standards and best practices.
If you want to join for work or do improvements on the libraries have a look at our contribution guidelines.