web3j基本使用

编译生成javaBean对象

  1. 编写solidity程序,保存在Voting.sol文件中
pragma solidity ^0.4.22;

contract Voting{
    
    bytes32[] public candidateList;
    mapping(bytes32=>uint8) public votingMap;
    
    constructor(bytes32[] candidateListName) public{
        candidateList = candidateListName;
    }
    
    function validateCandidate(bytes32 candidateListName) internal view returns(bool){
        for(uint8 i=0 ; i<candidateList.length ; i++){
            if(candidateListName == candidateList[i]){
                return true;
            }
        }
        return false;
    }
    
    function vote(bytes32 candidateListName) public{
        require(validateCandidate(candidateListName));
        votingMap[candidateListName] += 1;
    }
    
    function totalVoters(bytes32 candidateListName) public view returns(uint8){
        require(validateCandidate(candidateListName));
        return votingMap[candidateListName];
    } 
}
  1. 编译sol文件,生成bin和abi文件
./node_modules/solc/solcjs Voting.sol --bin --abi --optimize -o sourceCode
  1. 使用web3j编译生成javaBean类,将生成的文件加入到java的项目中
web3j solidity generate sourceCode/Voting_sol_Voting.bin sourceCode/Voting_sol_Voting.abi -o ./javaAPI -p com.yqj.blockChain

部署私链

geth --networkid 123 --rpc --rpcaddr 192.168.1.114 --rpcport 8989 --port 3000 --dev --datadir data1 console

编写java程序测试web3j

  1. 导包
<dependency>
    <groupId>org.web3j</groupId>
    <artifactId>core</artifactId>
    <version>3.6.0</version>
</dependency>
  1. 测试连接情况
@Slf4j(topic = "c.BlockChainTest")
public class BlockChainTest {
    public static void main(String[] args) throws IOException {
        Web3j web3 = Web3j.build(new HttpService("http://192.168.1.114:8989"));
        Web3ClientVersion web3ClientVersion = web3.web3ClientVersion().send();
        String clientVersion = web3ClientVersion.getWeb3ClientVersion();
        log.debug("{}",clientVersion);
    }
}

输出结果:

19:14:34 [main] c.BlockChainTest - Geth/v1.8.17-stable/linux-amd64/go1.9.7

Process finished with exit code 0

合约部署与方法调用

  • 测试文件 BlockChainTest
package com.yqj.blockchain;

import lombok.extern.slf4j.Slf4j;
import org.web3j.crypto.Credentials;
import org.web3j.crypto.WalletUtils;
import org.web3j.protocol.Web3j;
import org.web3j.protocol.core.methods.response.Web3ClientVersion;
import org.web3j.protocol.http.HttpService;
import org.web3j.utils.Numeric;

import java.math.BigInteger;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

@Slf4j(topic = "c.BlockChainTest")
public class BlockChainTest {
    public static void main(String[] args) throws Exception {
        loadContract();
    }

    //加载已经在链上的合约,并且调用方法
    public static void loadContract() throws Exception {
        //建立私链连接
        Web3j web3j = Web3j.build(new HttpService("http://192.168.1.114:8989"));
        //加载钱包账户,需要从geth的data文件中拷贝出来keysotre文件夹里的内容
        Credentials credentials = WalletUtils.loadCredentials("", "D:\\study\\code\\blockchain\\java-blockchain\\target\\classes\\keystore\\UTC--2020-05-23T13-30-20.410109802Z--613d104e6d80ce5a06e7987d39bbd4ee0ccd7656");
        //加载合约
        String contractAddr = "0x0db5bd6503e820be1691760491fd83df3ede3d76";
        Voting_sol_Voting contract = Voting_sol_Voting.load(contractAddr, web3j, credentials, BigInteger.valueOf(3000000), BigInteger.valueOf(3000000));
        log.debug("{}",contract);
        String count = contract.totalVoters(stringToBytes("Alice")).send().toString();
        log.debug("{}",count);
        contract.vote(stringToBytes("Alice")).send();
        count = contract.totalVoters(stringToBytes("Alice")).send().toString();
        log.debug("{}",count);
    }

    //部署合约
    public static void createContract() throws Exception {
        //建立私链连接
        Web3j web3j = Web3j.build(new HttpService("http://192.168.1.114:8989"));
        //查看版本信息,验证是否连接成功
        Web3ClientVersion web3ClientVersion = web3j.web3ClientVersion().send();
        String clientVersion = web3ClientVersion.getWeb3ClientVersion();
        log.debug("{}",clientVersion);
        //加载钱包账户
        Credentials credentials = WalletUtils.loadCredentials("", "D:\\study\\code\\blockchain\\java-blockchain\\target\\classes\\keystore\\UTC--2020-05-23T13-30-20.410109802Z--613d104e6d80ce5a06e7987d39bbd4ee0ccd7656");
        log.debug("{}",credentials);
        //构建初始化参数
        List<byte[]> list = new ArrayList<>();
        list.add(stringToBytes("Alice"));
        list.add(stringToBytes("Bob"));
        list.add(stringToBytes("Jerry"));
        //部署合约
        Voting_sol_Voting voting = Voting_sol_Voting.deploy(web3j,credentials,BigInteger.valueOf(3000000),BigInteger.valueOf(3000000),list).send();
        //合约地址 0x0db5bd6503e820be1691760491fd83df3ede3d76
        log.debug("{}",voting.getContractAddress());
    }

