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

这篇具有很好参考价值的文章主要介绍了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 前后端开发,Linux,大数据

 fisco bcos 前后端开发,Linux,大数据

 第三步. 引入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,写入配置内容。

(官方图)

fisco bcos 前后端开发,Linux,大数据

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 !!! 

fisco bcos 前后端开发,Linux,大数据

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

(官方图) 

fisco bcos 前后端开发,Linux,大数据

 第二步.开发业务逻辑

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

fisco bcos 前后端开发,Linux,大数据

 这里出现了一个小问题: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

fisco bcos 前后端开发,Linux,大数据

#!/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

fisco bcos 前后端开发,Linux,大数据

### 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] [%-d{yyyy-MM-dd HH:mm:ss}] %C{1}.%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] [%-d{yyyy-MM-dd HH:mm:ss}] %C{1}.%M(%L) | %m%n

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

(官方图片)

fisco bcos 前后端开发,Linux,大数据

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 在哪 ,就切到哪

fisco bcos 前后端开发,Linux,大数据

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

2.部署Asset.sol合约

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

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

fisco bcos 前后端开发,Linux,大数据

 3.注册资产

给张三注册资产10万元 

$ bash asset_run.sh register zhangsan 100000

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

fisco bcos 前后端开发,Linux,大数据

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

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

4.查询资产

查询张三的资产有多少

$ bash asset_run.sh query zhangsan

张三拥有10万资产

fisco bcos 前后端开发,Linux,大数据

 张五同上。

5.资产转移

张三转给张五 5万 块

$ bash asset_run.sh transfer zhangsan zhangwu  50000

转移成功 

fisco bcos 前后端开发,Linux,大数据

 检查张三还剩多少钱

$ bash asset_run.sh query zhangsan

张三还剩 5 万。 

fisco bcos 前后端开发,Linux,大数据

 检查张五还有多少钱

$ bash asset_run.sh query zhangwu

张五有 15 万 

fisco bcos 前后端开发,Linux,大数据文章来源地址https://www.toymoban.com/news/detail-783860.html

到了这里,关于FISCO BCOS开发第一个区块链应用--小白实战的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 搭建第一个区块链网络(Fisco-Bcos),启动并使用控制台

    1.安装依赖 centos7 Ubuntu 2.创建操作目录, 下载安装脚本 3. 搭建单群组4节点联盟链 搭建成功截图如下  4.启动FISCO BCOS链 启动成功截图如下  5.检查进程 检查进程是否启动  输出结果如下,如果进程数不为4,则进程没有启动(一般是端口被占用导致的)  6.检查日志输出 查看节

    2024年02月04日
    浏览(51)
  • Fisco Bcos区块链一(搭建单群组FISCO BCOS联盟链)

    技术文档:https://fisco-bcos-documentation.readthedocs.io/zh_CN/latest/index.html 1、搭建单群组FISCO BCOS联盟链 1. 安装centos依赖包 安装依赖包openssl、curl 2. 创建操作目录, 下载安装脚本 如果因为网络问题导致长时间无法下载build_chain.sh脚本,请尝试 3. 搭建单群组4节点联盟链 在fisco目录下执

    2024年02月10日
    浏览(46)
  • FISCO BCOS 区块链(一)

    目录 一、搭建 FISCO BCOS 链 1、安装 openssl, curl 依赖 2、安装 build_chain 脚本 二、配置控制台 1、下载java jdk 2、安装控制台 3、拷贝配置文件以及证书 4、启动控制台 三、Java-SDK(idea版) 1、创建 project  2、引入 Java-SDK依赖 3、sol2java.sh 4、导入所需资源 5、创建测试类 参考 FISCO

    2024年01月24日
    浏览(47)
  • 搭建FISCO BCOS区块链平台

    这是为北京交通大学《区块链技术》课程制作的实验教程,因面向全校研究生开放选课,故提供了详细的步骤。本文是实验第一步,用于搭建FISCO BCOS区块链平台。 详细阅读FISCO BCOS官方文档: https://fisco-bcos-doc.readthedocs.io/zh_CN/latest/index.html VMware虚拟机安装包下载地址: https

    2024年02月06日
    浏览(51)
  • 1.平台介绍:FISCO BCOS 区块链

    区块链技术作为一种分布式、安全可信的数据记录和交互方式,正逐渐在各行各业展现出巨大潜力。然而,公共区块链的隐私性和性能限制使得企业更倾向于采用联盟链或私有链解决方案。 FISCO BCOS(Blockchain Open Consortium Operating System)作为一种企业级区块链平台,为企业和组

    2024年02月13日
    浏览(44)
  • Fisco Bcos区块链四(扩容节点)

    4、扩容节点 1. 操作命令 为保证区块链安全性,FISCO BCOS引入了游离节点、观察者节点和共识节点,这三种节点类型可通过控制台相互转换。 共识节点:参与共识的节点,拥有群组的所有数据(搭链时默认都生成共识节点)。 观察者节点:不参与共识,但能实时同步链上数据

    2024年02月05日
    浏览(51)
  • FISCO BCOS区块链建立配置启动

    创建操作目录, 下载安装脚本 搭建单群组4节点联盟链 启动FISCO BCOS链 安装java 获取控制台并回到fisco目录 拷贝控制台配置文件 配置控制台证书 编写HelloWorld合约 contract HelloWorld { string name; } 部署HelloWorld合约 调用HelloWorld合约 见https://fisco-bcos-documentation.readthedocs.io/zh_CN/latest/do

    2024年02月07日
    浏览(55)
  • 【FISCO BCOS】二十、多机部署区块链

    目录 一、准备环境 二、开始搭建 三、检查节点          1.检查节点进程

    2024年02月05日
    浏览(43)
  • FISCO BCOS区块链 修改增加RPC接口

    RPC(Remote Procedure Call,远程过程调用)是客户端与区块链系统交互的一套协议和接口。用户通过RPC接口可查询区块链相关信息(如块高、区块、节点连接等)和发送交易。 介绍文档 远程过程调用(RPC) — FISCO BCOS v2.9.0 文档 https://fisco-bcos-documentation.readthedocs.io/zh_CN/latest/docs/de

    2024年02月16日
    浏览(51)
  • 深入浅出FISCO BCOS:区块链底层平台

        苏泽 大家好 这里是苏泽 一个钟爱区块链技术的后端开发者 本篇专栏  ← 持续记录本人自学两年走过无数弯路的智能合约学习笔记和经验总结 如果喜欢拜托三连支持~ 目录 我前面有补充相关的区块链的知识 如果没有了解的话 可能部分概念或名词会不懂哦 建议先了解一

    2024年03月16日
    浏览(64)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包