以太坊Web3j插件功能探究(一)

HPB小秘书发表于:2018年01月02日 11:02:08更新于:2018年01月03日 10:14:11

1.     以太坊概述


以太坊(Ethereum)并不是一个机构,而是一款能够在区块链上实现智能合约、开源的底层系统,以太坊从诞生到2017年5月,短短3年半时间,全球已有200多个以太坊应用诞生。以太坊是一个平台和一种编程语言,使开发人员能够建立和发布下一代分布式应用。 以太坊可以用来编程,分散,担保和交易任何事物:投票,域名,金融交易所,众筹,公司管理, 合同和大部分的协议,知识产权,还有得益于硬件集成的智能资产。


1.1   以太坊的技术特点


1)    以太坊是一个区块链的开发平台,而非用于交易的加密货币—--创始人Vitalik Buterin。因此,其显著特性是可编程性。


2)   客户端支持多种语言:Go、C++、Python、JavaScript; v  Go:go-ethereum(geth)

v  C++:cpp-ethereum(ceth)


3)   客户端支持多种操作系统和设备:Linux、FreeBSD、OS X、Windows、Docker、ARM、IOS、智能手机、智能手表、平板电脑;

v  得益于C++的跨平台;


4)   客户端既是服务器端软件(P2P通信、区块链管理、API接口服务)和挖矿软件,又是命令行工具,还是控制台程序。只需客户端即可运行完整的节点;


5)   客户端(geth、ceth)支持Docker容器部署;


6)   提供图形化钱包软件(Mist),内嵌客户端工具,支持转账和智能合约;


7)   支持多种编程接口:JAX-RPC、WS-RPC、IPC-RPC、JavaScript;功能最完善的是JavaScript接口库web3.js;


8)   控制台下可以直接运行JavaScript脚本,可以直接使用Web3.js库;


9)   Web应用的页面,可以直接使用Web3.js库,也可以通过Ajax/HttpClient使用JAX-RPC、WS-RPC接口。


10)   以太坊合约的代码使用低级的基于堆栈的字节码的语言写成的,被称为“以太坊虚拟机代码”或者“EVM代码”。



1.2   以太坊的账户

以太坊账户分为两类(均使用20字节的地址代表账户,HEX16转换后是40字节串):


1)     外部控制账户(EOA):由私钥保护的“实体” 账户,存储以太坊网络的以太币;


2)     智能合约账户:由合约代码控制的账户,从区块链的角度看形同一个实体账户,只是人无法直接操作;


3)     前者只能由人发起进行以太币的转账,后者只能在代码的控制下进行以太币转账;


4)     前者可以发送消息给后者,触发其执行相应的指令或业务逻辑,如转账、产品申购等。


5)     交易费用总是由前者提供。如要触发后者运行,前者既要提供发送消息的费用,还要提供合约运行的费用。如提供的费用不足,则合约可能运行到中途结束。此时,全部影响被自动撤销,但交易费用不会退还。交易结束后,多余的Gas自动退还。



1.3   智能合约


1.3.1  业务角度看智能合约


1)     智能合约是根据事先任意制订的规则来自动转移数字资产的系统;


2)     智能合约是事件驱动的、具有状态的、获得多方承认的、运行在区块链之上的程序。该程序能够按照预设的条件,自动地处理其管理的资产。


3)     智能合约是一个机器人,拥有自己的账户,按照其设定程序,可以代替自然人或法人严格地进行仲裁和执行合约;


4)     智能合约存储在区块链上,被矿工计算机自动执行;


5)     智能合约具有数据透明、代码透明、不可篡改、永久运行的特点;



1.3.2  程序员角度看智能合约


1)       智能合约像构建在区块链数据库上的存储过程;


2)       智能合约像类,有属性、方法和构造、析构函数;


3)       智能合约像服务,对外提供同步和异步的消息接口;


4)       智能合约使用类JavaScript高级语言编写,被编译为可以被以太坊区块链虚拟机(EVM)运行的二进制码;


5)       智能合约支持继承;


6)       智能合约可以部署为共享的库;


7)       智能合约编译后由接口描述和二进制执行代码构成。



1.4   以太坊架构描述


●   以太坊是构建在区块链2.0技术之上的应用平台;


●   区块链 2.0

1)  价值知晓:可以从外部数据源获取虚拟币的汇率;

2)  区块知晓:可以读取区块的内部数据;

3)  图灵完备:实现通用的计算机的指令;

4)  智能合约:支持编写和运行智能合约;

5)  平台化,支持多种应用和虚拟币;

6)  更快速地交易,秒级交易确认;

7)  更低能耗,支持多种共识算法。


●   增加多种共识算法和图灵完备的智能合约;


●   引入Gas(燃油)作为服务手续费,增加作恶成本,也阻止死循环程序的执行;


●   以太坊是可编程的区块链;


