本系列文章介绍以太坊区块链基于Java语言的解决方案。通过介绍EthereumJ定义的主要模块和Class,希望为大家学习和使用EthereumJ提供一些帮助。
整体架构
以太坊的Java解决方案主要是由两个项目来实现的:
l EthereumJ(https://github.com/ethereum/ethereumj),实现了Ethereum定义的核心协议,完成了区块链的核心功能。
l Ethereum Harmony(https://github.com/ether-camp/ethereum-harmony),提供了Ethereum用户访问层的功能。
下图描述了两个项目里的主要的模块。
在EthereumJ里面,
l 最底层的DataSource提供了数据的persistence。数据采用的是<key, value>格式,以byte的形式保存,缺省使用的是Facebook的RocksDB。
l Blockchain Management实现了以太坊定义的Trie node,Transaction,Block,Block chain等数据结构,以及这些数据结构的管理功能。
l P2P Network实现了以太坊定义的devp2p协议,实现了以太坊的网络的,nodes之间的发现和nodes之间的通信功能。
l Sync Management,实现了以太坊网络nodes之间同步blocks/Transactions的功能。
l Block Mining实现了Ethash协议定义的block生成以及产生共识的功能。
l Program/VM实现了Solidity的compile和prgram的执行功能。
在Ethereum Harmony里面,
l Json RPC实现了以太坊定义的RPC接口,应用可以通过该RPC接口访问EthereumJ的数据,如Blocks,Transactions,Balance等。
l Wallet实现了简单的Wallet功能,可以采用Ethereum Go相同的key store格式来保存Account的私钥。记录了Account的Balance余额。但是无法显示Account的Transactions的历史记录。
l Command Terminal可以执行RPC的操作。
l Peer Connection显示了与EthereumJ相链接的Peer的状态。
主要配置文件
Ethereum Harmony/EthereumJ提供了很多的sample配置文件,通过不同的配置文件可以实现访问不同的以太坊网络,如MainNet,TestNet以及私有网络。
EthereumJ.conf
EthereumJ提供了很多的配置选项来差异化的定制系统, 配置文件采用Json的格式。缺省的Ethereumj.conf文件配置了系统的绝大部分参数,一般用户只需要在自己的配置文件,定义很少的参数,如database的文件存储位置,genesis配置文件的位置,系统的privateKey,listening port等系统外部参数。
EhereumJ的配置文件是由SystemProperties.java通过typesafe的config类库读取的。用户可以通过多个配置文件,实现系统在不同的部署环境下运行说需要的差异化配置。
l JVM的system property定义的某个参数
l JVM命令行定义的ethereumj.conf.file(-Dethereumj.conf.file)文件位置
l JVM的resource path下的test-user.conf
l JVM的resource path下的test-ethereumj.conf
l OS的user.dir目录下的/config/ehtereumj.conf
l JVM的resource path下的user.conf
l JVM命令行定义的ethereumj.conf.res(-Dethereumj.conf.res)在JVM的resource path下的文件
l 系统缺省的ethereumj.conf
上面列出了配置生效的顺序(优先级从上到下)。
Genesis.json
Genesis.json定义了每一个以太坊网络的第0个block。该网络里后续mining的区块链上的blocks都是建立在这一个block的数据的基础上的。如果要建立一个私有的以太坊网络,需要定义一个不同于其它以太坊网络的gensis block。同一个私有网络的genesis.json需要完全一致。
一个典型的genesis.json的配置文件如下:
// genesis.json
{
"alloc": {
"0xca843569e3427144cead5e4d5999a3d0ccf92b8e": {
"balance": "1000000000000000000000000000"
},
"0x0fbdc686b912d7722dc86510934589e0aaf3b55a": {
"balance": "1000000000000000000000000000"
}
},
"config": {
"chainID": 68,
"homesteadBlock": 0,
"eip155Block": 0,
"eip158Block": 0
},
"nonce": "0x0000000000000000",
"difficulty": "0x0400",
"mixhash": "0x0000000000000000000000000000000000000000000000000000000000000000",
"coinbase": "0x0000000000000000000000000000000000000000",
"timestamp": "0x00",
"parentHash": "0x0000000000000000000000000000000000000000000000000000000000000000",
"extraData": "0x43a3dfdb4j343b428c638c19837004b5ed33adb3db69cbdb7a38e1e50b1b82fa",
"gasLimit": "0xffffffff"
}
其中alloc的数据定义了网络开始就已经生效的account。配置数据,包括该account的address和account的state,如balance等。
Config也定义了以太坊网络的配置参数,这里面的配置将会覆盖EthereumJ的配置文件里配置的以太坊网络的配置参数。以太坊网络在实际的部署过程中,发现了一些问题,网络为了改正这些错误进行了相应的升级。这些升级反应在以太坊网络的配置参数,以太坊网络里的Node上的程序按照这些配置参数来工作。Config里配置决定了网络节点在某一个block序号开始采用何种网络工作版本。下面是MainNetConfig里定义的不同的block序号,采用不同的网络工作版本。
add(0, new FrontierConfig());
add(1_150_000, new HomesteadConfig());
add(1_920_000, new DaoHFConfig());
add(2_463_000, new Eip150HFConfig(new DaoHFConfig()));
add(2_675_000, new Eip160HFConfig(new DaoHFConfig()));
add(4_370_000, new ByzantiumConfig(new DaoHFConfig()));
如果是一个私有的网络,就可以从第一个block开始就采用最新的工作版本了。
Difficulty定义了共识算法的难度。该数值越小,表示越容易生成新的block。如果是私有网络,可以定义较小的值来快速的生成block,从而提高网络的响应速度。
gasLimit定义了本网络的每一个block产生时,允许使用的最大gas数量。
下面的参数主要用于配置网络节点产生新的block,在genesis的block里不被使用。
Nonce/MixHash是为了验证新生成的block是否有效。
ParentHash是上一个block的hash。
Coinbase是成功生成block后,该地址的account将会得到奖励。
启动
EthereumJ使用Spring Framework来加载各个模块。
在EthereumJ的samples里面,提供了很多的例子,使用EthereumFactory的createEthereum()来加载Spring的Application Context。Spring通过加载EthereumJ定义的DefaultConfig和CommonConfig来加载EthereumJ的其它模块。EthereumJ除了在这两个类里创建的多个spring beans,在CommonConfig里通过Spring的ComponentScan的功能创建了EthereumJ定义的多个Components,Services。
EthereumJ启动的主要Spring Beans包括:
l DataSources类,定义了多个Data Source的访问类(实现了Source<K,V>接口),采用了Decorator模式,实现了多种cache,DB access等功能。
l BlockMiner,block mining的主要管理模块。
l WorldManager,作为主要的管理模块,启动了block chain的创建,和以太坊node间的同步。
l EthereumImpl,实现了Ethereum接口。Ethereum接口提供了外部应用程序访问以太坊内部功能的多个methods。
其它的主要模块,在后续的文章里会有介绍。