fiscobcos开发第一个区块链应用--小白实战(代码片段)

背不过单词选手 背不过单词选手     2023-04-06     756

关键词:

官方链接

简单的步骤直接跳过了,主要是记录下整个过程中出现问题最多的地方

4. 创建区块链应用项目

第一步. 安装环境

首先,我们需要安装JDK以及集成开发环境

首先,在官网上下载JDK14(JDK1.8 至JDK 14都支持)并安装

然后,修改环境变量

视频讲解

文字步骤

# 确认您当前的java版本
$ java -version
# 确认您的java路径
$ ls /Library/Java/JavaVirtualMachines
# 返回
# jdk-14.0.2.jdk

# 如果使用的是bash
$ vim .bash_profile 
# 在文件中加入JAVA_HOME的路径
# export JAVA_HOME=/Library/Java/JavaVirtualMachines/jdk-14.0.2.jdk/Contents/Home 
$ source .bash_profile

# 如果使用的是zash
$ vim .zashrc
# 在文件中加入JAVA_HOME的路径
# export JAVA_HOME = Library/Java/JavaVirtualMachines/jdk-14.0.2.jdk/Contents/Home 
$ source .zashrc

# 确认您的java版本
$ java -version
# 返回
# java version "14.0.2" 2020-07-14
# Java(TM) SE Runtime Environment (build 14.0.2+12-46)
# Java HotSpot(TM) 64-Bit Server VM (build 14.0.2+12-46, mixed mode, sharing)

进入IntelliJ IDE官网,下载并安装社区版IntelliJ IDE

(我把idea装ubantu里面了,虽然一开始有点卡,扩了2g内存就可以了。还是觉得这样比较方便简单一点。。毕竟师兄给我讲了一遍,我没听懂)

安装链接

安装完后要创建一个快捷方式,这样就不需要每次启动的时候去目录下执行

创建快捷方式链接

第二步. 创建一个Java工程

在IntelliJ IDE中创建一个gradle项目,勾选GradleJava,并输入工程名

 

 第三步. 引入FISCO BCOS Java SDK

 在build.gradle文件中的 dependencies下加入对FISCO BCOS Java SDK的引用。

repositories 
    mavenCentral()
    maven 
        allowInsecureProtocol = true
        url "http://maven.aliyun.com/nexus/content/groups/public/"
    
    maven 
        allowInsecureProtocol = true
        url "https://oss.sonatype.org/content/repositories/snapshots" 
    

引入Java SDK jar包

testImplementation group: 'junit', name: 'junit', version: '4.12'
implementation ('org.fisco-bcos.java-sdk:fisco-bcos-java-sdk:2.9.0')

第四步. 配置SDK证书

修改build.gradle文件,引入Spring框架,

def spring_version = "4.3.27.RELEASE"
List spring = [
        "org.springframework:spring-core:$spring_version",
        "org.springframework:spring-beans:$spring_version",
        "org.springframework:spring-context:$spring_version",
        "org.springframework:spring-tx:$spring_version",
]

dependencies 
    testImplementation group: 'junit', name: 'junit', version: '4.12'
    implementation ("org.fisco-bcos.java-sdk:fisco-bcos-java-sdk:2.9.0")
    implementation spring

 asset-app/test/resources目录下创建配置文件 applicationContext.xml,写入配置内容。

(官方图)

applicationContext.xml的内容如下:

<?xml version="1.0" encoding="UTF-8" ?>

