基于JavaSDK调用FISCO BCOS 区块链

本文档详述了一位Java程序员如何利用FISCO BCOS区块链存储文件的SHA256Hex哈希值并进行验证。通过智能合约,实现了存值、查询和获取区块链信息的功能,包括同步和异步交易处理,以及区块链高度、哈希等信息的获取。代码示例展示了如何部署和调用合约,以及解析交易回执来获取存储的数据。
摘要由CSDN通过智能技术生成

基于https://fisco-bcos-documentation.readthedocs.io文档开发


起因:需要将文件的sha256Hex哈希值存于搭建的FISCO BCOS 区块链中并验证文件的hash是否改变达到知晓文件是否改动的效果,并能查询出区块链的相关信息比如区块链的总高度,当前高度,区块链的hash值,名称,时间。

说明:我是一个java程序员只是负责读文档完成怎么实现调用区块链,关于这个区块链怎么搭建我没有做过多的了解,下面分享我通过智能合约调用区块链的过程

什么是FISCO BCOS 区块链

FISCO BCOS是由国内企业主导研发、对外开源、安全可控的企业级金融联盟链底层平台,由金链盟开源工作组协作打造,并于2017年正式对外开源。

FISCO BCOS 是一个稳定、高效、安全的区块链底层平台,经过多家机构、多个应用,长时间在生产环境运行的实际检验。

社区以开源链接多方,截止2020年5月,汇聚了超1000家企业及机构、逾万名社区成员参与共建共治,发展成为最大最活跃的国产开源联盟链生态圈。底层平台可用性经广泛应用实践检验,数百个应用项目基于FISCO BCOS底层平台研发,超80个已在生产环境中稳定运行,覆盖文化版权、司法服务、政务服务、物联网、金融、智慧社区等领域。

注解FISCO BCOS以联盟链的实际需求为出发点,兼顾性能、安全、可运维性、易用性、可扩展性,支持多种SDK,并提供了可视化的中间件工具,大幅缩短建链、开发、部署应用的时间。此外,FISCO BCOS通过信通院可信区块链评测功能、性能两项评测,单链TPS可达两万。

调用过程

  1. 引入调用区块链的相关jar
    		<dependency>
    			<groupId>org.fisco-bcos.java-sdk</groupId>
    			<artifactId>fisco-bcos-java-sdk</artifactId>
    			<version>2.7.1</version>
    		</dependency>
    		<dependency>
    			<groupId>org.bouncycastle</groupId>
    			<artifactId>bcprov-jdk15on</artifactId>
    			<version>1.60</version>
    		</dependency>
    		<dependency>
    			<groupId>org.fisco-bcos</groupId>
    			<artifactId>netty-sm-ssl-context</artifactId>
    			<version>1.2.0</version>
    		</dependency>
    		<dependency>
    			<groupId>org.fisco-bcos</groupId>
    			<artifactId>tcnative</artifactId>
    			<version>2.0.34.0</version>
    		</dependency>
  2. 引入相关配置文件比如证书,智能合约

环境准备好后,话不多说直接上代码

第一个接口,去往区块链里存值并拿到区块链返回的区块hash值

