FISCO BCOS开发第一个区块链应用--小白实战

Posted 背不过单词选手

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了FISCO BCOS开发第一个区块链应用--小白实战相关的知识,希望对你有一定的参考价值。

官方链接

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

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 万 

Fisco-bsco 开发联盟链 账户之间的转账

Fisco-bsco 开发联盟链 账户之间的转账

参考:开发第一个区块链应用 — FISCO BCOS v2.9.0 文档 (fisco-bcos-documentation.readthedocs.io)

前提:Fisco-bcos节点开启,控制台已搭建

步骤:

1. 开发源码

# 进入console/contracts目录
cd ~/fisco/console/contracts/solidity
# 创建Asset.sol合约文件
vi Asset.sol
​
# 将Assert.sol合约内容写入。
# 并键入wq保存退出。

Asset.sol:

pragma solidity ^0.4.24;
​
import "./Table.sol";
​
contract Asset 
    // event
    event RegisterEvent(int256 ret, string account, uint256 asset_value);
    event TransferEvent(int256 ret, string from_account, string to_account, uint256 amount);
​
    constructor() public 
        // 构造函数中创建t_asset表
        createTable();
    
​
    function createTable() private 
        TableFactory tf = TableFactory(0x1001);
        // 资产管理表, key : account, field : asset_value
        // |  资产账户(主键)      |     资产金额       |
        // |-------------------- |-------------------|
        // |        account      |    asset_value    |
        // |---------------------|-------------------|
        //
        // 创建表
        tf.createTable("t_asset", "account", "asset_value");
    
​
    function openTable() private returns(Table) 
        TableFactory tf = TableFactory(0x1001);
        Table table = tf.openTable("t_asset");
        return table;
    
​
    /*
    描述 : 根据资产账户查询资产金额
    参数 :
            account : 资产账户
​
    返回值:
            参数一: 成功返回0, 账户不存在返回-1
            参数二: 第一个参数为0时有效,资产金额
    */
    function select(string account) public constant returns(int256, uint256) 
        // 打开表
        Table table = openTable();
        // 查询
        Entries entries = table.select(account, table.newCondition());
        uint256 asset_value = 0;
        if (0 == uint256(entries.size())) 
            return (-1, asset_value);
         else 
            Entry entry = entries.get(0);
            return (0, uint256(entry.getInt("asset_value")));
        
    
​
    /*
    描述 : 资产注册
    参数 :
            account : 资产账户
            amount  : 资产金额
    返回值:
            0  资产注册成功
            -1 资产账户已存在
            -2 其他错误
    */
    function register(string account, uint256 asset_value) public returns(int256)
        int256 ret_code = 0;
        int256 ret= 0;
        uint256 temp_asset_value = 0;
        // 查询账户是否存在
        (ret, temp_asset_value) = select(account);
        if(ret != 0) 
            Table table = openTable();
​
            Entry entry = table.newEntry();
            entry.set("account", account);
            entry.set("asset_value", int256(asset_value));
            // 插入
            int count = table.insert(account, entry);
            if (count == 1) 
                // 成功
                ret_code = 0;
             else 
                // 失败? 无权限或者其他错误
                ret_code = -2;
            
         else 
            // 账户已存在
            ret_code = -1;
        
​
        emit RegisterEvent(ret_code, account, asset_value);
​
        return ret_code;
    
​
    /*
    描述 : 资产转移
    参数 :
            from_account : 转移资产账户
            to_account : 接收资产账户
            amount : 转移金额
    返回值:
            0  资产转移成功
            -1 转移资产账户不存在
            -2 接收资产账户不存在
            -3 金额不足
            -4 金额溢出
            -5 其他错误
    */
    function transfer(string from_account, string to_account, uint256 amount) public returns(int256) 
        // 查询转移资产账户信息
        int ret_code = 0;
        int256 ret = 0;
        uint256 from_asset_value = 0;
        uint256 to_asset_value = 0;
​
        // 转移账户是否存在?
        (ret, from_asset_value) = select(from_account);
        if(ret != 0) 
            ret_code = -1;
            // 转移账户不存在
            emit TransferEvent(ret_code, from_account, to_account, amount);
            return ret_code;