●   以太坊是运行智能合约的分布式虚拟机(EVM)。



1.5   以太坊的业务特点


●   以太坊的目标是提供一个带有内置的成熟的图灵完备语言的区块链,用这种语言可以创建合约来编码任意状态转换功能;


●   货币单位:(建议普通交易以以太为单位,微交易以芬尼为单位,费用以萨博或伟为单位 --- 因而,以太坊基本不使用小数)


1)   wei           Wei Dai               戴伟        密码学家,提出b-money思想,首次通过解决计算难题和去中心化共识创造货币;


2)  10^3: babbage      Charles Babbage 巴贝奇    英国数学家、发明家兼机械工程师,提出差分机与分析机设计概念,计算机先驱;


3)  10^6: lovelace    Ada Lovelace    洛夫莱斯     世界上第一位程序员、诗人拜伦之女


4)  10^9: shannon    Claude Elwood Shannon 香农  美国数学家、电子工程师和密码学家,被誉为信息论的创始人;


5)  10^12: szabo          Nick Szabo      尼克萨博         密码学家、智能合约的提出者;


6)  10^15: finney         Hal Finney     芬尼    密码学家、工作量证明机制(POW)的提出者,结合b-money,创造密码学货币;


7)  10^18: ether                            以太


●   支持POW、POS、DPOS等多种共识算法,默认是POW;


●   挖矿奖励(奖励的货币是凭空产生的):


1)  成功挖掘一个有效新区块,奖励 5 以太;


2)  该区块包含的全部交易的服务费中,3/4分配发起交易的各个发起节点,1/4给当前区块的矿工;


3)  对新块确认有贡献的叔叔块,给予87.5%的奖励;以该叔叔块进行计算的侄子块,给予 12.5%的奖励;每个块最多两个叔叔;


●   交易费用:


1)  每个交易都会导致存储、下载、验证的成本,因此需要通过交易费用以控制滥发交易;


2)  交易费用根据计算的复杂度和存储数据的大小由系统自动计算,这称为Gas;


3)  实际支付的费用=Gas*GasPrice。GasPrice默认为0.02萨博,创世纪块可以设置最大GasLimit,以阻止太复杂的智能合约。


●   挖矿效率:


1)  平均12秒挖出1个块;


2)  100小时挖出30000个块;


3)  6个块基本确认1笔交易(1分钟后基本认为交易有效)--- 幽灵协议;


●   消息和交易:消息是账户间传递的数据;交易指外部控制账户发起的消息的签名数据包。



1.6   以太坊常用命令

创建创世纪块:

# geth --networkid 20160817 --datadir /var/gethdata/init init /var/gethdata/genesis.json


启动节点:

# geth --verbosity 4 --networkid "20160817" --datadir /var/gethdata –rpc


以IPCS方式连接本地运行节点,进入控制台:

# geth attach ipc:/var/gethdata/geth.ipc


生成引导节点ID

bootnode --genkey=boot.key


运行引导节点

bootnode --nodekey=boot.key


以下命令在控制台执行:控制台提供 admin、debug、eth、miner、net、personal、rpc、txpool、web3等服务

1)     列出连接的Peers:> admin.peers

2)     列出驻留本节点的账号:> eth.accounts

3)     查询某个账号的余额:> eth.getBalance("0x….")

4)     解锁某个账号:> personal.unlockAccount("0x….")

5)     创建新账号:> personal.newAccount()

6)     账户直接转账:> eth.sendTransaction({from: “0x…付款人”, to: “0x…收款人”, value: …转账金额})

7)     启动挖矿服务:> miner.start(1)

8)     停止挖矿服务:> miner.stop()



1.7   参考资料

1.  Web3j的参考文档:https://docs.web3j.io/index.html

2.  Spring Boot的参考文档:https://docs.spring.io/spring-boot/docs/current/reference/html/index.html

3.  汪晓明对区块链、以太坊的思考:http://wangxiaoming.com/blog/archives/

4.  以太坊官方网站:https://ethereum.org/

5.  以太坊所有源码地址(官方):https://github.com/ethereum/

6.  以太坊Homestead文档地址(官方):http://www.ethdocs.org/en/latest/index.html

7.  以太坊网络状态地址(官方):https://ethstats.net/

8.  以太坊资源网站(官方):http://ether.fund/

9.  Solidity编程文档(官方):http://solidity.readthedocs.io/en/latest/

10.   以太坊网络扫描(官方):http://etherscan.io/

11.   以太坊官方的论坛:http://ethfans.org/topics

12.   以太坊官方博客:https://blog.ethereum.org/

13.   以太坊wiki百科地址:https://github.com/ethereum/wiki/wiki

14.   以太坊中文爱好者网站:http://ethfans.org/

15.   以太坊的gitter的实时交流网站:https://gitter.im/orgs/ethe reum/rooms