<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
    http://www.springframework.org/schema/beans/spring-beans-4.0.xsd">
    <bean id="defaultConfigProperty" class="org.fisco.bcos.sdk.config.model.ConfigProperty">
        <property name="cryptoMaterial">
            <map>
                <entry key="certPath" value="conf" />
            </map>
        </property>
        <property name="network">
            <map>
                <entry key="peers">
                    <list>
                        <value>127.0.0.1:20200</value>
                        <value>127.0.0.1:20201</value>
                    </list>
                </entry>
            </map>
        </property>
        <property name="account">
            <map>
                <entry key="keyStoreDir" value="account" />
                <entry key="accountAddress" value="" />
                <entry key="accountFileFormat" value="pem" />
                <entry key="password" value="" />
                <entry key="accountFilePath" value="" />
            </map>
        </property>
        <property name="threadPool">
            <map>
                <entry key="channelProcessorThreadSize" value="16" />
                <entry key="receiptProcessorThreadSize" value="16" />
                <entry key="maxBlockingQueueSize" value="102400" />
            </map>
        </property>
    </bean>

    <bean id="defaultConfigOption" class="org.fisco.bcos.sdk.config.ConfigOption">
        <constructor-arg name="configProperty">
            <ref bean="defaultConfigProperty"/>
        </constructor-arg>
    </bean>

    <bean id="bcosSDK" class="org.fisco.bcos.sdk.BcosSDK">
        <constructor-arg name="configOption">
            <ref bean="defaultConfigOption"/>
        </constructor-arg>
    </bean>
</beans>

 在以上配置文件中,我们指定了证书存放的位certPath的值为conf。接下来我们需要把SDK用于连接节点的证书放到指定的conf目录下。

