由于最近的项目涉及到区块链,需要做一个使用区块链存储数据的小型系统,区块链是用ethereum搭建的,加上自己一直在学习java(是个菜鸡哈哈哈可以一起交流),所以打算用web3j来与以太坊进行数据流转,发现网上做这个的人是真的少,自己摸索过也遇到了很多坑,(在这里要感谢已经毕业的大师兄@wtlife,帮了我不少忙,祝前程似锦,冲冲冲!)所以将自己遇到的一些问题和踩过的坑都贴出来,让大家少走一点弯路。下面开始正文:
以太坊的搭建这一块已经有很多前辈们写过了,这里不再赘述,仅将在学习过程中遇到的问题列出来:
geth --datadir 文件夹名 init genesis.json
会导致挖矿的时候长时间卡顿无法挖到区块,解决方案如下:
geth --datadir 文件夹名称 --networkid 网络号 --rpc --rpccorsdomain “*” init ./genesis.json
再给出启动节点的命令:
geth --datadir data --networkid 网络号 --rpc --rpccorsdomain “*” --nodiscover --port 16333 --rpc port 8546 console
之后正常挖矿即可,为了避免不必要的麻烦,创世区块中的gasLimit建议设置为0xffffff,即最大值。
一般来说,自己建立的私链都是使用的默认端口即:8545,但是保不齐该端口经常被占用,所以,在使用该可视化软件部署智能合约时,为了能够正确连接到本地私链,应采用如下方式:
本质上其实就是使用rpc调用节点文件夹中的geth.ipc文件。
成功连接之后如下图所示:
关于以太坊钱包如何使用,网上也有详细的教程,接下来将使用Java web3j的流程做一个小结。
先给出测试用的智能合约代码,该部分借鉴了@littleredhat1997 的github中的一些资料,不胜感激。
pragma solidity ^0.4.24;
contract Storage{
struct Msg{
string userName;
string ID;
string violateRecord;
uint lowPoint;
string AdministratorName;
}
Msg[] violateRecords;
uint totalMsg=0;
function addMsg(string username,string ID,string violateRecord,uint lowPoint,string AdministratorName ) public{
violateRecords.push(Msg(username,ID,violateRecord,lowPoint,AdministratorName));
}
// function returnTotal() view public returns (uint) {
// return violateRecords.length;
// }
function getuserName(uint id) view public returns (string){
return violateRecords[id].userName;
}
function getID(uint id) view public returns (string){
return violateRecords[id].ID;
}
function getviolateRecord(uint id) view public returns (string){
return violateRecords[id].violateRecord;
}
function getlowPoint(uint id) view public returns (uint){
return violateRecords[id].lowPoint;
}
function getAdministrator(uint id) view public returns (string){
return violateRecords[id].AdministratorName;
}
}
//如果没有安装npm 需要先安装npm
npm install solc
//会在输出目录生成abi文件和bin文件
solc Storage.sol --bin --abi --optimize - o <输出目录 -dir>/
web3j solidity generate bin文件的绝对路径 abi文件的绝对路径 -o java文件的目标路径 -p 包名+类名
org.web3j
core
4.2.0
import org.web3j.crypto.CipherException;
import org.web3j.crypto.Credentials;
import org.web3j.crypto.WalletUtils;
import org.web3j.protocol.Web3j;
import org.web3j.protocol.core.RemoteCall;
import org.web3j.protocol.core.methods.response.TransactionReceipt;
import org.web3j.protocol.core.methods.response.Web3ClientVersion;
import org.web3j.protocol.http.HttpService;
import org.web3j.tx.gas.ContractGasProvider;
import java.io.IOException;
import java.math.BigInteger;
public class Test {
// GAS价格
public static BigInteger GAS_PRICE = BigInteger.valueOf(20_000_000_000L);
// GAS上限
public static BigInteger GAS_LIMIT = BigInteger.valueOf(4_300_000L);
//合约文件的地址,不会查看的同学可以从将sol文件放入remix中编译获得
public static String ADDORSEARCH_ADDR = "0xc9D1639f492807CbAeEc1ce3B178eCBB171F2Df5";
public static void main(String[] args) throws Exception {
//建立web3j连接,监听私链端口
Web3j web3 = Web3j.build(new HttpService("http://localhost:8547"));
Web3ClientVersion web3ClientVersion = web3.web3ClientVersion().send();
String clientVersion = web3ClientVersion.getWeb3ClientVersion();
//连接本地私链的节点,WU.lC(账号的密码,账号对应的钱包文件的绝对路径)
Credentials credentials = WalletUtils.loadCredentials("12345678","/home/qiaozhi/ethereum/data1/keystore/UTC--2019-04-15T08-41-08.880520248Z--6c82e2fef78951b27a7f4c21004e1477cd876c91");
ContractGasProvider provider = new ContractGasProvider() {
@Override
public BigInteger getGasPrice(String s) {
return GAS_PRICE;
}
@Override
public BigInteger getGasPrice() {
return GAS_PRICE;
}
@Override
public BigInteger getGasLimit(String s) {
return GAS_LIMIT;
}
@Override
public BigInteger getGasLimit() {
return GAS_LIMIT;
}
};
// AddorSearch addorSearch = AddorSearch.deploy(web3,credentials,GAS_PRICE,GAS_LIMIT).send();
//该类即为使用web3j命令转换成的java类,包含了sol文件中的所有属性和方法
AddorSearch addorSearch = AddorSearch.load(ADDORSEARCH_ADDR,web3,credentials,provider);
//这里还未完善,sol中应该添加一个length属性,用来循环输出所存储的值
System.out.println(addorSearch.getuserName(BigInteger.valueOf(1)).send().toString());
System.out.println(addorSearch.getID(BigInteger.valueOf(1)).send());
System.out.println(addorSearch.getviolateRecord(BigInteger.valueOf(1)).send());
}
这个项目还没有完善,后期还会进行修改,最近一直在找工作,有时间会上传到我的github上,欢迎大家一起交流!^ _ ^