FISCO BCOS | 构建第一个区块链应用程序

本章将介绍基于FISCO BCOS区块链的业务应用场景开发的全流程。介绍包括业务场景分析、合约设计实现、合约编译、区块链开发等。最后,我们介绍一个应用模块实现,即通过我们提供的Java SDK实现对区块链上合约的调用访问。

本教程要求用户熟悉Linux操作环境,具备Java开发的基本技能,能够使用Gradle工具,熟悉Solidity语法。

通过本教程,您将了解以下内容:

  1. 如何以契约的形式表达业务场景的逻辑
  2. 如何将Solidity合约转换为Java类
  3. 如何配置Java开发工具包
  4. 如何构建应用程序并将Java SDK集成到应用程序工程中
  5. 如何通过Java SDK调用合约接口,并理解其原理

本教程中提供了该示例的完整项目源代码,用户可以基于它快速开发自己的应用程序。

示例应用程序要求

区块链自然是防篡改和可追溯的。这些特点使其对金融部门更具吸引力。本文将提供资产管理开发的简单示例,并最终实现以下功能:

  • 能够在区块链上注册资产
  • 能够从不同的账户转移资金
  • 能够检查账户中的资产数量

合同设计和实施

在区块链上开发应用时,为了结合业务需求,首先需要设计相应的智能合约,确定合约需要的存储数据,并在此基础上确定智能合约提供的接口。最后,具体实现每个接口。

存储设计

FISCO BCOS提供了合约CRUD接口开发模型,可以通过合约创建表,并对创建的表进行添加、删除和修改。对于此应用程序,我们需要设计一个用于存储资产管理的表。该表的字段如下所示:t_asset

  • 账户:主键、资产账户(字符串类型)
  • asset_value:资产金额(UINT256型)

account是主键,是操作表时需要传递的字段。区块链根据主键字段查询表中的匹配记录。表的示例如下:t_assett_asset

图片

界面设计

根据业务的设计目标,需要实现资产登记、转账、查询功能。对应函数的接口如下:

// query the amount of assets
function select(string account) public constant returns(int256, uint256)
// asset registration
function register(string account, uint256 amount) public returns(int256)
// asset transfer
function transfer(string from_asset_account, string to_asset_account, uint256 amount) public returns(int256)

完整来源

pragma solidity ^0.4.24;import "./Table.sol";contract Asset {// eventevent RegisterEvent(int256 ret, string account, uint256 asset_value);event TransferEvent(int256 ret, string from_account, string to_account, uint256 amount);constructor() public {// create a t_asset table in the constructorcreateTable();}function createTable() private {TableFactory tf = TableFactory(0x1001);// asset management table, key : account, field : asset_value// |  account(primary key)   |  amount       |// |-------------------- |-------------------|// |        account      |    asset_value    |// |---------------------|-------------------|//// create tabletf.createTable("t_asset", "account", "asset_value");}function openTable() private returns(Table) {TableFactory tf = TableFactory(0x1001);Table table = tf.openTable("t_asset");return table;}/*description: query asset amount according to asset accountparameter:account: asset accountreturn value:parameter1: successfully returns 0, the account does not exist and returns -1parameter2: valid when the first parameter is 0, the amount of assets*/function select(string account) public constant returns(int256, uint256) {// open tableTable table = openTable();// queryEntries 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")));}}/*description : asset registrationparameter :account : asset accountamount  : asset amountreturn value:0  regist successfully-1 asset account already exists-2 other error*/function register(string account, uint256 asset_value) public returns(int256){int256 ret_code = 0;int256 ret= 0;uint256 temp_asset_value = 0;// to query whather the account exists(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));// insertint count = table.insert(account, entry);if (count == 1) {// trueret_code = 0;} else {// false. no permission or other errorret_code = -2;}} else {// account already existsret_code = -1;}emit RegisterEvent(ret_code, account, asset_value);return ret_code;}/*description : asset transferparameter :from_account : transferred asset accountto_account :received asset accountamount : transferred amountreturn value:0  transfer asset successfully-1 transfe asset account does not exist-2 receive asset account does not exist-3 amount is insufficient-4 amount is excessive-5 other error*/function transfer(string from_account, string to_account, uint256 amount) public returns(int256) {// query transferred asset account informationint ret_code = 0;int256 ret = 0;uint256 from_asset_value = 0;uint256 to_asset_value = 0;// whather transferred asset account exists?(ret, from_asset_value) = select(from_account);if(ret != 0) {ret_code = -1;// not existemit TransferEvent(ret_code, from_account, to_account, amount);return ret_code;}// whather received asset account exists?(ret, to_asset_value) = select(to_account);if(ret != 0) {ret_code = -2;// not existemit TransferEvent(ret_code, from_account, to_account, amount);return ret_code;}if(from_asset_value < amount) {ret_code = -3;// amount of transferred asset account is insufficientemit TransferEvent(ret_code, from_account, to_account, amount);return ret_code;}if (to_asset_value + amount < to_asset_value) {ret_code = -4;// amount of received asset account is excessiveemit 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));// update transferred accountint count = table.update(from_account, entry0, table.newCondition());if(count != 1) {ret_code = -5;// false? no permission or other error?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));// update received accounttable.update(to_account, entry1, table.newCondition());emit TransferEvent(ret_code, from_account, to_account, amount);return ret_code;}
}