    //将字符串转换为可以转换为bytes32的形式的byte[]
    public static byte[] stringToBytes(String asciiValue)
    {
        char[] chars = asciiValue.toCharArray();
        StringBuffer hex = new StringBuffer();
        for (int i = 0; i < chars.length; i++) {
            hex.append(Integer.toHexString((int) chars[i]));
        }
        String hexString = hex.toString() + "".join("", Collections.nCopies(32 - (hex.length()/2), "00"));
        return Numeric.hexStringToByteArray(hexString);
    }
}
  • 由web3j自动生成的文件 Voting_sol_Voting
package com.yqj.blockchain;

import java.math.BigInteger;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import org.web3j.abi.FunctionEncoder;
import org.web3j.abi.TypeReference;
import org.web3j.abi.datatypes.Function;
import org.web3j.abi.datatypes.Type;
import org.web3j.abi.datatypes.generated.Bytes32;
import org.web3j.abi.datatypes.generated.Uint8;
import org.web3j.crypto.Credentials;
import org.web3j.protocol.Web3j;
import org.web3j.protocol.core.RemoteCall;
import org.web3j.protocol.core.methods.response.TransactionReceipt;
import org.web3j.tx.Contract;
import org.web3j.tx.TransactionManager;
import org.web3j.tx.gas.ContractGasProvider;

/**
 * <p>Auto generated code.
 * <p><strong>Do not modify!</strong>
 * <p>Please use the <a href="https://docs.web3j.io/command_line.html">web3j command line tools</a>,
 * or the org.web3j.codegen.SolidityFunctionWrapperGenerator in the 
 * <a href="https://github.com/web3j/web3j/tree/master/codegen">codegen module</a> to update.
 *
 * <p>Generated with web3j version 3.6.0.
 */
public class Voting_sol_Voting extends Contract {
    private static final String BINARY = "608060405234801561001057600080fd5b506040516102c43803806102c483398101604052805101805161003a906000906020840190610041565b50506100ab565b82805482825590600052602060002090810192821561007e579160200282015b8281111561007e5782518255602090920191600190910190610061565b5061008a92915061008e565b5090565b6100a891905b8082111561008a5760008155600101610094565b90565b61020a806100ba6000396000f3006080604052600436106100615763ffffffff7c01000000000000000000000000000000000000000000000000000000006000350416634db33f9281146100665780634dfb9c8014610094578063a69beaba146100ac578063b13c744b146100c6575b600080fd5b34801561007257600080fd5b5061007e6004356100f0565b6040805160ff9092168252519081900360200190f35b3480156100a057600080fd5b5061007e600435610105565b3480156100b857600080fd5b506100c4600435610131565b005b3480156100d257600080fd5b506100de60043561016e565b60408051918252519081900360200190f35b60016020526000908152604090205460ff1681565b60006101108261018d565b151561011b57600080fd5b5060009081526001602052604090205460ff1690565b61013a8161018d565b151561014557600080fd5b6000908152600160208190526040909120805460ff19811660ff91821690930116919091179055565b600080548290811061017c57fe5b600091825260209091200154905081565b6000805b60005460ff821610156101d3576000805460ff83169081106101af57fe5b6000918252602090912001548314156101cb57600191506101d8565b600101610191565b600091505b509190505600a165627a7a72305820bd2c76f66cb75779f0ca7f961af01658e499cf6ba22b040e7ea9e334018b76c60029";

    public static final String FUNC_VOTINGMAP = "votingMap";

    public static final String FUNC_TOTALVOTERS = "totalVoters";

    public static final String FUNC_VOTE = "vote";

    public static final String FUNC_CANDIDATELIST = "candidateList";

    @Deprecated
    protected Voting_sol_Voting(String contractAddress, Web3j web3j, Credentials credentials, BigInteger gasPrice, BigInteger gasLimit) {
        super(BINARY, contractAddress, web3j, credentials, gasPrice, gasLimit);
    }

    protected Voting_sol_Voting(String contractAddress, Web3j web3j, Credentials credentials, ContractGasProvider contractGasProvider) {
        super(BINARY, contractAddress, web3j, credentials, contractGasProvider);
    }

    @Deprecated
    protected Voting_sol_Voting(String contractAddress, Web3j web3j, TransactionManager transactionManager, BigInteger gasPrice, BigInteger gasLimit) {
        super(BINARY, contractAddress, web3j, transactionManager, gasPrice, gasLimit);
    }

    protected Voting_sol_Voting(String contractAddress, Web3j web3j, TransactionManager transactionManager, ContractGasProvider contractGasProvider) {
        super(BINARY, contractAddress, web3j, transactionManager, contractGasProvider);
    }

