Contents

Ethereumj 简介

1. 简介

在本文中,我们看一下EthereumJ 库,它允许我们使用 Java与Ethereum 区块链进行交互。

首先,让我们简要介绍一下这项技术的全部内容。

2. 关于以太坊

以太坊 是一种加密货币,它利用可编程blockchain形式的分布式点对点数据库,即以太坊虚拟机 (EVM)。它通过不同但连接的nodes进行同步和操作。

截至 2017 年,nodes通过共识同步blockchain ,通过挖掘创建硬币(proof of work),验证交易,执行用Solidity 编写的smart contracts,并运行 EVM。

blockchain 分为包含account states(包括account之间的交易)和proof of work的区块。

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注入到我们的应用程序配置中。然后它会自动连接到以太坊网络并开始下载区块链。

事实上,大多数连接处理都被方便地包装和抽象,只需将org.ethereum.listener.EthereumListenerAdapter实例添加到我们创建的org.ethereum.facade.Ethereum实例中,就像我们在上面的*start()*方法中所做的那样:

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("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;
        }
    }
}

*onBlock()*方法在接收到的任何新块(无论是旧的还是当前的)上触发。EthereumJ 使用org.ethereum.core.Block类表示和处理块。

一旦同步完成,*onSyncDone()*方法就会触发,从而使我们的本地以太坊数据保持最新。

5. 使用区块链

现在我们可以连接到以太坊网络并直接使用区块链,我们将深入研究我们经常使用的几个基本但非常重要的操作。

5.1. 提交交易

现在,我们已经连接到区块链,我们可以提交交易。提交Transaction相对容易,但创建实际Transaction本身就是一个冗长的话题:

ethereum.submitTransaction(new Transaction(new byte[]));

5.2. 访问Blockchain对象

getBlockchain()方法返回一个带有 getter的Blockchain外观对象,用于获取当前的网络困难和特定的Blocks

由于我们在 4.3 节中设置了EthereumListener,我们可以使用上述方法访问区块链:

ethereum.getBlockchain();

5.3. 返回以太坊账户地址

我们还可以返回一个以太坊Address

要获得以太坊Account——我们首先需要在区块链上验证公钥和私钥对。

让我们用一个新的随机密钥对创建一个新的密钥:

org.ethereum.crypto.ECKey key = new ECKey();

让我们从给定的私钥创建一个密钥:

org.ethereum.crypto.ECKey key = ECKey.fromPivate(privKey);

然后我们可以使用我们的密钥来初始化一个Account。通过调用*.init()我们在Account对象上设置ECKey和关联的Address*:

org.ethereum.core.Account account = new Account();
account.init(key);

6. 其他功能

该框架还提供了另外两个主要功能,我们不会在这里介绍,但值得一提。

首先,我们有能力编译和执行 Solidity 智能合约。然而,在 Solidity 中创建合约,然后编译和执行它们本身就是一个广泛的话题。

其次,虽然该框架支持使用 CPU 进行有限挖矿,但鉴于前者缺乏盈利能力,建议使用 GPU 矿工。

有关以太坊本身的更高级主题可以在官方文档 中找到。