• Fisco开发第一个区块链应用


    一、部署区块链

    1. 环境准备

    第一步:安装JDK 1.8版本。
    在这里插入图片描述

    第二步:下载fisco压缩包。

    链接:https://pan.baidu.com/s/1_ivw1FeKVhbVZIAbzvdSQg 
    提取码:e14j
    
    • 1
    • 2

    下载完成后解压缩到/root目录下。

    2. 启动节点

    1)启动区块链节点:

    cd /root/fisco/nodes/127.0.0.1/
    sh start_all.sh
    
    • 1
    • 2

    确认节点启动正常:

    tail -f /root/fisco/nodes/127.0.0.1/node0/log/log*  | grep +++
    
    • 1

    正常情况会不停输出++++Generating seal,表示共识正常。

    2)启动节点控制台服务:

    cd /root/fisco/WeBASE-Front/dist
    sh start.sh
    
    • 1
    • 2

    通过浏览器远程访问如下链接,如果可以访问,则说明已经正常运行了。

    http://ip:5002/WeBASE-Front/
    
    • 1

    界面如下所示:
    在这里插入图片描述

    3. 编译合约

    1)准备合约

    pragma solidity ^0.4.21;
    
    contract Asset {
        address public issuer;
        mapping (address => uint) public balances;
    
        event Sent(address from, address to, uint amount);
    
        constructor() {
            issuer = msg.sender;
        }
    
        function issue(address receiver, uint amount) public {
            if (msg.sender != issuer) return;
            balances[receiver] += amount;
        }
    
        function send(address receiver, uint amount) public {
            if (balances[msg.sender] < amount) return;
            balances[msg.sender] -= amount;
            balances[receiver] += amount;
            emit Sent(msg.sender, receiver, amount);
        }
        
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25

    2)部署合约

    选择合约IDE,点右上角“部署”按钮。部署成功后,会生成合约地址(如下图所示)。
    在这里插入图片描述

    3)下载SDK证书

    点击右上角的“SDK证书下载”按钮,将下载的证书压缩包文件保存起来,后面需要导入到项目中。

    4. 创建测试用户

    点击左边“测试用户”菜单,在主界面上点击“新增用户”,然后输入用户名。
    在这里插入图片描述
    点击新建用户右边的导出按钮,选择.pem,导出用户证书。
    在这里插入图片描述

    二、创建应用

    1. 新建项目

    本示例所使用开发工具为Idea。首先新建一个Maven项目。然后按照下面目录结构在src/main/javasrc/main/resources中创建相应的包和文件夹。
    在这里插入图片描述
    将上面准备好的用户证书和sdk证书分别复制到对应文件夹中(如下图所示)。
    在这里插入图片描述

    2. 引入依赖

    pom文件如下所示:

    <?xml version="1.0" encoding="UTF-8"?>
    ://maven.apache.org/POM/4.0.0"
             xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
             xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
        >4.0.0>
    
        >org.fisco.bcos>
        >asset-app>
        >1.0-SNAPSHOT>
    
        >
            >
                >org.springframework.boot>
                >spring-boot-starter-web>
                >2.7.3>
            >
            >
                >org.springframework.boot>
                >spring-boot-starter-test>
                >2.6.8>
                >test>
            >
            >
                >org.fisco-bcos.java-sdk>
                >fisco-bcos-java-sdk>
                >2.9.1>
            >
        >
    
        >
            >
                >
                    >org.apache.maven.plugins>
                    >maven-compiler-plugin>
                    >3.1>
                    >
                        >1.8>
                        >1.8>
                        >UTF-8>
                    >
                >
            >
        >
    
    >
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45

    3. 启动类

    org.fisco.bcos.asset包下创建启动类。

    @SpringBootApplication
    public class Application
    {
        public static void main(String[] args)
        {
            SpringApplication.run(Application.class, args);
            System.out.println("项目启动成功");
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    4. 导出Java文件

    点击节点控制台上的合约IDE,然后选中Asset.sol合约后,点击上方的导出Java文件。
    在这里插入图片描述
    然后将导出的Java文件拷贝到项目的org.fisco.bcos.asset.contract包下。
    在这里插入图片描述

    5. 定义区块链配置信息

    src/main/resources目录下,新建application.yaml文件。

    fisco:
      nodeList: 192.168.88.15:20201
      groupId: 1
      certPath: E:\workspace\asset-app\src\main\resources\sdk
      contractAddress:
        # Asset合约地址(一定要加引号 不然注解@Value会把按照16进制数字进行转换赋值)
        asset: "0xe755337500bb6ffad292a2499bc12e30d5dc744f"
      # 账户地址
      account:
        # 账户秘钥地址
        accountAddress: E:\workspace\asset-app\src\main\resources\account
        # 账户文件地址
        accountFilePath: E:\workspace\asset-app\src\main\resources\account\zhongliwen_key_0x6e26d380588049b43efca3881a2b2c419ae1a118.pem
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    fisco.nodeList:区块链节点的ip和端口;
    fisco.groupId:组ID;
    fisco.certPath:证书保存目录;
    fisco.contractAddress.asset:合约地址;
    fisco.contractAddress.account.accountAddress:测试用户地址;
    fisco.contractAddress.account.accountFilePath:用户密码文件地址;

    6. 编写sdk访问合约方法

    org.fisco.bcos.asset.client包下新建一个类,该类用于配置相关Bean。

    package org.fisco.bcos.asset.client;
    
    import org.fisco.bcos.sdk.BcosSDK;
    import org.fisco.bcos.sdk.client.Client;
    import org.fisco.bcos.sdk.config.ConfigOption;
    import org.fisco.bcos.sdk.config.exceptions.ConfigException;
    import org.fisco.bcos.sdk.config.model.ConfigProperty;
    import org.fisco.bcos.sdk.crypto.CryptoSuite;
    import org.fisco.bcos.sdk.crypto.keypair.CryptoKeyPair;
    import org.springframework.beans.factory.annotation.Value;
    import org.springframework.context.annotation.Bean;
    import org.springframework.context.annotation.Configuration;
    
    import java.security.KeyPair;
    import java.util.*;
    
    /**
     * @Description: 配置类
     * @Date: 2022/9/30
     * @Author: zhongliwen
     * @Version: 1.0
     */
    @Configuration
    public class ApplicationContext {
    
        @Value("${fisco.nodeList}")
        private String nodeLists;
    
        @Value("${fisco.groupId}")
        private Integer groupId;
    
        @Value("${fisco.certPath}")
        private String certPath;
    
        @Value("${fisco.account.accountFilePath}")
        private String accountFilePath;
    
        @Bean(name = "configProperty")
        public ConfigProperty defaultConfigProperty() {
            ConfigProperty property = new ConfigProperty();
            // 配置cryptoMaterial
            Map<String, Object> cryptoMaterialMap = new HashMap<>();
            cryptoMaterialMap.put("certPath", certPath);
            property.setCryptoMaterial(cryptoMaterialMap);
    
            // 配置network
            Map<String, Object> networkMap = new HashMap<>();
            String[] split = nodeLists.split(",");
            List<String> nodeList = Arrays.asList(split);
            networkMap.put("peers", nodeList);
            property.setNetwork(networkMap);
    
            // 配置account
            Map<String, Object> accountMap = new HashMap<>();
            accountMap.put("keyStoreDir", "account");
            accountMap.put("accountAddress", "");
            accountMap.put("accountFileFormat", "pem");
            accountMap.put("password", "");
            accountMap.put("accountFilePath", accountFilePath);
            property.setAccount(accountMap);
    
            //配置 threadPool
            Map<String, Object> threadPoolMap = new HashMap<>();
            threadPoolMap.put("channelProcessorThreadSize", "16");
            threadPoolMap.put("receiptProcessorThreadSize", "16");
            threadPoolMap.put("maxBlockingQueueSize", "102400");
            property.setThreadPool(threadPoolMap);
            return property;
        }
    
        @Bean(name = "configOption")
        public ConfigOption defaultConfigOption(ConfigProperty configProperty) throws ConfigException {
            return new ConfigOption(configProperty);
        }
    
        @Bean(name = "bcosSDK")
        public BcosSDK bcosSDK(ConfigOption configOption) {
            return new BcosSDK(configOption);
        }
    
        @Bean(name = "client")
        public Client getClient(BcosSDK bcosSDK) {
            // 为群组初始化client
            Client client = bcosSDK.getClient(groupId);
            return client;
        }
    
        @Bean
        public CryptoKeyPair getCryptoKeyPair(Client client) {
            // 如果有密钥文件 那么每次读取的就不再是随机的
            CryptoSuite cryptoSuite = client.getCryptoSuite();
            CryptoKeyPair cryptoKeyPair = cryptoSuite.getCryptoKeyPair();
            return cryptoKeyPair;
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95

    然后再同样的包下创建另外一个类,该类定义了访问Asset合约的方法。

    package org.fisco.bcos.asset.client;
    
    import org.fisco.bcos.asset.contract.Asset;
    import org.fisco.bcos.sdk.BcosSDK;
    import org.fisco.bcos.sdk.client.Client;
    import org.fisco.bcos.sdk.crypto.keypair.CryptoKeyPair;
    import org.fisco.bcos.sdk.model.TransactionReceipt;
    import org.fisco.bcos.sdk.model.callback.TransactionCallback;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.beans.factory.annotation.Value;
    import org.springframework.stereotype.Component;
    
    import java.math.BigInteger;
    
    @Component
    public class AssetClient {
        @Autowired
        private BcosSDK bcosSDK;
        @Autowired
        private Client client;
        @Autowired
        private CryptoKeyPair cryptoKeyPair;
        @Value("${fisco.contractAddress.asset}")
        private String contractAddress;
    
        /**
         * 发布资产(条件:当前用户是Asset合约发布者)
         * @param receiver 接收者地址
         * @param amount 资产数量
         */
        public void issueAsset(String receiver, BigInteger amount) {
            Asset asset = Asset.load(contractAddress, client, cryptoKeyPair);
            asset.issue(receiver, amount, new CallbackResponse());
        }
    
        /**
         * 发送资产(条件:发送者的账号Balance必须大于等于amount)
         * @param receiver 接收者地址
         * @param amount 资产数量
         */
        public void sendAsset(String receiver, BigInteger amount) {
            Asset asset = Asset.load(contractAddress, client, cryptoKeyPair);
            asset.send(receiver, amount, new CallbackResponse());
        }
    
        private class CallbackResponse extends TransactionCallback {
    
            @Override
            public void onResponse(TransactionReceipt transactionReceipt) {
                System.out.println("回调结果:");
                System.out.println(transactionReceipt.getContractAddress());
                System.out.println(transactionReceipt.getFrom());
                System.out.println(transactionReceipt.getGasUsed());
                System.out.println(transactionReceipt.getRemainGas());
                System.out.println(transactionReceipt.getStatus());
                System.out.println(transactionReceipt.getMessage());
                System.out.println(transactionReceipt.getStatusMsg());
            }
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60

    关于Java SDK的使用手册,可以参考官方提供的文档。

    https://fisco-bcos-documentation.readthedocs.io/zh_CN/latest/docs/sdk/java_sdk/index.html
    
    • 1

    7. 测试

    编写一个单元测试类,分别对AssetClient类中的两个方法进行单元测试。

    package org.fisco.bcos.asset.client;
    
    
    import org.fisco.bcos.Application;
    import org.junit.Test;
    import org.junit.runner.RunWith;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.boot.test.context.SpringBootTest;
    import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
    
    import java.math.BigInteger;
    
    @RunWith(SpringJUnit4ClassRunner.class)
    @SpringBootTest(classes = Application.class)
    public class AssetClientTest {
        @Autowired
        private AssetClient assetClient;
    
        @Test
        public void testIssueAsset() throws InterruptedException {
            String receiver = "0x6e26d380588049b43efca3881a2b2c419ae1a118";
            BigInteger amount = new BigInteger("10000");
            assetClient.issueAsset(receiver, amount);
            Thread.sleep(5000);
            System.out.println("发布成功!");
        }
    
        @Test
        public void testSendAsset() throws InterruptedException {
            String receiver = "0x0f16fe999788f945adcad08e5b8c4fb1fcfca55d";
            BigInteger amount = new BigInteger("50000");
            assetClient.sendAsset(receiver, amount);
            Thread.sleep(5000);
            System.out.println("发送成功!");
        }
    
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37

    测试步骤:

    1. 先后执行testIssueAssettestSendAsset测试方法;
    2. 执行成功后,在节点控制台的合约列表中找到对应的合约;

    在这里插入图片描述
    3. 点击右方的合约调用,然后方法选择balances,参数输入测试方法中receiver地址;
    在这里插入图片描述
    点击确定后,可以看到相关的交易回执。
    在这里插入图片描述
    到目前为止,已经完成了在Fisco区块链上部署智能合约,并通过Java SDK调用智能合约函数的示例。

  • 相关阅读:
    媒介盒子:品牌宣传的内容输出逻辑是什么
    深⼊理解指针(5)【深入理解指针,体会大厂的笔试题】
    【luogu CF1609G】A Stroll Around the Matrix(贪心)(线段树)
    2.3 Go语言中的字符型和常量定义
    基于DQN的强化学习 快速浏览(基础知识+示例代码)
    如何基于Angular从.ts获取鼠标响应的屏幕坐标,并传递至.html的Style中
    久经沙场的程序员居然也被某鱼的假程序员骗了,程序员之间的信任应该是最高的,他一个人毁了这种信任感
    深度学习-通过Resnet18实现CIFAR10数据分类
    14.计算机网络---应用层之HTTPS
    如何提高同行评审的有效性
  • 原文地址:https://blog.csdn.net/zhongliwen1981/article/details/127126265