Introducing rosetta-ethereum: Coinbase's Ethereum Implementation of the Rosetta API


Today, we’re excited to share rosetta-ethereum, our Ethereum Rosetta API implementation. This implementation provides support for universal balance tracking (both internal and external ETH transfers), curve-based transaction construction, and safe balance lookups.

If you work on a smart contract-based project and have been thinking about working on a Rosetta implementation, rosetta-ethereum makes a great foundation. Check out our documentation on Rosetta Modules for our recommendation on how to best integrate!

If you haven’t heard of Rosetta, you can learn more about how we’re creating a universal read/write layer for blockchains on our website:

Last month, we open sourced our Bitcoin Rosetta API implementation. You can learn more about it here:
Introducing rosetta-bitcoin: Coinbase’s Bitcoin implementation of the Rosetta API

Comprehensive Balance Tracking

The Ethereum Virtual Machine (EVM) allows smart contracts to create other smart contracts, destroy smart contracts, and transfer value to other contracts in what are known as “internal transactions”. Running a sophisticated business on top of Ethereum requires observing these types of transactions but existing tooling makes this notoriously difficult to do. As a result, many developers need to rely on third-party data providers to surface these balance changes instead of running their own nodes and extracting these balance changes themselves.

In August, this problem hit a boiling point when people started writing and tweeting about the inability to calculate the total Ethereum supply (as it is difficult to independently determine how much ETH is destroyed/burned in internal transactions):

rosetta-ethereum makes it easy for anyone to track all Ethereum balance transfers (including “internal transactions”) without relying on a third-party service or a collection of one-off scripts.

Curve-Based Transaction Construction

As with any Rosetta implementation, rosetta-ethereum makes it easy to create, sign, and broadcast transactions without maintaining a network-specific SDK or network-specific signing logic. If you can generate secp256k1 public keys and can use those keys to provide ecdsa_recovery signatures, you can create Ethereum transactions without any additional network-specific code.

You can see how we automatically test rosetta-ethereum’s ability to create valid transactions using the Rosetta Constructor DSL:

Safe Balance Lookups

eth_getBalance is commonly used to lookup the balance of any Ethereum account, however, it does not allow for specifying a block hash and block index when making a request. This makes tracking balances at tip frustrating because the balance returned may or may not have been calculated in the context of a now orphaned block. In practice, sophisticated integrators often need to trail tip by some safe “reorg depth” to ensure the balance they receive at a particular index is associated with a particular block hash.

rosetta-ethereum addresses this problem by returning the *types.BlockIdentifier where a balance was calculated using go-ethereum’s GraphQL endpoint. This means integrators can now query balances at tip with the assurance they won’t get account data from blocks they didn’t expect.

Try it Out

Enough with the talk, show me the code! This section will walk you through building rosetta-ethereum, starting rosetta-ethereum, interacting with rosetta-ethereum, and testing rosetta-ethereum. To complete the following steps, you need to be on a computer that meets the rosetta-ethereum system requirements and you must install Docker.

First, we need to download the pre-built rosetta-ethereum Docker image (saved with the tag rosetta-ethereum:latest ):

curl -sSfL | sh -s

Next, we need to start a container using our downloaded image (the container is started in detached mode):

docker run -d --rm --ulimit "nofile=100000:100000" -v "$(pwd)/ethereum-data:/data" -e "MODE=ONLINE" -e "NETWORK=TESTNET" -e "PORT=8080" -p 8080:8080 -p 30303:30303 rosetta-ethereum:latest

After starting the container, you will see an identifier printed in your terminal (that’s the Docker container ID). To view logs from this running container, you should run:

docker logs --tail 100 -f <container_id>

To make sure things are working, let’s make a cURL request for the current network status (you may need to wait a few minutes for the node to start syncing):

curl --request POST 'http://localhost:8080/network/status' \--header 'Accept: application/json' \--header 'Content-Type: application/json' \--data-raw '{ "network_identifier": { "blockchain": "Ethereum", "network": "Ropsten" }}'

Now that rosetta-ethereum is running, the fun can really begin! Next, we install rosetta-cli, our CLI tool for interacting with and testing Rosetta API implementations (this will be installed at ./bin/rosetta-cli ):

curl -sSfL | sh -s

We recommend moving this downloaded rosetta-cli binary into your bin folder so that it can be run by calling rosetta-cli instead of ./bin/rosetta-cli ). The rest of this walkthrough assumes that you’ve done this.

We also need to download the configuration files for interacting with rosetta-ethereum:

mkdir ethereum_testnet;
curl -sSfL -o ethereum_testnet/config.json;
curl -sSfL -o ethereum_testnet/bootstrap_balances.json;
curl -sSfL -o ethereum_testnet/ethereum.ros;

We can lookup the current sync status:

rosetta-cli view:networks --configuration-file ethereum_testnet/config.json

We can lookup the contents of any synced block (make sure the index you lookup is less than the index returned by the current index returned in sync status):

rosetta-cli view:block <block index> --configuration-file ethereum_testnet/config.json

We can validate the Data API endpoints using the the check:data command:

rosetta-cli check:data --configuration-file ethereum_testnet/config.json

This test will sync all blocks and confirm that the balance for each account returned by the /account/balance endpoint matches the computed balance using Rosetta operations .

Lastly, we can validate the Construction API endpoints using the check:construction command:

rosetta-cli check:construction --configuration-file ethereum_testnet/config.json

This test will create, broadcast, and confirm testnet transactions until we reach our specified exit conditions (# of successful transactions of each type). This test automatically adjusts fees based on the estimated size of the transactions it creates and returns all funds to a faucet address at the end of the test.

When you are done playing around with rosetta-ethereum, run the following command to shut it down:

docker kill --signal=2 <container_id>

Future Work

  • ERC-20 Transfer Module
  • Rosetta API /mempool/* Implementation
  • Add more methods to the /call endpoint (currently only support eth_getTransactionReceipt )

Work at Coinbase

We are actively hiring passionate developers to join the Crypto team and a developer relations lead to work on the Rosetta project. If you are interested in helping to build this common language for interacting with blockchains, Coinbase is hiring.

This website contains links to third-party websites or other content for information purposes only (“Third-Party Sites”). The Third-Party Sites are not under the control of Coinbase, Inc., and its affiliates (“Coinbase”), and Coinbase is not responsible for the content of any Third-Party Site, including without limitation any link contained in a Third-Party Site, or any changes or updates to a Third-Party Site. Coinbase is not responsible for webcasting or any other form of transmission received from any Third-Party Site. Coinbase is providing these links to you only as a convenience, and the inclusion of any link does not imply endorsement, approval or recommendation by Coinbase of the site or any association with its operators.

All images provided herein are by Coinbase.