注意:合约的实现需要引入FISCO BCOS提供的系统合约接口文件。系统合约文件的接口由底层FISCO BCOS实现。当业务合约需要操作CRUD接口时,需要引入接口合约文件。合同详细接口参考在这里:

​​https://fisco-bcos-documentation.readthedocs.io/en/latest/docs/manual/smart_contract.html#crud​​

Asset.solTable.solTable.sol

合同编制

在上一节中,我们根据业务需求设计了合约的存储和接口,并将它们完整地实现了。但是,Java程序不能直接调用Solidity合约。Solidity合约文件需要先编译成Java文件。Asset.sol

控制台提供了一个编译工具,用于将合约文件存储在目录中。使用控制台目录中提供的脚本进行编译,如下所示:

Asset.solconsole/contract/soliditysol2java.sh

$ mkdir -p ~/fisco
# download console
$ cd ~/fisco && curl -#LO https://github.com/FISCO-BCOS/console/releases/download/v2.9.2/download_console.sh && bash download_console.sh
# switch to the fisco/console/ directory
$ cd ~/fisco/console/
# compile the contract, specify a Java package name parameter later, you can specify the package name according to the actual project path.
$ ./sol2java.sh -p org.fisco.bcos.asset.contract

操作成功后,java、abi、bin目录将生成如下图。console/contracts/sdkdirectory

|-- abi # The generated abi directory, which stores the abi file generated by Solidity contract compilation.
|   |-- Asset.abi
|   |-- Table.abi
|-- bin # The generated bin directory, which stores the bin file generated by Solidity contract compilation.
|   |-- Asset.bin
|   |-- Table.bin
|-- contracts # The source code file that stores Solidity contract. Copy the contract that needs to be compiled to this directory.
|   |-- Asset.sol # A copied Asset.sol contract, depends on Table.sol
|   |-- Table.sol # The contract interface file that implements the CRUD operation
|-- java  # Storing compiled package path and Java contract file
|   |-- org
|        |--fisco
|             |--bcos
|                  |--asset
|                       |--contract
|                             |--Asset.java  # Java file generated by the Asset.sol contract
|                             |--Table.java  # Java file generated by the Table.sol contract
|-- sol2java.sh

包路径目录在java目录中生成。该目录包含两个文件和,其中是Java应用程序调用Asset.sol合约所需的文件。

org/fisco/bcos/asset/contract/Asset.javaTable.javaAsset.java

Asset.java的主界面:

package org.fisco.bcos.asset.contract;public class Asset extends Contract {// Asset.sol contract  transfer interface generationpublic TransactionReceipt transfer(String from_account, String to_account, BigInteger amount);// Asset.sol contract  register interface generationpublic TransactionReceipt register(String account, BigInteger asset_value);// Asset.sol contract  select interface generationpublic Tuple2<BigInteger, BigInteger> select(String account) throws ContractException;// Load the Asset contract address, to generate Asset objectpublic static Asset load(String contractAddress, Client client, CryptoKeyPair credential);// Deploy Assert.sol contract, to generate Asset objectpublic static Asset deploy(Client client, CryptoKeyPair credential) throws ContractException;
}

加载和部署函数用于构造Asset对象,其他接口用于调用相应solidity协定的接口。具体用法将在下面介绍。

开发工具包配置

我们为开发提供了一个Java工程项目。首先,获取Java工程项目:

$ mkdir -p ~/fisco
# get the Java project project archive
$ cd ~/fisco
$ curl -#LO https://github.com/FISCO-BCOS/LargeFiles/raw/master/tools/asset-app.tar.gz
# extract the Java project project asset-app directory
$ tar -zxf asset-app.tar.gz

如果资产app.tar.gz由于网络问题长时间无法下载,请尝试:

curl-#LOhttps://osp-1257653870.cos.ap-guangzhou.myqcloud.com/FISCO-BCOS/FISCO-BCOS/tools/asset-app.tar.gz

资产应用项目的目录结构如下:

|-- build.gradle // gradle configuration file
|-- gradle
|   |-- wrapper
|       |-- gradle-wrapper.jar //  related code implementation for downloading Gradle
|       |-- gradle-wrapper.properties //  Configuration information used by the wrapper, such as the version of gradle
|-- gradlew // shell script for executing wrapper commands under Linux or Unix
|-- gradlew.bat // batch script for executing wrapper commands under Windows
|-- src
|   |-- main
|   |   |-- java
|   |         |-- org
|   |             |-- fisco
|   |                   |-- bcos
|   |                         |-- asset
|   |                               |-- client // the client calling class
|   |                                      |-- AssetClient.java
|   |                               |-- contract // the Java contract class
|   |                                      |-- Asset.java
|   |-- test
|       |-- resources // resource files
|           |-- applicationContext.xml // project configuration file
|           |-- contract.properties // file that stores the deployment contract address
|           |-- log4j.properties // log configuration file
|           |-- contract // Solidity contract files
|                   |-- Asset.sol
|                   |-- Table.sol
|
|-- tool|-- asset_run.sh // project running script

项目介绍Java SDK

该项目的文件已引入Java SDK,无需修改。介绍方法如下:

  • 您需要将maven远程存储库添加到文件中:build.gradle
repositories {mavenCentral()maven {url "http://maven.aliyun.com/nexus/content/groups/public/"}maven { url "https://oss.sonatype.org/content/repositories/snapshots" }
}

  • 介绍Java SDKjar包
compile ('org.fisco-bcos.java-sdk:fisco-bcos-java-sdk:2.7.2')

证书和配置文件

  • 区块链节点证书配置

复制区块链节点对应的SDK证书