说明:此方法传进去的两个参数一个是当前创建时间另一个是文件的hash值去存储,包涵了初始化sdk,初始化对象部署,同步方式部署合约异步方式部署,同步发送交易,异步发生区块交易,已经一些区块链的接口方法的调用,具体说明在远程调用接口 — FISCO BCOS v2.7.2 文档借口文档

 private String  transactionHash;//区块链返回的hash
    
 public String  testClient(String createTime,String FileMd5) throws Exception {
    	String path = this.getClass().getResource("/").getPath()
                    .replaceFirst("/","");
    	//String path = classpath.replaceAll("WEB-INF/classes/", "conf");
    	//path = path.replaceAll("\\\\", "/");
    	//初始化BcosSDK对象
    	BcosSDK sdk =  BcosSDK.build("/"+path+"conf/config-example.toml");
        // 获取Client对象,此处传入的群组ID为1
        final Client client = sdk.getClient(1);
        // 获得区块数量
        //BlockNumber blockNumber = client.getBlockNumber();
        
 //*******************************TEST***********************************************************
        //初始化配置对象--------------------部署、交易和查询/仅交易和查询
        //构造AssembleTransactionProcessor对象,需要传入client对象,CryptoKeyPair对象和        
          //abi、binary文件存放的路径。
        CryptoKeyPair cryptoKeyPair = client.getCryptoSuite().createKeyPair();
        AssembleTransactionProcessor transactionProcessor =             
        TransactionProcessorFactory.createAssembleTransactionProcessor
        (client, cryptoKeyPair, "/"+path+"abi/", "/"+path+"bin/");
       
        // 同步方式部署合约-----------------也可以异步部署
        // 部署HelloWorld合约。第一个参数为合约名称,第二个参数为合约构造函数的列表,是    
           //List<Object>类型。
        TransactionResponse response =     transactionProcessor.deployByContractLoader("StoreData", new ArrayList<Object>());
        String con = response.getContractAddress();//获取部署或调用的合约地址。
        System.out.println("the contract hash is :"+con);
        
        //获取合约的abi文件里的参数
        final String api = transactionProcessor.getContractLoader().getABIByContractName("StoreData");
     	//获取交易总数	
        String  txNumber = client.getTotalTransactionCount().getTotalTransactionCount().getTxSum();
        int startTxNumber = Integer.parseInt(txNumber.replace("0x",""), 16);
        System.out.println("the startTxNumber:TxNumber is  :"+startTxNumber);
        

        final int SEND_TX_NUMBER = 1;
        //发送交易
        for (int i = 0; i < SEND_TX_NUMBER; i++) {
        	// 创建调用交易函数的参数,此处为传入一个参数
            List<Object> listAgv = new ArrayList<Object>();
            listAgv.add(createTime);
            listAgv.add(FileMd5);
            //同步发送交易  调用合约交易
            // 调用StoreData合约,合约地址为con, 调用函数名为『set』,函数参数类型为listAgv 并接收TransactionResponse结果。
//            TransactionResponse transactionResponse = transactionProcessor.sendTransactionAndGetResponseByContractLoader("StoreData", con, "set", listAgv);
//            System.out.println(transactionResponse);
            
            //异步发送交易
           transactionProcessor.sendTransactionAndGetReceiptByContractLoaderAsync("StoreData", con,
                    "set", listAgv,new TransactionCallback() {
                        @SneakyThrows
                        @Override
                        public void onResponse(TransactionReceipt receipt) {
                        	transactionHash = receipt.getTransactionHash();
                            System.out.println("start parse the receipt");
                            System.out.printf("the block getBlockNumber is %d \n",Integer.parseInt(receipt.getBlockNumber().replace("0x",""), 16));
                            System.out.printf("the block hash is %s\n",receipt.getBlockHash());
                            if(true)
                            	return;
                            CryptoSuite cryptoSuite = client.getCryptoSuite();
                            TransactionDecoderInterface decoder = new TransactionDecoderService(cryptoSuite);

                            List<TransactionReceipt.Logs> logs =  receipt.getLogs();
                            Map<String, List<List<Object>>> events = new HashMap<String, List<List<Object>>>();
							try {
								events = decoder.decodeEvents(api, receipt.getLogs());
							} catch (ABICodecException e) {
								e.printStackTrace();
							}
							
                           // Map<String, List<List<Object>>>> events  = decoder.decodeEvents(abi, receipt.getLogs());
                            for (List<List<Object>> lists :events.values()){
                                for(List<Object> list : lists){
                                    System.out.println(list);
                                }
                            }

                        }
                    });
        }

        txNumber = client.getTotalTransactionCount().getTotalTransactionCount().getTxSum();
        int endTxNumber = Integer.parseInt(txNumber.replace("0x",""), 16);

        while (endTxNumber - startTxNumber < SEND_TX_NUMBER) {
            txNumber = client.getTotalTransactionCount().getTotalTransactionCount().getTxSum();
            endTxNumber = Integer.parseInt(txNumber.replace("0x",""), 16);
            //System.out.println(endTxNumber);
        }

        System.out.println("the endTxNumber:TxNumber is  :"+endTxNumber);
        //当前区块链的高度
        System.out.printf("client.getBlockNumber() is %d",client.getBlockNumber().getBlockNumber());

        return transactionHash;
    }

第二个接口,根据区块链返回的hash值去查询我存进去的文件hash以及传入时间

        说明:参数hash是存值是区块链返回的hash值

