1. 简介
本文将介绍 EthereumJ 库,这是一个让我们能用 Java 与 以太坊 区块链交互的工具。
首先快速了解下这项技术的核心概念。
⚠️ 重要提示:本文使用的 EthereumJ 库已被弃用,相关代码不再维护。
2. 关于以太坊
以太坊 是一种加密货币,它基于可编程的区块链(以太坊虚拟机 EVM)构建分布式点对点数据库。网络由分散但相互连接的节点同步和运作。
截至2017年,节点通过共识同步区块链,通过挖矿(工作量证明)创建代币,验证交易,执行用 Solidity 编写的智能合约,并运行 EVM。
区块链由区块组成,每个区块包含:
- 账户状态(包括账户间交易)
- 工作量证明
3. Ethereum 门面类
org.ethereum.facade.Ethereum
类将 EthereumJ 的多个包抽象为统一的易用接口。通过它我们可以连接节点同步网络,连接后即可操作区块链。
创建门面对象非常简单:
Ethereum ethereum = EthereumFactory.createEthereum();
4. 连接以太坊网络
要连接网络,必须先连接到运行官方客户端的节点。节点由 org.ethereum.net.rlpx.Node
类表示。
org.ethereum.listener.EthereumListenerAdapter
用于处理连接成功后检测到的区块链事件。
4.1. 连接以太坊网络
手动连接网络节点:
String ip = "http://localhost";
int port = 8345;
String nodeId = "a4de274d3a159e10c2c9a68c326511236381b84c9ec...";
ethereum.connect(ip, port, nodeId);
也可通过 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();
}
}
将 EthBean
注入应用配置后,会自动连接以太坊网络并开始下载区块链。核心连接逻辑被封装在 EthereumListenerAdapter
中:
EthBean eBean = new EthBean();
Executors.newSingleThreadExecutor().submit(eBean::start);
4.2. 使用监听器处理区块链事件
继承 EthereumListenerAdapter
处理区块链事件:
public class EthListener extends EthereumListenerAdapter {
private void out(String t) {
l.info(t);
}
//...
@Override
public void onBlock(Block block, List receipts) {
if (syncDone) {
out("网络算力: " + calcNetHashRate(block));
out("区块难度: " + block.getDifficultyBI().toString());
out("区块交易: " + block.getTransactionsList().toString());
out("最新区块: " + ethereum
.getBlockchain()
.getBestBlock().toString());
out("总难度: " + ethereum
.getBlockchain()
.getTotalDifficulty().toString());
}
}
@Override
public void onSyncDone(SyncState state) {
out("同步完成 " + state);
if (!syncDone) {
out(" ** 同步完成 ** ");
syncDone = true;
}
}
}
关键方法说明:
onBlock()
:接收到新区块时触发(历史或当前区块),区块由org.ethereum.core.Block
类处理onSyncDone()
:同步完成时触发,此时本地数据已更新至最新状态
5. 操作区块链
连接网络后,我们来看几个常用的重要操作。
5.1. 提交交易
提交交易很简单,但创建交易本身是个复杂话题:
ethereum.submitTransaction(new Transaction(new byte[]));
5.2. 访问区块链对象
getBlockchain()
返回区块链门面对象,提供获取网络难度和特定区块的方法:
ethereum.getBlockchain();
5.3. 生成以太坊账户地址
获取以太坊地址需要先在链上认证公私钥对。
创建新随机密钥对:
org.ethereum.crypto.ECKey key = new ECKey();
从已有私钥创建密钥:
org.ethereum.crypto.ECKey key = ECKey.fromPrivate(privKey);
用密钥初始化账户对象:
org.ethereum.core.Account account = new Account();
account.init(key);
调用 init()
会同时设置 ECKey
和关联的 Address
。
6. 其他功能
框架还提供两个重要功能(本文不展开):
- 智能合约:编译和执行 Solidity 智能合约(这是个独立的大话题)
- 挖矿:支持 CPU 挖矿,但鉴于收益低,推荐使用 GPU 挖矿
更高级的以太坊主题可参考官方文档。
7. 总结
本文展示了如何连接以太坊网络及操作区块链的核心方法。完整示例代码可在 GitHub 获取。