16.   以太坊的官方论坛:https://forum.ethereum.org/

17.   以太坊开发框架Truffle说明书:http://truffle.readthedocs.io/en/latest/

18.   以太坊开发框架dapple说明书:http://dapple.readthedocs.io/en/master/

19.   以太坊官方推荐开发框架Meteor说明书:https://github.com/ethereum/wiki/wiki/Dapp-using-MeteorDAO



2       Java Web3J概述


Web3j是一个轻量级,Reactive(响应式),类型安全的Java库,用于与Ethereum网络上的客户端(节点)集成,这允许您使用Ethereum块链,而不需要为平台编写自己的集成代码的额外开销。


2.1   Web3J的提供的功能

1.  通过HTTP和IPC 完成Ethereum的JSON-RPC客户端API的实现

2.  Ethereum钱包支持

3.  使用过滤器的函数式编程功能的API

4.  自动生成Java智能合约包装器,以创建、部署、处理和调用来自本地Java代码的智能合约

5.  支持Parity的 个人和Geth的 个人客户端API

6.  支持Infura,所以您不必自己运行一个Ethereum客户端

7.  综合整合测试展示了上述一些场景

8.  命令行工具


2.2   Web3J的依赖的库(中间件)

1.  RxJava函数式编程的的API中间件

2.  Apache HTTP Client中间件

3.  Jackson Core 用于快速JSON序列化/反序列化中间件

4.  Bouncy Castle加密解密和 Java Scrypt加密中间件

5.  生成智能合约java包装器类的java源代码(.java)的JavaPoet中间件

6.  Java的UNIX域套接字的*nix系统进程间通信API中间件


 2.3   启动Ethereum客户端

$ geth --fast --cache = 512 –networkid 2 - -rpcapi “personal,db,eth,net,web3” --rpc --dev


2.4   Web3J的进程间通信IPC

Web3j还支持通过文件套接字快速进行进程间通信(IPC)到在与web3j相同的主机上运行的客户端。在创建服务时,连接只需使用相关的IpcService实现而不是 HttpService



2.5   Web3J的过滤器

Web3j的函数式编程的特性让我们设置观察者很容易,这样通知订阅者在区块链以便知道区块链上设置的事件。


2.5.1  区块过滤器

当所有新的块被添加到块链中的时候,接收到这些区块

如果您希望查看最近的当前的区块,以便于新的后续块的创建:

2.5.2  交易过滤器

当所有新的交易被添加到块链中的时候,接收到这些交易

2.5.3  待处理的交易过滤器

当所有待处理的交易被提交到网络时(也就是说,在它们被分组到一个块之前),接收这些交易

2.5.4  使用Web3J交易

Web3j支持使用Ethereum钱包文件(推荐)和用于发送交易的Ethereum客户端管理命令。

使用您的Ethereum钱包文件将Ether发送到另一方:

如果想自定义交易

1.    获取可用的nonce

 2.    创建交易

3.    签名并发送交易

4.    使用web3j的智能合约包装器要简单得多


2.6   使用Web3J智能合约

使用Java智能合约包装器处理智能合约

web3j可以自动生成智能合约包装器代码,以便在不离开Java的情况下部署和与智能合约进行交互,生成包装代码


2.6.1  编译智能合约

$ solc <contract> .sol --bin --abi --optimize -o <output-dir>


2.6.2  然后使用Web3J的命令行工具生成包装器代码

Web3j solidity生成/path/to/<smart-contract>.bin /path/to/<smart-contract>.abi -o / path / to / src / main / java -p com.your.organisation.name


2.6.3  创建并部署智能合约


2.6.4  使用已存在的智能合约



3         以太坊的Web3J交易


3.1   Web3J交易类型

从广义上讲,以太坊有三种类型的交易

1.从以太坊的一方转移到另一方

2.创建智能合约

3.交易智能合约


3.2   在TestNet /私有块链上挖矿

在Ethereme测试网络(TestNet)中,采矿难度低于主网络(MainNet)。这意味着您可以使用常规CPU(如笔记本电脑)挖掘新的Ether,您需要做的就是运行一个Ethereum客户端


3.3   以太坊GAS

在使用Ethereum客户端时,这意味着有两个参数(GasPrice,GasLimit)用来决定你想花多少时间来完成一项任务:


3.3.1  Gas Price

这是你在每单位Gas中所准备的量。它的价格是9000 Wei (9 x 10 ^15 Ether)

这是你在交易执行过程中愿意花费的总金额。在以太坊中,一个交易的大小是有上限的,它限制了这个值,通常限制为1,500,000


3.3.2  Gas Limit

这些参数组合在一起,决定了您愿意花费在交易成本上的最大数量。也就是说,你不能再用Gas的价格限制了。GasPrice也会影响交易发生的速度,这取决于其他交易的价格,而这些交易对矿商来说更有利可图,您可能需要对这些参数进行调整,以确保交易能够及时地进行。