# 假设我们将asset-app放在~/fisco目录下 进入~/fisco目录
$ cd ~/fisco
# 创建放置证书的文件夹
$ mkdir -p asset-app/src/test/resources/conf
# 拷贝节点证书到项目的资源目录
$ cp -r nodes/127.0.0.1/sdk/* asset-app/src/test/resources/conf
# 若在IDE直接运行,拷贝证书到resources路径
$ mkdir -p asset-app/src/main/resources/conf
$ cp -r nodes/127.0.0.1/sdk/* asset-app/src/main/resources/conf

这里注意!!!假设我们将 asset-app 放在~fisco目录下

一开始的默认地址并不是 fisco !!! 

5. 业务逻辑开发 

上面我们已经介绍了如何在自己的项目中引入以及配置Java SDK,本节介绍如何通过Java程序调用合约,同样以示例的资产管理说明。

第一步.将3编译好的Java合约引入项目中

cd ~/fisco  
# 将编译好的合约Java类引入项目中。
cp console/contracts/sdk/java/org/fisco/bcos/asset/contract/Asset.java asset-app/src/main/java/org/fisco/bcos/asset/contract/Asset.java

(官方图) 

 第二步.开发业务逻辑

在路径/src/main/java/org/fisco/bcos/asset/client目录下,创建AssetClient.java类,通过调用Asset.java实现对合约的部署与调用

 这里出现了一个小问题:client 是我自己新建的,但是当要创建AssetClient.java类的时候,提示 client是只读文件,使用了网上的方法也不管用,后面我想到这也是ubuntu里的文件呀,就去终端看了下,发现文件夹确实是带着小锁的。解决方法

AssetClient.java 代码如下:

package org.fisco.bcos.asset.client;

import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.math.BigInteger;
import java.util.List;
import java.util.Properties;
import org.fisco.bcos.asset.contract.Asset;
import org.fisco.bcos.sdk.BcosSDK;
import org.fisco.bcos.sdk.abi.datatypes.generated.tuples.generated.Tuple2;
import org.fisco.bcos.sdk.client.Client;
import org.fisco.bcos.sdk.crypto.keypair.CryptoKeyPair;
import org.fisco.bcos.sdk.model.TransactionReceipt;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.core.io.ClassPathResource;
import org.springframework.core.io.Resource;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;

public class AssetClient 
    static Logger logger = LoggerFactory.getLogger(AssetClient.class);

    private BcosSDK bcosSDK;
    private Client client;
    private CryptoKeyPair cryptoKeyPair;

    public void initialize() throws Exception 
        @SuppressWarnings("resource")
        ApplicationContext context =
                new ClassPathXmlApplicationContext("classpath:applicationContext.xml");
        bcosSDK = context.getBean(BcosSDK.class);
        client = bcosSDK.getClient(1);
        cryptoKeyPair = client.getCryptoSuite().createKeyPair();
        client.getCryptoSuite().setCryptoKeyPair(cryptoKeyPair);
        logger.debug("create client for group1, account address is " + cryptoKeyPair.getAddress());
    

    public void deployAssetAndRecordAddr() 

        try 
            Asset asset = Asset.deploy(client, cryptoKeyPair);
            System.out.println(
                    " deploy Asset success, contract address is " + asset.getContractAddress());

            recordAssetAddr(asset.getContractAddress());
         catch (Exception e) 
            // TODO Auto-generated catch block
            // e.printStackTrace();
            System.out.println(" deploy Asset contract failed, error message is  " + e.getMessage());
        
    

    public void recordAssetAddr(String address) throws FileNotFoundException, IOException 
        Properties prop = new Properties();
        prop.setProperty("address", address);
        final Resource contractResource = new ClassPathResource("contract.properties");
        FileOutputStream fileOutputStream = new FileOutputStream(contractResource.getFile());
        prop.store(fileOutputStream, "contract address");
    

    public String loadAssetAddr() throws Exception 
        // load Asset contact address from contract.properties
        Properties prop = new Properties();
        final Resource contractResource = new ClassPathResource("contract.properties");
        prop.load(contractResource.getInputStream());

        String contractAddress = prop.getProperty("address");
        if (contractAddress == null || contractAddress.trim().equals("")) 
            throw new Exception(" load Asset contract address failed, please deploy it first. ");
        
        logger.info(" load Asset address from contract.properties, address is ", contractAddress);
        return contractAddress;
    

    public void queryAssetAmount(String assetAccount) 
        try 
            String contractAddress = loadAssetAddr();
            Asset asset = Asset.load(contractAddress, client, cryptoKeyPair);
            Tuple2<BigInteger, BigInteger> result = asset.select(assetAccount);
            if (result.getValue1().compareTo(new BigInteger("0")) == 0) 
                System.out.printf(" asset account %s, value %s \\n", assetAccount, result.getValue2());
             else 
                System.out.printf(" %s asset account is not exist \\n", assetAccount);
            
         catch (Exception e) 
            // TODO Auto-generated catch block
            // e.printStackTrace();
            logger.error(" queryAssetAmount exception, error message is ", e.getMessage());

            System.out.printf(" query asset account failed, error message is %s\\n", e.getMessage());
        
    

    public void registerAssetAccount(String assetAccount, BigInteger amount) 
        try 
            String contractAddress = loadAssetAddr();

            Asset asset = Asset.load(contractAddress, client, cryptoKeyPair);
            TransactionReceipt receipt = asset.register(assetAccount, amount);
            List<Asset.RegisterEventEventResponse> response = asset.getRegisterEventEvents(receipt);
            if (!response.isEmpty()) 
                if (response.get(0).ret.compareTo(new BigInteger("0")) == 0) 
                    System.out.printf(
                            " register asset account success => asset: %s, value: %s \\n", assetAccount, amount);
                 else 
                    System.out.printf(
                            " register asset account failed, ret code is %s \\n", response.get(0).ret.toString());
                
             else 
                System.out.println(" event log not found, maybe transaction not exec. ");
            
         catch (Exception e) 
            // TODO Auto-generated catch block
            // e.printStackTrace();

            logger.error(" registerAssetAccount exception, error message is ", e.getMessage());
            System.out.printf(" register asset account failed, error message is %s\\n", e.getMessage());
        
    

    public void transferAsset(String fromAssetAccount, String toAssetAccount, BigInteger amount) 
        try 
            String contractAddress = loadAssetAddr();
            Asset asset = Asset.load(contractAddress, client, cryptoKeyPair);
            TransactionReceipt receipt = asset.transfer(fromAssetAccount, toAssetAccount, amount);
            List<Asset.TransferEventEventResponse> response = asset.getTransferEventEvents(receipt);
            if (!response.isEmpty()) 
                if (response.get(0).ret.compareTo(new BigInteger("0")) == 0) 
                    System.out.printf(
                            " transfer success => from_asset: %s, to_asset: %s, amount: %s \\n",
                            fromAssetAccount, toAssetAccount, amount);
                 else 
                    System.out.printf(
                            " transfer asset account failed, ret code is %s \\n", response.get(0).ret.toString());
                
             else 
                System.out.println(" event log not found, maybe transaction not exec. ");
            
         catch (Exception e) 
            // TODO Auto-generated catch block
            // e.printStackTrace();

            logger.error(" registerAssetAccount exception, error message is ", e.getMessage());
            System.out.printf(" register asset account failed, error message is %s\\n", e.getMessage());
        
    

    public static void Usage() 
        System.out.println(" Usage:");
        System.out.println(
                "\\t java -cp conf/:lib/*:apps/* org.fisco.bcos.asset.client.AssetClient deploy");
        System.out.println(
                "\\t java -cp conf/:lib/*:apps/* org.fisco.bcos.asset.client.AssetClient query account");
        System.out.println(
                "\\t java -cp conf/:lib/*:apps/* org.fisco.bcos.asset.client.AssetClient register account value");
        System.out.println(
                "\\t java -cp conf/:lib/*:apps/* org.fisco.bcos.asset.client.AssetClient transfer from_account to_account amount");
        System.exit(0);
    

    public static void main(String[] args) throws Exception 
        if (args.length < 1) 
            Usage();
        

        AssetClient client = new AssetClient();
        client.initialize();

        switch (args[0]) 
            case "deploy":
                client.deployAssetAndRecordAddr();
                break;
            case "query":
                if (args.length < 2) 
                    Usage();
                
                client.queryAssetAmount(args[1]);
                break;
            case "register":
                if (args.length < 3) 
                    Usage();
                
                client.registerAssetAccount(args[1], new BigInteger(args[2]));
                break;
            case "transfer":
                if (args.length < 4) 
                    Usage();
                
                client.transferAsset(args[1], args[2], new BigInteger(args[3]));
                break;
            default:
            
                Usage();
            
        
        System.exit(0);
    

在 asset-app/tool目录下添加一个调用AssetClient的脚本 asset_run.sh

#!/bin/bash 

function usage() 

    echo " Usage : "
    echo "   bash asset_run.sh deploy"
    echo "   bash asset_run.sh query    asset_account "
    echo "   bash asset_run.sh register asset_account asset_amount "
    echo "   bash asset_run.sh transfer from_asset_account to_asset_account amount "
    echo " "
    echo " "
    echo "examples : "
    echo "   bash asset_run.sh deploy "
    echo "   bash asset_run.sh register  Asset0  10000000 "
    echo "   bash asset_run.sh register  Asset1  10000000 "
    echo "   bash asset_run.sh transfer  Asset0  Asset1 11111 "
    echo "   bash asset_run.sh query Asset0"
    echo "   bash asset_run.sh query Asset1"
    exit 0


    case $1 in
    deploy)
            [ $# -lt 1 ] &&  usage; 
            ;;
    register)
            [ $# -lt 3 ] &&  usage; 
            ;;
    transfer)
            [ $# -lt 4 ] &&  usage; 
            ;;
    query)
            [ $# -lt 2 ] &&  usage; 
            ;;
    *)
        usage
            ;;
    esac

    java -Djdk.tls.namedGroups="secp256k1" -cp 'apps/*:conf/:lib/*' org.fisco.bcos.asset.client.AssetClient $@

接着,配置好 log。在asset-app/src/test/resources目录下创建log4j.properties

### set log levels ###
log4j.rootLogger=DEBUG, file

### output the log information to the file ###
log4j.appender.file=org.apache.log4j.DailyRollingFileAppender
log4j.appender.file.DatePattern='_'yyyyMMddHH'.log'
log4j.appender.file.File=./log/sdk.log
log4j.appender.file.Append=true
log4j.appender.file.filter.traceFilter=org.apache.log4j.varia.LevelRangeFilter
log4j.appender.file.layout=org.apache.log4j.PatternLayout
log4j.appender.file.layout.ConversionPattern=[%p] [%-dyyyy-MM-dd HH:mm:ss] %C1.%M(%L) | %m%n

###output the log information to the console ###
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.Target=System.out
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=[%p] [%-dyyyy-MM-dd HH:mm:ss] %C1.%M(%L) | %m%n

 接着,通过配置gradle中的Jar命令,指定复制和编译任务。并引入日志库,在asset-app/src/test/resources目录下,创建一个空的contract.properties文件,用于应用在运行时存放合约地址。

(官方图片)

dependencies 
    testCompile group: 'junit', name: 'junit', version: '4.12'
    compile ("org.fisco-bcos.java-sdk:fisco-bcos-java-sdk:2.9.0")
    compile spring
    compile ('org.slf4j:slf4j-log4j12:1.7.25')
    runtime ('org.slf4j:slf4j-log4j12:1.7.25')

jar 
    destinationDir file('dist/apps')
    archiveName project.name + '.jar'
    exclude '**/*.xml'
    exclude '**/*.properties'
    exclude '**/*.crt'
    exclude '**/*.key'

    doLast 
        copy 
            from configurations.runtime
            into 'dist/lib'
        
        copy 
            from file('src/test/resources/')
            into 'dist/conf'
        
        copy 
            from file('tool/')
            into 'dist/'
        
        copy 
            from file('src/test/resources/contract')
            into 'dist/contract'
        
    

 至此,我们已经完成了这个应用的开发。

