区块链之java调用智能合约(一)编译智能合约_调用智能合约

阿里云国内75折 回扣 微信号:monov8
阿里云国际,腾讯云国际,低至75折。AWS 93折 免费开户实名账号 代冲值 优惠多多 微信号:monov8 飞机:@monov6

前言

首先还是一贯的思路带着问题学习。

在最后附带上我的Gitee代码因为国内访问github有时候真的很蛋疼。

提问

1.Solidity是什么

2.java如何调用Solidity

解答

1.Solidity是什么呢

Solidity是一种语言为了编写智能合约的一种语言。以*.sol结尾的类似test.java结尾的java文件。该语言类似javaScript语法。易上手。

展示个小案例。

// SPDX-License-Identifier: GPL-3.0

pragma solidity >=0.7.0 <0.9.0;

/**
 * @title Storage
 * @dev Store & retrieve value in a variable
 * @custom:dev-run-script ./scripts/deploy_with_ethers.ts
 */
contract Storage {

    uint256 number;

    /**
     * @dev Store value in variable
     * @param num value to store
     */
    function store(uint256 num) public {
        number = num;

    }

    /**
     * @dev Return value
     * @return value of 'number'
     */
    function retrieve() public view returns (uint256){
        return number;
    }

}

其中于java比较不同的是里面的数据类型及方法访问定义。

Solidity目前的ide有remix 一款线上的编辑工具

及基于node环境的vscode基于vscode编译需要安装Solidity的环境。

编译器的差别、

remix

优点免安装可直接使用易上手集成基础功能。

缺点没有本地保存刷新后会直接清空当前编写的合同易丢失文件

vscode

优点不易丢失文件

缺点需要安装插件需要本地部署安装框架

2.合约部署这个是属于区块链的东西针对后端的java攻城狮们并不是太了解。

那么接下来说的就是在java中如何调用智能合约。

首先java调用智能合约原理就是智能合约部署到区块链后java调用区块链api。

简单理解为我们就是调用第三方的api。但是呢区块链针对这块做了很多加密算法的工作。并不像原始的http那样显示的方式直接调用。这里就需要使用到一些java已经封装好的包了。

引入对应的maven包具体的版本到时候看对应的发布

 <!--web3j-->
    <dependency>
      <groupId>org.web3j</groupId>
      <artifactId>core</artifactId>
      <version>5.0.0</version>
    </dependency>

    <dependency>
      <groupId>org.web3j</groupId>
      <artifactId>codegen</artifactId>
      <version>5.0.0</version>
    </dependency>

引入对于的包是第一步那么接下来就是如何调用了。

首先可以看一个开源的案例。

https://github.com/web3j/sample-project-gradle

该项目的项目结构为这样的。 

该图中包含了sol文件及java的调用文件Application。

其中有个问题。

就是虽然导入sol文件但是在java中并不属于java文件这个时候是无法调用的。

那么我们需要先将sol文件转为java文件然后才能调用。

怎么转呢

两种方式

前面的步骤都是一样的。具体的合约编译自行查询下。我知道的暂时就是两种一种是使用npm下载的Solidity编译还有一个是使用remix编译。

编写好后直接在remix中点击编译即可。

编译前

编译后这里需要注意的是需要选中对应的sol文件才会对相应的sol文件编译否则编译按钮会显示灰色例如下图2显示

 编译完后对就需要获取对应的abi于bin文件了。

 点击该abi按钮后对自动复制的粘贴板中可直接复制到文件或对于的数据中

  点击该bytecode按钮后对自动复制的粘贴板中可直接复制到文件或对于的数据中

一、使java插件的web3j库生成对应的java文件。

首选需要创建一个生成对于文件的java类。

package org.saiwen.paul.util;

import org.web3j.codegen.SolidityFunctionWrapperGenerator;

import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.Arrays;
import java.util.stream.Stream;

/**
 * @Author paul.peng
 * @Date 2022/5/10
 * @Version 1.0
 */

public class SolidityGenerateUtil {

    // 私有实例类初始化就加载
    private static SolidityGenerateUtil solidityGenerateUtil = new SolidityGenerateUtil();

    // 私有构造方法
    private SolidityGenerateUtil() {}

    // 公共的、静态的获取实例方法
    public static SolidityGenerateUtil getInstance() {
        return solidityGenerateUtil;
    }

