区块链私链的搭建以及web3j的API调用
(参考文档)
(http://blog.hubwiz.com/2018/07/10/web3j-index/、
https://github.com/ethereum/wiki/wiki/JavaScript-API、
http://cw.hubwiz.com/card/c/geth-rpc-api/、
https://www.jianshu.com/p/cd5aed9b06af,)
区块链私链的搭建,以及使用
1 首先安装区块链客户端工具Geth。https://ethfans.org/wikis/Ethereum-Geth-Mirror
下载完成后需要配置一下环境变量。
2 创建区块链的配置文件genesis.json
{
"config": {
"chainId": 666,
"homesteadBlock": 0,
"eip150Block": 0,
"eip150Hash": "0x0000000000000000000000000000000000000000000000000000000000000000",
"eip155Block": 0,
"eip158Block": 0,
"byzantiumBlock": 0,
"constantinopleBlock": 0,
"petersburgBlock": 0,
"istanbulBlock": 0,
"ethash": {
}
},
"nonce": "0x00",
"timestamp": "0x00",
"extraData": "0x47656e6573697320426c6f636b",
"gasLimit": "0x47b760",
"difficulty": "0x00000ff0",
"mixHash": "0x0000000000000000000000000000000000000000000000000000000000000000",
"coinbase": "0x0000000000000000000000000000000000000000",
"alloc": {
},
"parentHash": "0x0000000000000000000000000000000000000000000000000000000000000000"
}
nonce: 证明64位散列与混合散列相结合,在该块上进行了足够的计算:工作量证明(PoW). nonce是加密安全的挖掘工作证明,证明在确定该令牌值时已经花费了特定量的计算.
timestamp: 标量值等于此块开始时Unix time()函数的合理输出。该机制在块之间的时间方面强制实施稳态。最后两个块之间的较小周期导致难度级别的增加,从而导致找到下一个有效块所需的额外计算。如果周期太大,则减少了难度和到下一个块的预期时间。时间戳还允许验证链内的块顺序。
extraData: 区块存储中的附加信息。可选填,但最多32字节长的空间。
gasLimit: 该值设置为对gas的消耗总量限的制,用来对区块能包含的交易信息总和的限制,即每块区块消费的gas总量不能大于这个值,用来限制每个区块可以记账的总数,我们的情况需要设置得很高,以避免在测试期间受到此阈值的限制。
difficulty: 对应于在该区块的随机数发现期间应用的难度级别。它定义了挖掘目标,可以根据前一个块的难度级别和时间戳来计算。值越大,难度越高,矿工必须通过更多的计算才能发现有效的区块。
mixHash:表示上一区块中的部分数据算出来的hash值,和Nonce一起计算出新的随机数,其目的是用于下一个区块产生的共识计算过程
coinbase:当前节点矿工地址
alloc:可以预先定义填充的钱包列表。即可以预先设置几个账户
parentHash:整个父块头的Keccak256位哈希。指向父块的指针,从而有效地构建块链。创世区块中,它为0.
3 初始化区块链节点
创建一个目录用来存放区块链数据,如图:
这里创建了一个geth目录用来存放区块链私有节点数据。
命令geth --datadir “node1” init gensis.json,中–datadir为指定创建节点后数据存放的目录,init gensis.json表示根据gensis.json文件初始化,这里我一开始初始化了四个节点,如下:
#!/bin/bash
rm -rf /Users/wutong/Documents/论文/code/geth/node1
rm -rf /Users/wutong/Documents/论文/code/geth/node2
rm -rf /Users/wutong/Documents/论文/code/geth/node3
rm -rf /Users/wutong/Documents/论文/code/geth/node4
mkdir node1
mkdir node2
mkdir node3
mkdir node4
geth --datadir "node1" init gensis.json
geth --datadir "node2" init gensis.json
geth --datadir "node3" init gensis.json
geth --datadir "node4" init gensis.json
4 启动各个节点,并连接各个节点
启动时geth客户端一些参数含义具体如下:
–identity 表示自定义节点名
–rpc 表示启用HTTP-RPC服务,即可以通过调用API访问区块链私链
–rpcport 表示HTTP-RPC服务器侦听端口
–rpcaddr 表示HTTP-RPC服务器侦听接口
–rpcapi 表示通过HTTP-RPC接口提供的API
–rpccorsdomain 表示接受跨源请求的域的逗号分隔列表
–nodiscover 表示禁用对等发现机制(手动添加对等节点)
–allow-insecure-unlock 表示当http公开与帐户相关的rpc时,允许不安全的帐户解锁
–networkid 表示网络表示符(整数,1=Frontier,2=Morden(已废弃),3=Ropsten,4=Rinkeby)(默认值:1),这里因为是本地搭建私有链,填一个与这些不同的数就可以
–datadir 表示根据指定目录下的文件启动节点
console 表示启动交互式JavaScript环境
打开四个终端界面,分别执行下面一行的geth命令,一行geth命令启动一个节点,如果想再添加区块链节点个数,按上面步骤换端口,重新初始化一个节点,并启动,之后如下面的,添加到区块链网络上就可以了。
geth --identity "node1" --rpc --rpcport "30001" --nodiscover --port "8001" --rpcapi "personal,eth,net,web3,miner" --networkid 1234 --allow-insecure-unlock -rpcaddr "10.3.80.81" --rpccorsdomain "*" --datadir "./node1" console
geth --identity "node2" --rpc --port "8002" --nodiscover --rpcport "30002" --rpcapi "personal,eth,net,web3,miner" --networkid 1234 --allow-insecure-unlock -rpcaddr "10.3.80.81" --rpccorsdomain "*" --datadir "./node2" console
geth --identity "node3" --rpc --port "8003" --nodiscover --rpcport "30003" --rpcapi "personal,eth,net,web3,miner" --networkid 1234 --allow-insecure-unlock -rpcaddr "10.3.80.81" --rpccorsdomain "*" --datadir "./node3" console
geth --identity "node4" --rpc --port "8004" --nodiscover --rpcport "30004" --rpcapi "personal,eth,net,web3,miner" --networkid 1234 --allow-insecure-unlock -rpcaddr "10.3.80.81" --rpccorsdomain "*" --datadir "./node4" console
具体如图:
查询节点细腻些,选择一个节点,将其他节点都添加到这个节点对应的区块链网络中(节点通信类似与无向图,不需要每个节点都添加其他所有节点,只要加入这个网络就能访问区块链网络上的所有信息)
查询节点信息:
添加到区块链网络中:
5 添加完成后,就可以做区块链网络上的一些操作了,具体如下:
① :创建账户(personal.newAccount(“password”)) password为账户密码
② 查询账户(personal.listAccount()
③ 查询账户余额(eth.getBalance(“账号地址”)),默认单位是wei,单位进制如下:
④ 挖矿(挖矿首先当前节点下得有账户,节点默认选取第一个为矿工,也可以设置,挖矿好处多多,首先挖到矿,拥有记账权,记账,区块链系统采用的激励机制会奖励一些币给矿工,其次矿工可以收取一部分转账用户的小费)具体如下图:miner.start()挖矿
⑤ 停止挖矿(miner.stop())
⑥ 设置矿工 miner.setEtherbase(“矿工地址”)
⑦ 查询区块总数(eth.blockNumber)
⑧ 查询区块信息(eth.getBlock(序号))
⑨ 解锁账户(personal.unlockAccount(账户地址))
⑩ 锁定账户 (personal.lockAccount(账户地址)
⑪ 转账,转账前需要解锁账户
Amount = web3.toWei(1,'ether') //将以太转换为微
personal.unlockAccount(eth.accounts[0]) //解锁账户
Data = web3.toHex(“你可以将信息保存在这个字段”) //将信息保存在区块交易中
eth.sendTransaction({
from: eth.accounts[0], to: eth.accounts[1], value: Amount, data: Data}) //转账
(注意,这个时候交易信息还没有被记录到区块中,当有矿工挖到矿,记下这笔交易,才被写入区块账本中)
⑫ 查询交易中的信息(txpool.content)
终端上常用的命令工具有(admin、eth、personal、net、txpool、web3)
使用Java工具类web3j, 调用API访问私有区块链
习惯使用IDEA的maven去构建一个springboot项目,方便,是真的方便,可以免去网上找包,类库的麻烦(可以去maven官网找web3j的jar包,构建一个java项目,也可以用IDEA去构建一个web项目,https://mvnrepository.com/artifact/org.web3j/core,这里构建的是一个web项目
① pom.xml依赖
<dependency>
<groupId>org.web3j</groupId>
<artifactId>core</artifactId>
<version>4.0.0</version>
</dependency>
<dependency>
<groupId>org.web3j</groupId>
<artifactId>geth</artifactId>
<version>4.0.0</version>
</dependency>
② Web3Client.java(采用单列模式创建一个工具类)
public class Web3jClient {
private static String ip = "http://10.3.80.81:30001";
private Web3jClient(){
}
private volatile static Web3j web3j;
private volatile static Admin admin;
private volatile static Geth geth;
public static Web3j getClient(){
if(web3j == null){
synchronized (Web3jClient.class){
if(web3j == null){
web3j = Web3j.build(new HttpService(ip));
}
}
}
return web3j;
}
public static Admin getAdmin(){
if(admin == null){
synchronized (Web3jClient.class){
if(admin == null){
admin = Admin.build(new HttpService(ip));
}
}
}
return admin;
}
public static Geth getGeth(){
if