6. 运行应用

至此我们已经介绍使用区块链开发资产管理应用的所有流程并实现了功能,接下来可以运行项目,测试功能是否正常。

1.编译

# 切换到项目目录
$ cd ~/fisco/asset-app
# 编译项目
$ ./gradlew build

注意上面的 切换到项目目录,自己的 asset-app 在哪 ,就切到哪

 编译成功之后,将在项目根目录下生成 dist目录。dist目录下有一个asset_run.sh脚本,简化项目运行。现在开始一一验证本文开始定下的需求。

2.部署Asset.sol合约

# 进入dist目录
$ cd dist
$ bash asset_run.sh deploy

这里我出现了一些警告,我看有人说是jdk版本过高,无伤大雅,以后再看吧

 3.注册资产

给张三注册资产10万元 

$ bash asset_run.sh register zhangsan 100000

 注册成功,张三拥有资产10万元

 同上,也给张五注册资产10万元

$ bash asset_run.sh register Bob 100000
Register account successfully => account: Bob, value: 100000

4.查询资产

查询张三的资产有多少

$ bash asset_run.sh query zhangsan

张三拥有10万资产

 张五同上。

5.资产转移

张三转给张五 5万 块

$ bash asset_run.sh transfer zhangsan zhangwu  50000

转移成功 

 检查张三还剩多少钱