    public RemoteCall<BigInteger> votingMap(byte[] param0) {
        final Function function = new Function(FUNC_VOTINGMAP, 
                Arrays.<Type>asList(new Bytes32(param0)),
                Arrays.<TypeReference<?>>asList(new TypeReference<Uint8>() {}));
        return executeRemoteCallSingleValueReturn(function, BigInteger.class);
    }

    public RemoteCall<BigInteger> totalVoters(byte[] candidateListName) {
        final Function function = new Function(FUNC_TOTALVOTERS, 
                Arrays.<Type>asList(new Bytes32(candidateListName)),
                Arrays.<TypeReference<?>>asList(new TypeReference<Uint8>() {}));
        return executeRemoteCallSingleValueReturn(function, BigInteger.class);
    }

    public RemoteCall<TransactionReceipt> vote(byte[] candidateListName) {
        final Function function = new Function(
                FUNC_VOTE, 
                Arrays.<Type>asList(new Bytes32(candidateListName)),
                Collections.<TypeReference<?>>emptyList());
        return executeRemoteCallTransaction(function);
    }

    public RemoteCall<byte[]> candidateList(BigInteger param0) {
        final Function function = new Function(FUNC_CANDIDATELIST, 
                Arrays.<Type>asList(new org.web3j.abi.datatypes.generated.Uint256(param0)), 
                Arrays.<TypeReference<?>>asList(new TypeReference<Bytes32>() {}));
        return executeRemoteCallSingleValueReturn(function, byte[].class);
    }

    public static RemoteCall<Voting_sol_Voting> deploy(Web3j web3j, Credentials credentials, ContractGasProvider contractGasProvider, List<byte[]> candidateListName) {
        String encodedConstructor = FunctionEncoder.encodeConstructor(Arrays.<Type>asList(new org.web3j.abi.datatypes.DynamicArray<Bytes32>(
                        org.web3j.abi.Utils.typeMap(candidateListName, Bytes32.class))));
        return deployRemoteCall(Voting_sol_Voting.class, web3j, credentials, contractGasProvider, BINARY, encodedConstructor);
    }

    public static RemoteCall<Voting_sol_Voting> deploy(Web3j web3j, TransactionManager transactionManager, ContractGasProvider contractGasProvider, List<byte[]> candidateListName) {
        String encodedConstructor = FunctionEncoder.encodeConstructor(Arrays.<Type>asList(new org.web3j.abi.datatypes.DynamicArray<Bytes32>(
                        org.web3j.abi.Utils.typeMap(candidateListName, Bytes32.class))));
        return deployRemoteCall(Voting_sol_Voting.class, web3j, transactionManager, contractGasProvider, BINARY, encodedConstructor);
    }

    @Deprecated
    public static RemoteCall<Voting_sol_Voting> deploy(Web3j web3j, Credentials credentials, BigInteger gasPrice, BigInteger gasLimit, List<byte[]> candidateListName) {
        String encodedConstructor = FunctionEncoder.encodeConstructor(Arrays.<Type>asList(new org.web3j.abi.datatypes.DynamicArray<Bytes32>(
                        org.web3j.abi.Utils.typeMap(candidateListName, Bytes32.class))));
        return deployRemoteCall(Voting_sol_Voting.class, web3j, credentials, gasPrice, gasLimit, BINARY, encodedConstructor);
    }

    @Deprecated
    public static RemoteCall<Voting_sol_Voting> deploy(Web3j web3j, TransactionManager transactionManager, BigInteger gasPrice, BigInteger gasLimit, List<byte[]> candidateListName) {
        String encodedConstructor = FunctionEncoder.encodeConstructor(Arrays.<Type>asList(new org.web3j.abi.datatypes.DynamicArray<Bytes32>(
                        org.web3j.abi.Utils.typeMap(candidateListName, Bytes32.class))));
        return deployRemoteCall(Voting_sol_Voting.class, web3j, transactionManager, gasPrice, gasLimit, BINARY, encodedConstructor);
    }

    @Deprecated
    public static Voting_sol_Voting load(String contractAddress, Web3j web3j, Credentials credentials, BigInteger gasPrice, BigInteger gasLimit) {
        return new Voting_sol_Voting(contractAddress, web3j, credentials, gasPrice, gasLimit);
    }

    @Deprecated
    public static Voting_sol_Voting load(String contractAddress, Web3j web3j, TransactionManager transactionManager, BigInteger gasPrice, BigInteger gasLimit) {
        return new Voting_sol_Voting(contractAddress, web3j, transactionManager, gasPrice, gasLimit);
    }

    public static Voting_sol_Voting load(String contractAddress, Web3j web3j, Credentials credentials, ContractGasProvider contractGasProvider) {
        return new Voting_sol_Voting(contractAddress, web3j, credentials, contractGasProvider);
    }

    public static Voting_sol_Voting load(String contractAddress, Web3j web3j, TransactionManager transactionManager, ContractGasProvider contractGasProvider) {
        return new Voting_sol_Voting(contractAddress, web3j, transactionManager, contractGasProvider);
    }
}