3.4   交易机制

当您使用某种Ether创建有效的帐户时,可以使用两种机制来与Ethereum进行交易,这两种机制都通过web3j来支持。

1.  通过Ethereum客户端进行交易签名

2.  离线交易签名


3.4.1  通过Ethereum客户端进行交易签名

为了通过Ethereum客户端进行交易,您首先需要确保您所交易的客户知道您的钱包地址。为了做到这一点,你最好运行自己的Ethereum客户端,如Geth / Parity。一旦您有客户端运行,您可以通过以下方式创建一个钱包:

1.  Geth Wiki包含了Geth支持的不同机制的良好运行,比如导入私钥文件,并通过它的控制台创建一个新帐户或者,您可以为客户端使用JSON-RPC管理命令,例如,用于Parity 或Geth的personal_newAccount  

2.  在客户端使用json-rpc管理命令,对于 Parity or Geth使用personal_newAccount

创建您的钱包文件后,您可以通过web3j解锁帐户,首先创建一个支持Parity / Geth管理命令的web3j实例:


3.4.2  脱机交易签名

如果您不想管理自己的Ethereum客户端,或者不想向Ethereum客户端提供电子钱包详细信息(如密码),那么离线交易签名就是要走的路。

离线交易签名允许您使用您在Web3j中的Ethereum Ethereum钱包签署交易,从而可以完全控制您的私人凭据。离线创建的交易可以发送到网络上的任何Ethereum客户端,这将会将交易传播到其他节点,前提是它是一个有效的交易。


3.4.3  创建和使用钱包文件

为了离线签署交易,您需要使用您的Ethereum钱包文件或与Ethereum钱包/帐户相关的公钥和私钥,web3j能够为您生成一个新的安全Ethereum钱包文件,或者使用现有的钱包文件。

要创建一个新的钱包文件:

String fileName = WalletUtils.generateNewWalletFile("your password",new File("/path/to/destination"));


3.4.4  脱机签名交易

如果具有达到脱机签名能力目的交易应该使用 RawTransaction类型。RawTransaction类似于之前提到的交易类型,但是它不需要from地址,因为这可以从签名中推断出来。

为了创建和签名一个raw交易,顺序如下:

确定发件人帐户的下一个可用随机数

1.        创建RawTransaction对象

2.         编码RawTransaction对象

3.         签名RawTransaction对象

4.         将RawTransaction对象发送到节点进行处理

5.         获取下一个可用的随机数后,该值就可以用于创建交易对象:


6.        然后可以对交易进行签名和编码:

这些凭证是在创建和处理钱包文件时加载的。

7.        然后使用ethsendrawtransaction发送该交易:


3.4.5  交易 Nonce

Nonce是一个递增的数值,它用于惟一地标识交易。一个nonce只能被使用一次,直到一个交易被挖矿确认,它可以用同一个nonce发送多个版本的交易,然而,一旦被挖矿确认,任何后续的提交都将被拒绝,可以通过


3.4.6  Nonce使用规则

为了防止交易重播,ETH(ETC)节点要求每笔交易必须有一个nonce数值。每一个账户从同一个节点发起交易时,这个nonce值从0开始计数,发送一笔nonce对应加1。当前面的nonce处理完成之后才会处理后面的nonce。

注意这里的前提条件是相同的地址在相同的节点发送交易。

1.         当nonce太小(小于之前已经有交易使用的nonce值),交易会被直接拒绝。

2.         当nonce太大,交易会一直处于队列之中,这也就是导致我们上面描述的问题的原因;

3.         当发送一个比较大的nonce值,然后补齐开始nonce到那个值之间的nonce,那么交易依旧可以被执行。

4.         当交易处于queue中时停止geth客户端,那么交易queue中的交易会被清除掉。


3.5   创建智能合约


3.5.1 使用Raw Transaction


3.5.2  获取合约地址

如果智能合约包含构造函数,则相关的构造函数字段值必须编码并附加到编译后的智能合约代码中:


3.5.3  执行智能合约

web3j负责为您提供功能编码,进一步的详细信息可以在Ethereum维基百科的电子合同ABI节中找到。

等待响应就使用EthGetTransactionReceipt…

不管消息签名的返回类型是什么,都不可能从事务性函数调用返回值。但是,可以使用过滤器捕获函数返回的值


3.5.4  查询智能合约的状态

此功能由ethcall json-rpc调用实现, ethcall允许您在智能合约中调用一个方法来查询一个值。这个函数不存在交易成本,这是因为它不会改变任何智能合约方法的状态,它只是简单地返回它们的值:

注意:如果生成了一个无效的函数调用,或者获得了一个null结果,那么返回值将是一个集合。emptylist的实例


HPB(芯链)