$ bash asset_run.sh query zhangsan

张三还剩 5 万。 

 检查张五还有多少钱

$ bash asset_run.sh query zhangwu

张五有 15 万 

区块链实战区块链在哪些行业得到了应用

...、简介二、知识点区块链应用场景数字金融:微众 FISCOBCOS北京互联网法院:天平链食品安全:京东智臻链三、应用实例1、微众 FISCOBCOS2、北京互联网法院天平链3、食品安全,京东智臻链一、简介区块链应用主要... 查看详情

区块链供应链金融实战2(代码片段)

...复杂的区块链供应链金融应用打下基础。我们在这里利用FiscoBcos提供的CRUD接口,来开发智能合约,供Web服务器来调用,从而实现各种复杂的业务逻辑。之所以选择CRUD接口& 查看详情

区块链入门教程--fiscobcos单机四节点联盟链安装(代码片段)

...目录,下载安装脚本4.4搭建单群组4节点联盟链4.5启动FISCOBCOS链4.6检查进程4.7检查日志输出5.任务总结6.任务拓展1.任务背景要学习区块链,首先得有一个区块链系统去操作、学习、研究,FISCOBCOS区块链系统是一个应用... 查看详情

区块链项目实战-使用以太坊/智能合约solidity,全栈开发区块链借贷记账小应用,含完整源码(代码片段)