# go to the ~ directory
# copy the node certificate to the project's resource directory
$ cd ~/fisco
$ cp -r nodes/127.0.0.1/sdk/* asset-app/src/test/resources/conf
# if you want to run this app in IDE, copy the certificate to the main resource directory
$ mkdir -p asset-app/src/main/resources/conf
$ cp -r nodes/127.0.0.1/sdk/* asset-app/src/main/resources/conf

  • 应用程序上下文.xml

注意:

如果链中设置的channel_listen_ip(如果节点版本低于v2.3.0,勾选listen_ip)为127.0.0.1或0.0.0.0,channel_listen_port为20200,则无需修改配置。如果区块链节点的配置发生变化,则需要修改。

applicationContext.xmlapplicationContext.xml

业务发展

我们已经介绍了如何在您自己的项目中引入和配置Java SDK。本节介绍如何通过Java程序调用合约,以及一个示例资产管理说明。资产应用项目已包含示例的完整源代码,用户可以直接使用。现在介绍核心类的设计和实现。AssetClient

AssetClient.java:合约的部署和调用是通过调用来实现的,路径、初始化和调用过程都在这个类中。

Asset.java/src/main/java/org/fisco/bcos/asset/client

  • 初始化

初始化代码的主要功能是构造Web3j和凭证的对象,在创建相应的合约类对象(调用合约类的部署或加载函数)时需要使用这些对象。

@SuppressWarnings("resource")
ApplicationContext context =new ClassPathXmlApplicationContext("classpath:applicationContext.xml");
bcosSDK = context.getBean(BcosSDK.class);
// init the client that can send requests to the group one
client = bcosSDK.getClient(1);
// create the keyPair
cryptoKeyPair = client.getCryptoSuite().createKeyPair();
client.getCryptoSuite().setCryptoKeyPair(cryptoKeyPair);
logger.debug("create client for group1, account address is " + cryptoKeyPair.getAddress());

  • 构造协定类对象

合约对象可以使用部署或加载函数进行初始化,这些函数在不同场景下使用。前者适用于初始部署协定,后者在协定已部署且合约地址已知时使用。

// deploy contract
Asset asset = Asset.deploy(client, cryptoKeyPair);
// load contract address
Asset asset = Asset.load(contractAddress, client, cryptoKeyPair);

  • 接口调用

使用合约对象调用对应的接口,处理返回的结果。

// select interface callingTuple2<BigInteger, BigInteger> result = asset.select(assetAccount);
// register interface calling
TransactionReceipt receipt = asset.register(assetAccount, amount);
// transfer interface
TransactionReceipt receipt = asset.transfer(fromAssetAccount, toAssetAccount, amount);

运行

到目前为止,我们已经介绍了使用区块链的资产管理应用程序的所有流程并实现了这些功能。然后我们可以运行项目并测试函数是否正常。

  • 汇编
# switch to project directory
$ cd ~/asset-app
# compile project
$ ./gradlew build

编译成功后,将在项目根目录下生成目录。dist目录中有一个脚本来简化项目操作。现在,让我们首先验证本文中列出的要求。distasset_run.sh

  • 部署合约Asset.sol
# enter dist directory
$ 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

总结:到目前为止,我们已经通过合约开发、合约编译、SDK配置和业务开发,构建了基于FISCO BCOS联盟区块链的应用。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/155767.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

NCV6324CMTAATBG---车规级3MHz 2A 高效同步降压转换器

同步降压转换器&#xff1f; 是一种电源管理电路&#xff0c;它可以将输入电压转换为较低的输出电压。与传统的降压转换器相比&#xff0c;同步降压转换器具有更高的效率和更好的动态响应。 同步降压转换器的工作原理是通过控制开关管的导通和截止来实现电能的转换。在导通状…

Go语言入门心法(一)

一: go语言中变量认知 go语言中变量的定义: &#xff08;要想飞|先会走&#xff09;||&#xff08;翻身仗|抹遗憾 &#xff09;(1)go语言中变量认知升维(2)go语言中变量与强类型语言java类似,变量使用必须先声明后使用(3)go语言中变量标准的声明使用var关键字进行声明: var 变…

微信小程序通过 movable-area 做一个与vuedraggable相似的上下拖动排序控件

因为只是做个小案例 我就直接代码写page页面里了 其实很简单 组件稍微改一下就好了 wxss /* 设置movable-area的宽度 */ .area{width: 100%; }/* a b c 每条元素的样式 */ movable-view {width: 100%;background-color: red;height: 40px;line-height: 40px;color: #FFFFFF;tex…

如何进行pyhon的虚拟环境创建及管理

无论服务器或者本地&#xff0c;创建虚拟环境都是&#xff1a; 【Python】搭建虚拟环境_python创建虚拟环境_今天自洽了吗的博客-CSDN博客 虚拟环境绑定到项目 这个是运行环境&#xff0c;可以切换任意运行环境 如果是服务器上&#xff1a;可以先source xx/bin/active&#xf…

Python皮卡丘

系列文章 序号文章目录直达链接1浪漫520表白代码https://want595.blog.csdn.net/article/details/1306668812满屏表白代码https://want595.blog.csdn.net/article/details/1297945183跳动的爱心https://want595.blog.csdn.net/article/details/1295031234漂浮爱心https://want…

canvas基础2 -- 形状

七巧板 七巧板本质上就是 分别由几个直线 拼成一个个图形&#xff0c;再将这些图形结合起来 var tangram [{ p: [{ x: 0, y: 0 }, { x: 800, y: 0 }, { x: 400, y: 400 }], color: "#caff67" },{ p: [{ x: 0, y: 0 }, { x: 400, y: 400 }, { x: 0, y: 800 }], col…

1808_ChibiOS基本的架构介绍

全部学习汇总&#xff1a; GreyZhang/g_ChibiOS: I found a new RTOS called ChibiOS and it seems interesting! (github.com) 简单看了一下ChibiOS的架构介绍&#xff0c;感觉这种OS以及组件非常适合快速构建一个应用。这里做一个简单的资料整理。。 1. 不同于其他的OS&#…

JVM面试题:(三)GC和垃圾回收算法

GC: 垃圾回收算法&#xff1a; GC最基础的算法有三种&#xff1a; 标记 -清除算法、复制算法、标记-压缩算法&#xff0c;我们常用的垃圾回收器一般 都采用分代收集算法。 标记 -清除算法&#xff0c;“标记-清除”&#xff08;Mark-Sweep&#xff09;算法&#xff0c;如它的…

Vuex获取、修改参数值及异步数据处理

一、Vuex简介 1.1 vuex介绍 Vuex是专门为vue应用程序开发的状态管理模式&#xff0c;将组件的共享状态抽取出来&#xff0c;以一个全局单例模式进行管理&#xff0c;组件树构成一个巨大的视图&#xff0c;不管组件在树的何种位置&#xff0c;任何组件都能获取到状态和触发行为…

个股期权、商品期权、股指期权开户攻略(全网最全)

在进行个股期权、商品期权、股指期权交易之前&#xff0c;首先需要选择一个可靠的期权分仓平台。这样才能是想零门槛开通期权账户和交易权限&#xff0c;下文详细为大家科普个股期权、商品期权、股指期权开户攻略&#xff08;全网最全&#xff09; 一、期权分仓平台的选择 目前…

mac 版hadoop3.2.4 解决 Unable to load native-hadoop library 缺失文件

mac 版hadoop3.2.4或其他版本 Unable to load native-hadoop library 缺失文件 Native 包报错缺失&#xff1a; 1. hadoop-3.2.4/lib/native里加*.dylib 2. hadoop-3.2.4/etc/hadoop/hadoop-env.sh 加或修改 export HADOOP_OPTS"-Djava.library.path/Users/lvan/Documen…

Ubuntu下怎么配置vsftpd

2023年10月12日&#xff0c;周四中午 目录 首先要添加一个系统用户然后设置这个系统用户的密码给新创建的系统用户创建主目录启动vsftpd服务查看vsftpd服务的状态打开外界访问vsftpd服务所需的端口获取服务器的IP地址大功告成 首先要添加一个系统用户 useradd 用户名然后设置…

基于内存的分布式NoSQL数据库Redis(一)介绍与安装

文章目录 基于内存的分布式NoSQL数据库Redis知识点01&#xff1a;课程目标知识点02&#xff1a;NoSQL与RDBMS知识点03&#xff1a;Redis的功能与应用场景知识点04&#xff1a;Redis的Linux版单机部署后记 基于内存的分布式NoSQL数据库Redis 知识点01&#xff1a;课程目标 整体…

短视频账号矩阵系统源码saas===独立部署

前言&#xff1a; 短视频账号矩阵是指在不同的短视频平台上&#xff0c;一个个人或企业所拥有的账号数量和分布情况。由于不同的短视频平台受众人群和内容类型等因素不同&#xff0c;因此拥有更多账号可以在更广泛的受众中传播内容&#xff0c;提高曝光度和流量。短视频账号矩阵…

Air001 TIM1高级定时器单脉冲输出模式使用

Air001 TIM1高级定时器单脉冲输出模式使用 ✨本例程基于合宙官方提供的标准库以及Demo工程作为验证参考。&#x1f4cd;官方提供的SDK包资源&#xff1a;https://gitee.com/openLuat/luatos-soc-air001&#x1f33f;想了解STM32高级定时器单脉冲输出模式了解可以参考阅读:https…

多输入多输出 | MATLAB实现CNN-BiLSTM-Attention卷积神经网络-双向长短期记忆网络结合SE注意力机制的多输入多输出预测

MATLAB实现CNN-BiLSTM-Attention卷积神经网络-双向长短期记忆网络结合SE注意力机制的多输入多输出预测 目录 MATLAB实现CNN-BiLSTM-Attention卷积神经网络-双向长短期记忆网络结合SE注意力机制的多输入多输出预测预测效果基本介绍程序设计往期精彩参考资料 预测效果 基本介绍 C…

哈希的应用--位图和布隆过滤器

哈希的应用--位图和布隆过滤器 位图1. 位图概念2. 位图在实际中的应用3. 位图相似应用给定100亿个整数&#xff0c;如何找到只出现一次的整数&#xff1f;1个文件100亿int&#xff0c;1G内存&#xff0c;如何找到不超过2次的所有整数 布隆过滤器1. 布隆过滤器的提出2. 布隆过滤…

uniapp apple 苹果登录 离线本地打包

官方文档 uni-app官网 文档写的不全&#xff0c;没有写离线打包流程 加lib 签名里带 sign in with apple hbuilder开关 代码 测试代码&#xff0c;获取app里所有的provider uni.getProvider({service: oauth,success: function (res) {console.log(res.provider)uni.showT…

WIN10如何搭建自己的博客

引言&#xff1a; 路线说明&#xff1a; 在CSDN&#xff0c;博客园&#xff0c;简书等平台&#xff0c;可以直接在上面发表&#xff0c;用户交互做的好&#xff0c;写的文章百度也能搜索的到&#xff0c;这样速度也是最快的&#xff0c;不费心运营啥的。缺点是比较不自由&…

Elasticsearch 分片内部原理—近实时搜索、持久化变更

目录 一、近实时搜索 refresh API 二、持久化变更 flush API 一、近实时搜索 随着按段&#xff08;per-segment&#xff09;搜索的发展&#xff0c;一个新的文档从索引到可被搜索的延迟显著降低了。新文档在几分钟之内即可被检索&#xff0c;但这样还是不够快。 磁盘在这…