前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >浅析MetaForce原力元宇宙佛萨奇2.0智能合约系统开发逻辑详解丨佛萨奇2.0源码功能开发

浅析MetaForce原力元宇宙佛萨奇2.0智能合约系统开发逻辑详解丨佛萨奇2.0源码功能开发

原创
作者头像
VX_I357O98O7I8
发布2022-12-15 17:18:41
4850
发布2022-12-15 17:18:41
举报
文章被收录于专栏:商业模式策划

2.2.2. 编写合约注意事项

  1. 代码入口包名必须为main
  2. 代码入口 package main // sdk代码中,有且仅有一个main()方法 func main() { // main()方法中,下面的代码为必须代码,不建议修改main()方法当中的代码 // 其中,TestContract为用户实现合约的具体名称 err := sandbox.Start(new(FactContract)) if err != nil { log.Fatal(err) } }
  3. 合约必要代码 // 合约结构体,合约名称需要写入main()方法当中 type FactContract struct { } // 合约必须实现下面两个方法: // InitContract() protogo.Response // UpgradeContract() protogo.Response // InvokeContract(method string) protogo.Response // 用于合约的部署 // @return: 合约返回结果,包括Success和Error func (f *FactContract) InitContract() protogo.Response { return sdk.Success([]byte("Init contract success")) } // 用于合约的升级 // @return: 合约返回结果,包括Success和Error func (f *FactContract) UpgradeContract() protogo.Response { return sdk.Success([]byte("Upgrade contract success")) } // 用于合约的调用 // @param method: 交易请求调用的方法 // @return: 合约返回结果,包括Success和Error func (f *FactContract) InvokeContract(method string) protogo.Response { switch method { case "save": return f.save() case "findByFileHash": return f.findByFileHash() default: return sdk.Error("invalid method") } }

2.2.3. 合约SDK接口描述

长安链提供golang合约与链交互的相关接口,写合约时可直接导入包,并进行引用,具体信息可参考文章末尾”接口描述章节”。

2.2.4. 编译合约

当合约编写完成后,则需要编译合约,具体教程如下

2.2.4.1. 使用脚本编译合约
  1. 在合约工程中添加编译脚本build.sh搭建编译环境。 #!/bin/bash contractName=$1 if [[ ! -n $contractName ]] ;then echo "contractName is empty. use as: ./build.sh contractName" exit 1 fi go build -ldflags="-s -w" -o $contractName 7z a $contractName $contractName rm -f $contractName
  2. 编译撰写好的智能合约。 其中ContractName请替换成需要安装的合约名称 ./build.sh ContractName 编译成功,如下图所示:
2.2.4.2. 手动编译合约

需要保证是在Linux环境下编译,在此文件夹的当前路径执行如下编译命令:

代码语言:javascript
复制
# 如果需要在其他系统环境下编译合约,请参考Golang的交叉编译修改go build命令。
go build -ldflags="-s -w" -o file_name

7z a file_name file_name

在编译合约时,首先使用golang编译程序。

编译后使用7zip对编译好的可执行文件进行压缩。

编译结果输出与使用脚本编译一致。

2.2.5. 部署调用合约

编译完成后,将得到一个.7z格式的合约文件,可将之部署到指定到长安链上,完成合约部署。 部署合约的使用教程可详见:部署示例合约

2.3. 示例合约使用演示

2.3.1. 示例代码说明

ChainMaker官方提供了通过go.mod引用合约SDK进行合约开发的示例合约工程。

以存证合约为例,可以直接下载下编译存证合约,过程如下:

代码语言:javascript
复制
$ git clone https://git.chainmaker.org.cn/contracts/contracts-go.git
$ cd contracts-go/fact
$ ./build.sh fact
...

更多合约示例可以直接查看仓库contracts-go

2.3.2. 存证合约示例源码展示

代码语言:javascript
复制
/*
Copyright (C) BABEC. All rights reserved.
Copyright (C) THL A29 Limited, a Tencent company. All rights reserved.

SPDX-License-Identifier: Apache-2.0
*/