public void todiscase(String hash){
    String path = request.getSession().getServletContext().getRealPath("/");
    //初始化BcosSDK对象
  	BcosSDK sdk =  BcosSDK.build(path+"WEB-INF/classes/conf/config-example.toml");
    // 获取Client对象,此处传入的群组ID为1
    Client client = sdk.getClient(1);
    //初始化配置对象--------------------部署、交易和查询/仅交易和查询
    //构造AssembleTransactionProcessor对象,需要传入client对象,CryptoKeyPair对象和        
      //abi、binary文件存放的路径。
	CryptoKeyPair cryptoKeyPair = client.getCryptoSuite().createKeyPair();
	AssembleTransactionProcessor transactionProcessor =         
        TransactionProcessorFactory.createAssembleTransactionProcessor(client,     
        cryptoKeyPair, path+"WEB-INF/classes/abi/", path+"WEB-INF/classes/bin/");
	//获取合约的abi文件里的参数
	String api =     
        transactionProcessor.getContractLoader().getABIByContractName("StoreData");
	//根据交易哈希获取交易回执
	BcosTransactionReceipt cosTransactionReceipt = 
        client.getTransactionReceipt(hash);
	TransactionReceipt transactionReceipt = cosTransactionReceipt.getResult();
    //查询传入的参数
	CryptoSuite cryptoSuite = client.getCryptoSuite();
	TransactionDecoderInterface decoder = new TransactionDecoderService(cryptoSuite);
	Map<String, List<List<Object>>> events = 
             decoder.decodeEvents(api, transactionReceipt.getLogs());
    /*for (List<List<Object>> lists :events.values()){
            for(List<Object> list : lists){
                System.out.println(list);
            }
    }*/
    events.get("onset").get(0).get(0);//存入时间
    events.get("onset").get(0).get(1);//存入的文件hash
}

第三个接口,查询区块链的信息

        说明:参数hash是存值是区块链返回的hash值

public void selectBlock(String hash) {
		String path = request.getSession().getServletContext().getRealPath("/");
        //初始化BcosSDK对象
  	   	BcosSDK sdk =  BcosSDK.build(path+"WEB-INF/classes/conf/config-example.toml");
  	   	// 获取Client对象,此处传入的群组ID为1
		Client client = sdk.getClient(1);
		BcosTransaction bcosTransaction = client.getTransactionByHash(hash);
		JsonTransactionResponse jsonTransactionResponse = bcosTransaction.getResult();
		BlockNumber blockNumber = client.getBlockNumber();
		BigInteger blockNumbersum = blockNumber.getBlockNumber();//区块链的总高度
        jsonTransactionResponse.getBlockNumber();//当前区块链的高度
        jsonTransactionResponse.getBlockHash();//blockHash
        jsonTransactionResponse.getFrom();//from
        jsonTransactionResponse.getHash();;//hash
	}

我当时需求涉及的接口就这三个,更多接口的调用依需求而定

  • 0
    点赞
  • 20
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
好的,我可以为您解答关于在 SpringBoot 中调用 FISCO BCOS 合约的问题。 首先,您需要在项目中引入 FISCO BCOSJava SDK 包,可以通过 Maven 或 Gradle 依赖来实现。然后,您需要创建一个合约的 Java 接口,该接口需要继承自 org.fisco.bcos.sdk.contract.Contract 接口,并定义您合约中的方法,如下所示: ```java public interface MyContract extends Contract { public RemoteCall<TransactionReceipt> myMethod(int param1, String param2); } ``` 在接口中,您需要定义您合约中的方法,方法的返回值类型需要使用 RemoteCall 包装,以便异步调用合约并获取合约返回结果。 接下来,您需要实现该接口,实现类需要继承自 org.fisco.bcos.sdk.contract.ContractImpl 类,并在构造函数中调用父类的构造函数,同时将合约地址、私钥、公钥等信息传递给父类,如下所示: ```java public class MyContractImpl extends ContractImpl implements MyContract { public MyContractImpl(String contractAddress, Web3j web3j, Credentials credentials, BigInteger gasPrice, BigInteger gasLimit) { super(contractAddress, web3j, credentials, gasPrice, gasLimit); } @Override public RemoteCall<TransactionReceipt> myMethod(int param1, String param2) { // 执行合约方法 return executeRemoteCallTransaction(FunctionEncoder.encode(function), gasPrice, gasLimit); } } ``` 在实现类中,您需要实现接口中定义的方法,并在方法中调用合约的方法。 最后,在您的 SpringBoot 应用程序中,您可以通过以下方式进行合约的调用: ```java @Autowired private Web3j web3j; @Autowired private Credentials credentials; public void callContract() { String contractAddress = "0x..."; // 合约地址 MyContract myContract = new MyContractImpl(contractAddress, web3j, credentials, gasPrice, gasLimit); RemoteCall<TransactionReceipt> remoteCall = myContract.myMethod(1, "test"); TransactionReceipt receipt = remoteCall.sendAsync().get(); // 处理合约返回结果 } ``` 在 SpringBoot 中,您可以通过注入 Web3j 和 Credentials 对象来连接 FISCO BCOS 区块链网络,并通过调用 MyContractImpl 类中定义的方法来调用合约。最后,您可以通过异步调用 RemoteCall 对象的 sendAsync 方法来执行合约方法,并获取合约返回结果。 希望这些信息对您有所帮助。
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值