本文使用区块链平台以太坊+智能合约实现一个区块链记账的功能,具体为:借款人和贷款人以及数额被记录在区块链中。使用区块链地址来表示借款人或者贷款人。若一个借款人多次向一个贷款人借钱,更新所有... 查看详情

fiscobcos(二十八)———使用javasdk与区块链交互(代码片段)

.../blog.csdn.net/weixin_46457946/article/details/1232435132、搭建单群组FISCOBCOS联盟链https://blog.csdn.net/weixin_46457946/article/details/1225463343、配置及使用控制台https://blog.csdn.net/weixin_46457946/article/details/122551128二、创建一个Gradle应用1、新建项目2、导... 查看详情

fiscobcos区块链固定出块节点方法

请教一下开发者,在pbft共识下,我想固定出块节点始终是一个,我只修改getLeader函数可以吗?有其它固定出块节点的方法吗那就让单独的那个节点作为共识节点,其他节点作为观察节点这样比较合理 查看详情

区块链技术:truffle开发入门

以太坊是区块链开发领域最好的编程平台,而truffle是以太坊(Ethereum)最受欢迎的一个开发框架,这是我们第一篇区块链技术文章介绍truffle的原因,实战是最重要的事情,这篇文章不讲原理,只搭建环境,运行第一个区块链程... 查看详情

fiscobcos区块链查看代码版本号

  查看详情

fisco-bcosresources(代码片段)

...发。该项目是基于Web3SDK的springboot版本的示例项目。提供FISCOBCOS区块链应用开发的基本框架和基本的测试案例,帮助开发者基于 FISCOBCOS区块链快速进行应用开发。此版本只支持FISCOBCOS2.0。项目文档和地址区块链开发工具集Web3... 查看详情

fiscobcos区块链设置交易最晚处理区块高度

     查看详情

fiscobcos区块链配置文件位置

./nodes/127.0.0.1/node0/conf/group.1.genesis  查看详情

区块链入门与去中心化应用实战

...的主要内容,希望通过这章的学习,可以让大家对课程有一个整体的,清晰的了解。第2章区块链技术的核心概念和原理本章会讲解比特币的由来,比特币概念及原理,如:账本如何验证,如何确定账户所有权问题,如何保护用户... 查看详情

学习hyperledgerfabric实战联盟链

...块链框架及工具,以及Fabric相关的项目介绍,并搭建了第一个Fabric区块链网络,让大家能够快速体验区块链的魅力第3章HyperledgerFabric系统架构本章概括了Fabric的体系架构,包括 查看详情

区块链应用:nas星云链入门之从零开发第一个dapp

...一遍,想一遍不如做一遍。这不最近星云链nebulas正有开发者激励计划,每提交一个应用都可以获得奖励,所以正好借此机会,开发第一个DAPP,并且理解所谓的DAPP到底是一个什么样的东西。这篇文章几乎是DAPP... 查看详情

区块链应用:nas星云链入门之从零开发第一个dapp

前言本文同步自wing的地方酒馆无论你是否想了解NAS,只要你想了解区块链或者DAPP都可以看这篇文章,因为很多概念是一样的。应该有很多小伙伴和我一样,一直想去入手学习区块链,但是总无从下手,有些概... 查看详情

区块链技术:truffle开发入门(代码片段)

以太坊是区块链开发领域最好的编程平台,而truffle是以太坊(Ethereum)最受欢迎的一个开发框架,这是我们第一篇区块链技术文章介绍truffle的原因,实战是最重要的事情,这篇文章不讲原理,只搭建环... 查看详情

一个区块链小白的自传

一个区块链小白的自传                作者:山石 我是一个小白,一个区块链方面的小白,在我之前的生活中从来没听说过区块链这个概念。直到有一天我朋友跟我介... 查看详情

一个区块链小白的自传

一个区块链小白的自传                作者:山石 我是一个小白,一个区块链方面的小白,在我之前的生活中从来没听说过区块链这个概念。直到有一天我朋友跟我介... 查看详情