    public static void genAbiAndBin(){
        String abi  = "[\n" +
                "\t{\n" +
                "\t\t\"inputs\": [],\n" +
                "\t\t\"name\": \"retrieve\",\n" +
                "\t\t\"outputs\": [\n" +
                "\t\t\t{\n" +
                "\t\t\t\t\"internalType\": \"uint256\",\n" +
                "\t\t\t\t\"name\": \"\",\n" +
                "\t\t\t\t\"type\": \"uint256\"\n" +
                "\t\t\t}\n" +
                "\t\t],\n" +
                "\t\t\"stateMutability\": \"view\",\n" +
                "\t\t\"type\": \"function\"\n" +
                "\t},\n" +
                "\t{\n" +
                "\t\t\"inputs\": [\n" +
                "\t\t\t{\n" +
                "\t\t\t\t\"internalType\": \"uint256\",\n" +
                "\t\t\t\t\"name\": \"num\",\n" +
                "\t\t\t\t\"type\": \"uint256\"\n" +
                "\t\t\t}\n" +
                "\t\t],\n" +
                "\t\t\"name\": \"store\",\n" +
                "\t\t\"outputs\": [],\n" +
                "\t\t\"stateMutability\": \"nonpayable\",\n" +
                "\t\t\"type\": \"function\"\n" +
                "\t}\n" +
                "]";
        String bin = "{\n" +
                "\t\"functionDebugData\": {},\n" +
                "\t\"generatedSources\": [],\n" +
                "\t\"linkReferences\": {},\n" +
                "\t\"object\": \"608060405234801561001057600080fd5b50610150806100206000396000f3fe608060405234801561001057600080fd5b50600436106100365760003560e01c80632e64cec11461003b5780636057361d14610059575b600080fd5b610043610075565b60405161005091906100d9565b60405180910390f35b610073600480360381019061006e919061009d565b61007e565b005b60008054905090565b8060008190555050565b60008135905061009781610103565b92915050565b6000602082840312156100b3576100b26100fe565b5b60006100c184828501610088565b91505092915050565b6100d3816100f4565b82525050565b60006020820190506100ee60008301846100ca565b92915050565b6000819050919050565b600080fd5b61010c816100f4565b811461011757600080fd5b5056fea2646970667358221220314b4c9cabe40fdbaade24da458a24445455e8c74197270e57df53f1ccf13fea64736f6c63430008070033\",\n" +
                "\t\"opcodes\": \"PUSH1 0x80 PUSH1 0x40 MSTORE CALLVALUE DUP1 ISZERO PUSH2 0x10 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST POP PUSH2 0x150 DUP1 PUSH2 0x20 PUSH1 0x0 CODECOPY PUSH1 0x0 RETURN INVALID PUSH1 0x80 PUSH1 0x40 MSTORE CALLVALUE DUP1 ISZERO PUSH2 0x10 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST POP PUSH1 0x4 CALLDATASIZE LT PUSH2 0x36 JUMPI PUSH1 0x0 CALLDATALOAD PUSH1 0xE0 SHR DUP1 PUSH4 0x2E64CEC1 EQ PUSH2 0x3B JUMPI DUP1 PUSH4 0x6057361D EQ PUSH2 0x59 JUMPI JUMPDEST PUSH1 0x0 DUP1 REVERT JUMPDEST PUSH2 0x43 PUSH2 0x75 JUMP JUMPDEST PUSH1 0x40 MLOAD PUSH2 0x50 SWAP2 SWAP1 PUSH2 0xD9 JUMP JUMPDEST PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 RETURN JUMPDEST PUSH2 0x73 PUSH1 0x4 DUP1 CALLDATASIZE SUB DUP2 ADD SWAP1 PUSH2 0x6E SWAP2 SWAP1 PUSH2 0x9D JUMP JUMPDEST PUSH2 0x7E JUMP JUMPDEST STOP JUMPDEST PUSH1 0x0 DUP1 SLOAD SWAP1 POP SWAP1 JUMP JUMPDEST DUP1 PUSH1 0x0 DUP2 SWAP1 SSTORE POP POP JUMP JUMPDEST PUSH1 0x0 DUP2 CALLDATALOAD SWAP1 POP PUSH2 0x97 DUP2 PUSH2 0x103 JUMP JUMPDEST SWAP3 SWAP2 POP POP JUMP JUMPDEST PUSH1 0x0 PUSH1 0x20 DUP3 DUP5 SUB SLT ISZERO PUSH2 0xB3 JUMPI PUSH2 0xB2 PUSH2 0xFE JUMP JUMPDEST JUMPDEST PUSH1 0x0 PUSH2 0xC1 DUP5 DUP3 DUP6 ADD PUSH2 0x88 JUMP JUMPDEST SWAP2 POP POP SWAP3 SWAP2 POP POP JUMP JUMPDEST PUSH2 0xD3 DUP2 PUSH2 0xF4 JUMP JUMPDEST DUP3 MSTORE POP POP JUMP JUMPDEST PUSH1 0x0 PUSH1 0x20 DUP3 ADD SWAP1 POP PUSH2 0xEE PUSH1 0x0 DUP4 ADD DUP5 PUSH2 0xCA JUMP JUMPDEST SWAP3 SWAP2 POP POP JUMP JUMPDEST PUSH1 0x0 DUP2 SWAP1 POP SWAP2 SWAP1 POP JUMP JUMPDEST PUSH1 0x0 DUP1 REVERT JUMPDEST PUSH2 0x10C DUP2 PUSH2 0xF4 JUMP JUMPDEST DUP2 EQ PUSH2 0x117 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST POP JUMP INVALID LOG2 PUSH5 0x6970667358 0x22 SLT KECCAK256 BALANCE 0x4B 0x4C SWAP13 0xAB 0xE4 0xF 0xDB 0xAA 0xDE 0x24 0xDA GASLIMIT DUP11 0x24 DIFFICULTY SLOAD SSTORE 0xE8 0xC7 COINBASE SWAP8 0x27 0xE JUMPI 0xDF MSTORE8 CALL 0xCC CALL EXTCODEHASH 0xEA PUSH5 0x736F6C6343 STOP ADDMOD SMOD STOP CALLER \",\n" +
                "\t\"sourceMap\": \"199:356:0:-:0;;;;;;;;;;;;;;;;;;;\"\n" +
                "}";
        String abiFileName = "Storage.abi";
        String binFileName = "Storage.bin";
        generateAbiAndBin(abi,bin,abiFileName,binFileName);
    }

