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. 其他功能

框架还提供两个重要功能(本文不展开):

  1. 智能合约:编译和执行 Solidity 智能合约(这是个独立的大话题)
  2. 挖矿:支持 CPU 挖矿,但鉴于收益低,推荐使用 GPU 挖矿

更高级的以太坊主题可参考官方文档

7. 总结

本文展示了如何连接以太坊网络及操作区块链的核心方法。完整示例代码可在 GitHub 获取。


原始标题:Introduction to EthereumJ

« 上一篇: RxJava 教程
» 下一篇: GeoTools 入门指南