​
        
​
        // 接受账户是否存在?
        (ret, to_asset_value) = select(to_account);
        if(ret != 0) 
            ret_code = -2;
            // 接收资产的账户不存在
            emit TransferEvent(ret_code, from_account, to_account, amount);
            return ret_code;
        
​
        if(from_asset_value < amount) 
            ret_code = -3;
            // 转移资产的账户金额不足
            emit TransferEvent(ret_code, from_account, to_account, amount);
            return ret_code;
        
​
        if (to_asset_value + amount < to_asset_value) 
            ret_code = -4;
            // 接收账户金额溢出
            emit TransferEvent(ret_code, from_account, to_account, amount);
            return ret_code;
        
​
        Table table = openTable();
​
        Entry entry0 = table.newEntry();
        entry0.set("account", from_account);
        entry0.set("asset_value", int256(from_asset_value - amount));
        // 更新转账账户
        int count = table.update(from_account, entry0, table.newCondition());
        if(count != 1) 
            ret_code = -5;
            // 失败? 无权限或者其他错误?
            emit TransferEvent(ret_code, from_account, to_account, amount);
            return ret_code;
        
​
        Entry entry1 = table.newEntry();
        entry1.set("account", to_account);
        entry1.set("asset_value", int256(to_asset_value + amount));
        // 更新接收账户
        table.update(to_account, entry1, table.newCondition());
​
        emit TransferEvent(ret_code, from_account, to_account, amount);
​
        return ret_code;
    

运行ls命令,确保Asset.solTable.sol在目录~/fisco/console/contracts/solidity下。

Table.sol 在搭建控制台的时候自动创建

2.编译智能合约

# 切换到fisco/console/目录
cd ~/fisco/console/
​
# 若控制台版本大于等于2.8.0,编译合约方法如下:(可通过bash sol2java.sh -h命令查看该脚本使用方法)
bash sol2java.sh -p org.fisco.bcos.asset.contract
​
# 若控制台版本小于2.8.0,编译合约(后面指定一个Java的包名参数,可以根据实际项目路径指定包名)如下:
./sol2java.sh org.fisco.bcos.asset.contract

3.创建区块链应用项目

  1. 确认jdk以及集成环境

 确认您当前的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)
​
  1. 进入IntelliJ IDE官网下载社区版即可,安装解压

  2. 快速搭建

     cd ~/fisco
    $ curl -#LO https://github.com/FISCO-BCOS/LargeFiles/raw/master/tools/asset-app.tar.gz
    # 解压得到Java工程项目asset-app
    $ tar -zxf asset-app.tar.gz
    ​
  3. 将项目用IDE打开,打开终端

    # 假设我们将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

4.运行

  • 编译

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

    # 进入dist目录
    $ cd dist
    $ bash asset_run.sh deploy
    Deploy Asset successfully, contract address is 0xd09ad04220e40bb8666e885730c8c460091a4775
  • 注册资产

    $ bash asset_run.sh register Alice 100000
    Register account successfully => account: Alice, value: 100000
    $ bash asset_run.sh register Bob 100000
    Register account successfully => account: Bob, value: 100000
  • 查询资产

    $ bash asset_run.sh query Alice
    account Alice, value 100000
    $ bash asset_run.sh query Bob
    account Bob, value 100000
  • 资产转移

    $ bash asset_run.sh transfer Alice Bob  50000
    Transfer successfully => from_account: Alice, to_account: Bob, amount: 50000
    $ bash asset_run.sh query Alice
    account Alice, value 50000
    $ bash asset_run.sh query Bob
    account Bob, value 150000

 

 

以上是关于FISCO BCOS开发第一个区块链应用--小白实战的主要内容,如果未能解决你的问题,请参考以下文章

区块链入门教程--FISCO BCOS单机四节点联盟链安装

Fisco-bsco 开发联盟链 账户之间的转账

FISCO BCOS区块链固定出块节点 方法

FISCO BCOS区块链固定出块节点 方法

FISCO BCOS 区块链 查看代码版本号

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