文章目录

    • 一、前言
    • 二、业务场景分析:简易资产管理系统
    • 三、智能合约设计与实现
      • 3.1 存储结构设计
      • 3.2 接口设计
      • 3.3 完整合约代码
    • 四、合约编译与Java接口生成
    • 五、SDK配置与项目搭建
      • 5.1 获取Java工程项目
      • 5.2 项目目录结构
      • 5.3 引入Web3SDK
      • 5.4 证书与配置文件
    • 六、业务开发:Java客户端实现
      • 6.1 核心类设计:AssetClient
        • 6.1.1 初始化
        • 6.1.2 合约对象创建
        • 6.1.3 接口调用
    • 七、项目运行与功能验证
      • 7.1 编译项目
      • 7.2 部署合约
      • 7.3 注册资产
      • 7.4 查询资产
      • 7.5 资产转移
    • 八、参考资料

一、前言

在区块链技术快速发展的今天,如何将其应用于实际业务场景成为开发者关注的重点。FISCO BCOS作为国产优秀的联盟链平台,为企业级区块链应用开发提供了强大支持。本文将跟随官方教程,详细记录基于FISCO BCOS构建第一个区块链应用的全过程,涵盖从业务分析到最终实现的完整流程。

二、业务场景分析:简易资产管理系统

区块链技术因其防篡改、可追溯的特性,在金融领域有着天然优势。本次实践选择开发一个简易的资产管理系统,主要实现以下核心功能:

  • 资产注册:在区块链上登记资产账户及初始金额
  • 资产转账:实现不同账户间的资产转移
  • 资产查询:查询指定账户的资产余额

这个场景虽然简单,但涵盖了区块链应用开发的核心流程,非常适合作为入门案例。

三、智能合约设计与实现

3.1 存储结构设计

FISCO BCOS提供了合约CRUD接口开发模式,允许通过合约创建表结构并进行数据操作。针对资产管理需求,设计了名为t_asset的表:

  • account:资产账户,作为主键(string类型)
  • asset_value:资产金额(uint256类型)

该表结构示例如下:

accountasset_value
Alice10000
Bob20000

3.2 接口设计

根据业务目标,定义了三个核心接口:

  • select(string account):查询资产金额
  • register(string account, uint256 amount):资产注册
  • transfer(string from_asset_account, string to_asset_account, uint256 amount):资产转移

3.3 完整合约代码

pragma solidity ^0.4.24;
import "./Table.sol";contract Asset {// 事件定义,用于记录关键操作event RegisterEvent(int256 ret, string account, uint256 asset_value);event TransferEvent(int256 ret, string from_account, string to_account, uint256 amount);constructor() public {// 构造函数中创建表createTable();}function createTable() private {TableFactory tf = TableFactory(0x1001);// 创建t_asset表,指定主键和字段tf.createTable("t_asset", "account", "asset_value");}function openTable() private returns (Table) {TableFactory tf = TableFactory(0x1001);Table table = tf.openTable("t_asset");return table;}// 查询资产金额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")));}}// 资产注册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;}// 资产转移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;}
}

注意:该合约依赖FISCO BCOS提供的系统合约Table.sol,实现对表的CRUD操作

四、合约编译与Java接口生成

Solidity合约无法被Java程序直接调用,需要通过控制台工具将其编译为Java类。具体步骤如下:

  1. Asset.solTable.sol放在console/contracts/solidity目录
  2. 执行编译脚本:
# 切换到console目录
cd ~/fisco/console/
# 编译合约,指定Java包名
./sol2java.sh org.fisco.bcos.asset.contract

编译成功后会在console/contracts/sdk目录生成:

  • abi目录:存放合约ABI文件
  • bin目录:存放合约字节码文件
  • java目录:存放生成的Java合约类

生成的Asset.java包含了与Solidity合约对应的Java接口:

