1. Introduction
In this article, we take a look at the EthereumJ library that allows us to interact with the Ethereum blockchain, using Java.
First, let’s just briefly dive into what this technology is all about.
Note that this tutorial uses the EthereumJ, which is now deprecated. As a result, the supporting code shown here is no longer maintained.
2. About Ethereum
Ethereum is a cryptocurrency leveraging a distributed, peer-to-peer, database in the form of a programmable blockchain, the Ethereum Virtual Machine (EVM). It’s synchronized and operated through disparate but connected nodes.
As of 2017, Nodes synchronize the blockchain through consensus, create coins through mining (proof of work), verify transactions, execute smart contracts written in Solidity, and run the EVM.
The blockchain is divided into blocks which contain account states (including transactions between accounts) and proof of work.
3. The Ethereum Facade
The org.ethereum.facade.Ethereum class abstracts and unites many packages of EthereumJ into one easy to use interface.
It’s possible to connect to a node to sync with the overall network and, once connected, we can work with the blockchain.
Creating a facade object is as easy as:
Ethereum ethereum = EthereumFactory.createEthereum();
4. Connecting to the Ethereum Network
To connect to the network, we must first connect to a node*, i.e.* a server running the official client. Nodes are represented by the org.ethereum.net.rlpx.Node class.
The org.ethereum.listener.EthereumListenerAdapter handles blockchain events detected by our client after connection to a node has been established successfully.
4.1. Connecting to the Ethereum Network
Let’s connect to a node on the network. This can be done manually:
String ip = "http://localhost";
int port = 8345;
String nodeId = "a4de274d3a159e10c2c9a68c326511236381b84c9ec...";
ethereum.connect(ip, port, nodeId);
Connecting to the network can also be done automatically using a bean:
public class EthBean {
private Ethereum ethereum;
public void start() {
ethereum = EthereumFactory.createEthereum();
ethereum.addListener(new EthListener(ethereum));
}
public Block getBestBlock() {
return ethereum.getBlockchain().getBestBlock();
}
public BigInteger getTotalDifficulty() {
return ethereum.getBlockchain().getTotalDifficulty();
}
}
We can then inject our EthBean into our application configuration. Then it automatically connects to the Ethereum network and starts downloading the blockchain.
In fact, the most connection processing is conveniently wrapped and abstracted by merely adding an org.ethereum.listener.EthereumListenerAdapter instance to our created org.ethereum.facade.Ethereum instance, as we did in our start() method above:
EthBean eBean = new EthBean();
Executors.newSingleThreadExecutor().submit(eBean::start);
4.2. Handling the Blockchain Using a Listener
We can also subclass the EthereumListenerAdapter to handle blockchain events detected by our client.
To accomplish this step, we’ll need to make our subclassed listener:
public class EthListener extends EthereumListenerAdapter {
private void out(String t) {
l.info(t);
}
//...
@Override
public void onBlock(Block block, List receipts) {
if (syncDone) {
out("Net hash rate: " + calcNetHashRate(block));
out("Block difficulty: " + block.getDifficultyBI().toString());
out("Block transactions: " + block.getTransactionsList().toString());
out("Best block (last block): " + ethereum
.getBlockchain()
.getBestBlock().toString());
out("Total difficulty: " + ethereum
.getBlockchain()
.getTotalDifficulty().toString());
}
}
@Override
public void onSyncDone(SyncState state) {
out("onSyncDone " + state);
if (!syncDone) {
out(" ** SYNC DONE ** ");
syncDone = true;
}
}
}
The onBlock() method is triggered on any new block received (whether old or current). EthereumJ represents and handles blocks using the org.ethereum.core.Block class.
The onSyncDone() method fires once syncing is complete, bringing our local Ethereum data up-to-date.
5. Working With the Blockchain
Now that we can connect to the Ethereum network and work directly with the blockchain, we’ll dive into several basic but nevertheless very important operations we’ll often use.
5.1. Submitting a Transaction
Now, that we’ve connected to the blockchain we can submit a transaction. Submitting a Transaction is relatively easy but creating an actual Transaction is a lengthy topic by itself:
ethereum.submitTransaction(new Transaction(new byte[]));
5.2. Access the Blockchain Object
The getBlockchain() method returns a Blockchain facade object with getters for fetching current network difficulties and specific Blocks.
Since we set up our EthereumListener in section 4.3, we can access the blockchain using the above method:
ethereum.getBlockchain();
5.3. Returning an Ethereum Account Address
We can also return an Ethereum Address.
To get an Ethereum Account – we first need to authenticate a public and private key pair on the blockchain.
Let’s create a fresh key with a new random key pair:
org.ethereum.crypto.ECKey key = new ECKey();
And let’s create a key from a given private key:
org.ethereum.crypto.ECKey key = ECKey.fromPivate(privKey);
We can then use our key to initialize an Account. By calling .init() we set both an ECKey and the associated Address on the Account object:
org.ethereum.core.Account account = new Account();
account.init(key);
6. Other Functionality
There are two other major functionalities provided for by the framework that we won’t cover here but that are worth mentioning.
First, we have the ability to compile and execute Solidity smart contracts. However, creating contracts in Solidity, and subsequently compiling and executing them is an extensive topic in its own right.
Second, although the framework supports limited mining using a CPU, using a GPU miner is the recommended approach given the lack of profitability of the former.
More advanced topics regarding Ethereum itself can be found in the official docs.
7. Conclusion
In this quick tutorial, we showed how to connect to the Ethereum network and several important methods for working with the blockchain.
As always the code used in this example can be found over on GitHub.