    public static void generateAbiAndBin(String abi,String bin,String abiFileName,String binFileName){

        File abiFile = new File("src/main/"+abiFileName);
        File binFile = new File("src/main/"+binFileName);
        BufferedOutputStream abiBos = null;
        BufferedOutputStream binBos = null;
        try{
            FileOutputStream abiFos = new FileOutputStream(abiFile);
            FileOutputStream binFos = new FileOutputStream(binFile);
            abiBos = new BufferedOutputStream(abiFos);
            binBos = new BufferedOutputStream(binFos);
            abiBos.write(abi.getBytes());
            abiBos.flush();
            binBos.write(bin.getBytes());
            binBos.flush();
            generateJavaFile(abiFile.getPath(),binFile.getPath());
        }catch (Exception e){
            e.printStackTrace();

        }finally {
            if(abiBos != null){
                try{
                    abiBos.close();;
                }catch (IOException e){
                    e.printStackTrace();
                }
            }
            if(binBos != null){
                try {
                    binBos.close();
                }catch (IOException e){
                    e.printStackTrace();
                }
            }
        }
    }

    public static void generateJavaFile(String abiFile, String binFile){
        String generateFile = "src/main/java/org/saiwen/paul/solidity/";
        generateClass(abiFile,binFile,generateFile);
    }

    public static void generateClass(String abiFile,String binFile,String generateFile){
        String[] args = Arrays.asList(
                "-a",abiFile,
                "-b",binFile,
                "-p","",
                "-o",generateFile
        ).toArray(new String[0]);
        Stream.of(args).forEach(System.out::println);
        SolidityFunctionWrapperGenerator.main(args);
    }





}

自定义位置启动genAbiAndBin方法即可。

然后在项目中就可以查找到对于的Storage.abiStorage.bin与Storage.java了。

二、使用web3j命令行生成对应的java文件

先下载web3j命令行工具。找到对应的zip

然后解压到自己的目录中。

 进入bin目录。然后手动创建两个对应的文件。***.abi及***.bin。在把刚刚编译的对应合约码的abi与bytecode码拷贝到相应的文件中。然后在当前目录进入cmd。执行

web3j solidity generate ***.bin ***.abi -o java -p com.eth

用Storage.abi为例。

web3j solidity generate Storage.bin Storage.abi -o java -p com.eth

 然后就会在当前目录生成对应的java文件。

git地址link-sol: 智能合约

然后将java文件导入到项目对应存放的地址即可记住导入后需要修改package 的路径

 至此简单的合约编译合约导入完成。下一节在讲讲如何调用钱包等。

阿里云国内75折 回扣 微信号:monov8
阿里云国际,腾讯云国际,低至75折。AWS 93折 免费开户实名账号 代冲值 优惠多多 微信号:monov8 飞机:@monov6
标签: Java区块链