package org.fisco.bcos.asset.contract;
public class Asset extends Contract {// 转账接口public RemoteCall<TransactionReceipt> transfer(String from_account, String to_account, BigInteger amount);// 注册接口public RemoteCall<TransactionReceipt> register(String account, BigInteger asset_value);// 查询接口public RemoteCall<Tuple2<BigInteger, BigInteger>> select(String account);// 加载合约public static Asset load(String contractAddress, Web3j web3j, Credentials credentials, ContractGasProvider contractGasProvider);// 部署合约public static RemoteCall<Asset> deploy(Web3j web3j, Credentials credentials, ContractGasProvider contractGasProvider);
}

五、SDK配置与项目搭建

5.1 获取Java工程项目

# 下载项目压缩包
cd ~
curl -LO https://github.com/FISCO-BCOS/LargeFiles/raw/master/tools/asset-app.tar.gz
# 解压项目
tar -zxf asset-app.tar.gz

5.2 项目目录结构

asset-app/
├── build.gradle          # Gradle配置文件
├── gradle/
│   ├── wrapper/
│   │   ├── gradle-wrapper.jar
│   │   └── gradle-wrapper.properties
├── gradlew               # Linux执行脚本
├── gradlew.bat           # Windows执行脚本
├── src/
│   ├── main/
│   │   ├── java/
│   │   │   └── org/
│   │   │       └── fisco/
│   │   │           └── bcos/
│   │   │               └── asset/
│   │   │                   ├── client/      # 客户端调用类
│   │   │                   │   └── AssetClient.java
│   │   │                   └── contract/    # 合约Java类
│   │   │                       └── Asset.java
│   │   └── resources/
│   │       ├── applicationContext.xml       # 项目配置文件
│   │       ├── contract.properties          # 合约地址配置
│   │       ├── log4j.properties             # 日志配置
│   │       └── contract/
│   │           ├── Asset.sol                # Solidity合约
│   │           └── Table.sol
├── tool/
│   └── asset_run.sh     # 运行脚本

5.3 引入Web3SDK

项目已在build.gradle中配置好Web3SDK依赖:

repositories {maven { url "http://maven.aliyun.com/nexus/content/groups/public/" }maven { url "https://dl.bintray.com/ethereum/maven/" }mavenCentral ()
}dependencies {compile('org.fisco-bcos:web3sdk:2.1.0')
}

5.4 证书与配置文件

拷贝区块链节点的SDK证书到项目资源目录:

cp fisco/nodes/127.0.0.1/sdk/* asset-app/src/test/resources/

六、业务开发:Java客户端实现

6.1 核心类设计:AssetClient

AssetClient.java是业务逻辑的核心,负责合约的部署与调用,主要包含以下功能模块:

6.1.1 初始化
// 初始化Web3j和Credentials对象
ApplicationContext context = new ClassPathXmlApplicationContext("classpath:applicationContext.xml");
Service service = context.getBean(Service.class);
service.run();ChannelEthereumService channelEthereumService = new ChannelEthereumService();
channelEthereumService.setChannelService(service);
Web3j web3j = Web3j.build(channelEthereumService, 1);Credentials credentials = Credentials.create(Keys.createEcKeyPair());
6.1.2 合约对象创建
// 部署合约
Asset asset = Asset.deploy(web3j, credentials, new StaticGasProvider(gasPrice, gasLimit)).send();// 加载已部署合约
Asset asset = Asset.load(contractAddress, web3j, credentials, new StaticGasProvider(gasPrice, gasLimit));
6.1.3 接口调用
// 查询资产
Tuple2<BigInteger, BigInteger> result = asset.select(assetAccount).send();// 注册资产
TransactionReceipt registerReceipt = asset.register(assetAccount, amount).send();// 资产转账
TransactionReceipt transferReceipt = asset.transfer(fromAccount, toAccount, amount).send();

七、项目运行与功能验证

7.1 编译项目

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

编译成功后在dist目录生成运行脚本。

7.2 部署合约

cd dist
bash asset_run.sh deploy
# 输出示例:Deploy Asset successfully, contract address is 0xd09ad04220e40bb8666e885730c8c460091a4775

7.3 注册资产

bash asset_run.sh register Alice 100000
# 输出:Register account successfully => account: Alice, value: 100000bash asset_run.sh register Bob 100000
# 输出:Register account successfully => account: Bob, value: 100000

7.4 查询资产

bash asset_run.sh query Alice
# 输出:account Alice, value 100000bash asset_run.sh query Bob
# 输出:account Bob, value 100000

7.5 资产转移

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

八、参考资料

  • FISCO BCOS文档:https://www.bookstack.cn/read/fisco-bcos-2.4-zh

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

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

相关文章

软件设计模式选择、判断解析-1

前言 解析是我个人的理解&#xff0c;相对来说我觉得是能对上定义的逻辑的 目录 一.单选题 1.设计模式的两大主题是(  )  解析&#xff1a;无 2.下列模式中,属于行为型模式的是&#xff08;&#xff09; 解析&#xff1a; 排除A和D&#xff0c;剩下的观察者的“观察”…

【编程基本功】Win11中Git安装配置全攻略,包含Git以及图形化工具TortoiseGit

1 摘要 今天田辛老师给大家带来了一份超实用的博客&#xff0c;手把手教你安装并配置 Git 及其图形化界面 TortoiseGit&#xff0c;从官网下载到最终完成配置&#xff0c;每一个步骤都给大家讲得明明白白&#xff0c;还配有相应的截图&#xff0c;即使是新手小白也能轻松上手&…

细谈QT信号与槽机制

转自个人博客 信号与槽是我个人认为QT中最牛的机制之一&#xff0c;最近没有其他的内容可写&#xff0c;今天就来细细总结一下这个信号与槽机制。 1. 信号与槽机制概述 信号与槽机制可以理解为QT中的一种通信手段&#xff0c;在运行相关代码前&#xff0c;分别声明信号和槽&a…

Docker Swarm 与 Kubernetes 在集群管理上的主要区别

Docker Swarm 和 Kubernetes 是两种流行的容器编排工具&#xff0c;它们都可以用于部署、管理和扩展容器化应用&#xff0c;但在集群管理方面有明显的差异。 下面从多个维度对比它们在集群管理上的主要区别&#xff1a; ✅ 一、总体定位 项目Docker SwarmKubernetes官方支持D…

【StarRocks系列】查询优化

步骤参考官网 分析查询 | StarRocks StarRocks-Profile分析及优化指南 StarRocks-Profile分析及优化指南 - 经验教程 - StarRocks中文社区论坛

软测八股--测试理论 1 测试基础

软件测试&#xff1f; 发现程序中的侧屋执行程序工程 目的&#xff1a;不仅是找出错误&#xff0c;还要分析错误产生原因和错误分布。检查开发如阿健过程出现的bug&#xff0c;使开发人员及时修改。测试只能说明软件中存在错误 目标&#xff1a;尽可能发现多的错误。一个好的…

mfc与vs成功在xp系统所需做的修改

目录 前言一、MFC程序 inet_pton 、CT2A 未声明问题1&#xff09;问题1&#xff1a;inet_pton &#xff1a;undeclared identifier - inet_pton未声明2&#xff09;问题1&#xff1a;CT2A &#xff1a;undeclared identifier - CT2A未声明 二、VS程序 使用事件、委托问题1&…

SpringMVC系列(三)(请求处理的十个实验(上))

0 引言 作者正在学习SpringMVC相关内容&#xff0c;学到了一些知识&#xff0c;希望分享给需要短时间想要了解SpringMVC的读者朋友们&#xff0c;想用通俗的语言讲述其中的知识&#xff0c;希望与诸位共勉&#xff0c;共同进步&#xff01; 本系列会持续更新&#xff01;&…

Python案例练习:函数专题

用函数重新设计文章单词出现次数程序 composition This is my family. We have a father, a mother and two brothers. My father is a doctor. He works in a hospital. My mother is a teacher. She teaches English in a school. My older brother is a student. He stu…

数据驱动 AI 时代:数据库行业的技术跃迁与生态重构

在数据驱动的 AI 战场&#xff0c;真正的决胜武器不是复杂精妙的算法模型&#xff0c;而是深埋在企业核心系统中的高维数据网络&#xff08;图&#xff09;。 时至今日&#xff0c;市场对AI的风向正从“狂飙突进”转向“精耕细作”&#xff0c;就在上周&#xff08;米国时间6月…

码分复用通俗理解

一、码分复用&#xff08;CDMA&#xff09;的通俗理解 码分复用&#xff08;Code Division Multiple Access&#xff0c;CDMA&#xff09;是一种让多个用户在同一时间、同一频段上同时传输数据的技术。它的核心思想是&#xff1a;给每个用户分配一个唯一的“编码钥匙”&#x…

MAC、IP地址、TCP、UDP、SSL、OSI模型

目录 一 概要 二 MAC和IP地址 &#xff08;1&#xff09;什么是 MAC 地址&#xff1f; &#xff08;2&#xff09;什么是 IP 地址&#xff1f; &#xff08;3&#xff09;MAC 地址 vs IP 地址对比表 &#xff08;4&#xff09;总结一下 二 TCP、UDP、SSL详细介绍 &#…

弱口令介绍及破解方式笔记

一、弱口令的定义与危害 弱口令是指容易被猜测或破解的密码&#xff0c;通常包含简单数字组合&#xff08;如“123456”&#xff09;、键盘连续字符&#xff08;如“qwerty”&#xff09;、个人信息&#xff08;如生日、姓名&#xff09;或常见词汇&#xff08;如“password”…

Kotlin 中ArrayList、listOf、arrayListOf 和 mutableListOf区别

在 Kotlin 中&#xff0c;ArrayList、listOf、arrayListOf 和 mutableListOf 是常用的集合创建方式&#xff0c;但它们在类型、可变性和使用场景上有明显区别。以下是核心对比&#xff1a; 一、基本定义与类型 创建方式类型可变性底层实现ArrayList<T>()ArrayList<T…

C盘清理技巧分享:释放宝贵空间,提升电脑性能

Hi&#xff0c;我是布兰妮甜 &#xff01;随着电脑使用时间的增长&#xff0c;C盘空间逐渐被各种文件占据&#xff0c;导致系统运行缓慢、程序响应迟钝。对于许多用户来说&#xff0c;C盘空间不足是一个常见且令人头疼的问题。本文将分享一系列实用的C盘清理技巧&#xff0c;帮…

【 感知集群】大规模分布式基础设施的AI赋能蓝图

第一部分&#xff1a;AIOps基础——从被动响应到预测性运维 在本报告的初始部分&#xff0c;我们将为管理一个复杂的大规模集群建立关键的基线。我们认为&#xff0c;在追求高级优化或未来主义架构之前&#xff0c;一个强大、由人工智能驱动的运维基础是不可或缺的。本部分将详…

《R循环:深度解析与高效使用技巧》

《R循环:深度解析与高效使用技巧》 引言 R语言作为一种功能强大的统计计算和图形显示语言,被广泛应用于科研、数据分析、金融等领域。R循环是R语言中的核心概念之一,对于提高编程效率、处理复杂数据至关重要。本文将深度解析R循环,并介绍高效使用技巧,帮助读者更好地掌握…

Windows WSL安装Emscripten‌/emsdk(失败)

前面说过&#xff0c;在CMD、PS下&#xff0c;根本安装不了。那只能试试在WSL安装了。 安装ubuntu 管理员运行PowerShell wsl --install ubuntu自带python3&#xff0c;不需要安装。 安装 我就奇怪了&#xff0c;都说得头头是道&#xff0c;实际上一操作就出问题&#xff…

SpringBoot + EMQX 通过MQTT协议和下位机建立通讯并获取下位机的监测数据-->测试

一、说明 在上一个博客中&#xff0c;我们部署了 EMQX 服务器&#xff0c;实现了 SpringBoot EMQX 通过MQTT协议和下位机建立通讯并获取下位机的监测数据的编码。现在我们对编码进行进一步的测试。 二、编码测试 2.1 在 EMQX 服务器开启客户端认证 这里的客户端认证&#xf…

#17 修改开源模型以适配新任务

在Kaggle的评论区看到有选手想用Swin Transformer来做回归任务,从这个片段可以窥见修改模型的一些思路,于是记录下来学习一下 基于 torchvision Swin_B 模型的特征提取 from torchvision.models.swin_transformer import swin_b, Swin_B_Weights, swin_v2_b, Swin_V2_B_Weig…