package main

import (
	"encoding/json"
	"fmt"
	"log"
	"strconv"

	"chainmaker.org/chainmaker/contract-sdk-go/v2/pb/protogo"
	"chainmaker.org/chainmaker/contract-sdk-go/v2/sandbox"
	"chainmaker.org/chainmaker/contract-sdk-go/v2/sdk"
)

type FactContract struct {
}

// 存证对象
type Fact struct {
	FileHash string `json:"fileHash"`
	FileName string `json:"fileName"`
	Time     int32  `json:"time"`
}

// 新建存证对象
func NewFact(fileHash string, fileName string, time int32) *Fact {
	fact := &Fact{
		FileHash: fileHash,
		FileName: fileName,
		Time:     time,
	}
	return fact
}

func (f *FactContract) InitContract() protogo.Response {
	return sdk.Success([]byte("Init contract success"))
}

func (f *FactContract) UpgradeContract() protogo.Response {
	return sdk.Success([]byte("Upgrade contract success"))
}

func (f *FactContract) InvokeContract(method string) protogo.Response {
	switch method {
	case "save":
		return f.save()
	case "findByFileHash":
		return f.findByFileHash()
	default:
		return sdk.Error("invalid method")
	}
}

func (f *FactContract) save() protogo.Response {
	params := sdk.Instance.GetArgs()

	// 获取参数
	fileHash := string(params["file_hash"])
	fileName := string(params["file_name"])
	timeStr := string(params["time"])
	time, err := strconv.Atoi(timeStr)
	if err != nil {
		msg := "time is [" + timeStr + "] not int"
		sdk.Instance.Errorf(msg)
		return sdk.Error(msg)
	}

	// 构建结构体
	fact := NewFact(fileHash, fileName, int32(time))

	// 序列化
	factBytes, err := json.Marshal(fact)
	if err != nil {
		return sdk.Error(fmt.Sprintf("marshal fact failed, err: %s", err))
	}
	// 发送事件
	sdk.Instance.EmitEvent("topic_vx", []string{fact.FileHash, fact.FileName})

	// 存储数据
	err = sdk.Instance.PutStateByte("fact_bytes", fact.FileHash, factBytes)
	if err != nil {
		return sdk.Error("fail to save fact bytes")
	}

	// 记录日志
	sdk.Instance.Infof("[save] fileHash=" + fact.FileHash)
	sdk.Instance.Infof("[save] fileName=" + fact.FileName)

	// 返回结果
	return sdk.Success([]byte(fact.FileName + fact.FileHash))

}

func (f *FactContract) findByFileHash() protogo.Response {
	// 获取参数
	fileHash := string(sdk.Instance.GetArgs()["file_hash"])

	// 查询结果
	result, err := sdk.Instance.GetStateByte("fact_bytes", fileHash)
	if err != nil {
		return sdk.Error("failed to call get_state")
	}

	// 反序列化
	var fact Fact
	if err = json.Unmarshal(result, &fact); err != nil {
		return sdk.Error(fmt.Sprintf("unmarshal fact failed, err: %s", err))
	}

	// 记录日志
	sdk.Instance.Infof("[find_by_file_hash] fileHash=" + fact.FileHash)
	sdk.Instance.Infof("[find_by_file_hash] fileName=" + fact.FileName)

	// 返回结果
	return sdk.Success(result)
}

func main() {
	err := sandbox.Start(new(FactContract))
	if err != nil {
		log.Fatal(err)
	}
}

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 2.2.3. 合约SDK接口描述
  • 2.2.4. 编译合约
    • 2.2.4.1. 使用脚本编译合约
      • 2.2.4.2. 手动编译合约
      • 2.2.5. 部署调用合约
      • 2.3. 示例合约使用演示
        • 2.3.1. 示例代码说明
          • 2.3.2. 存证合约示例源码展示
          领券
          问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档