上云无忧 > 文档中心 > 百度智能云超级链BaaS Fabric-Dapp开发指南 - 链码开发及部署
超级链BaaS平台
百度智能云超级链BaaS Fabric-Dapp开发指南 - 链码开发及部署

文档简介:
IDE环境准备: 本文采用Go语言开发Fabric链码,Golang IDE请读者自行准备。 链码实现: 编写链码的Golang基础语法请读者自行阅读或参考完整源码,这里主要介绍便签板合约的主要实现。 【百度智能云】可信计算平台
*此产品及展示信息均由百度智能云官方提供。免费试用 咨询热线:400-826-7010,为您提供专业的售前咨询,让您快速了解云产品,助您轻松上云! 微信咨询
  免费试用、价格特惠

IDE环境准备

本文采用Go语言开发Fabric链码,Golang IDE请读者自行准备。

链码实现

编写链码的Golang基础语法请读者自行阅读或参考完整源码,这里主要介绍便签板合约的主要实现。

链码对象

Golang实现的链码必须定义合约对象,对象定义为空即可,代码如下

type SmartContract struct {
}

便签对象的实现

便签板合约的实现关键就是定义一个便签在区块链上存储的数据格式。我们首先定义一个便签的结构体

type Note struct {
	Id		int		`json:"id"`
	Title	string	`json:"title"`
	Content	string	`json:"content"`
}

便签由三部分构成,string类型的标题,string类型的便签正文以及一个64位(也有可能为32位,与CPU位数有关)的有符号整数类型表示的便签ID。

Init接口的实现

在本合约中,并不需要初始化部分便签数据,所以Init接口直接返回成功,具体实现方法如下

func (s *SmartContract) Init(APIstub shim.ChaincodeStubInterface) sc.Response {
	return shim.Success(nil)
}

Invoke接口的实现

Fabric链码的核心接口是invoke,这也是用户实现业务逻辑的地方。在本示例中,主要实现的业务逻辑包括新增便签、更新便签、获取所有的便签。以下就这三个业务进行详细说明。

新增便签的实现

新增便签需要构建一个Note对象,对象中的title和content由用户定义传入,因为本Dapp只是用于示例,所以Id由提交时的时间戳生成,实际生产环境中可以采用其他算法,保证Id的唯一性。Fabric的链上的数据必须为key-value格式,而且key必须为string类型,value必须为byte数组。在本合约中,我们使用Id作为key,所以在调用该方法时,传入的三个参数,Id、title、content,都为字符串类型。在构建Note对象时需要先将string类型的Id转换为int类型,并将Note对象转换为byte数组格式。 新增便签的函数如下

func (s *SmartContract) insert(APIstub shim.ChaincodeStubInterface, args []string) sc.Response {
	if len(args) != 3 {
		return shim.Error("Incorrect number of arguments. Expecting 3")
	}

	noteId, transErr := strconv.Atoi(args[0])
	if transErr != nil {
		fmt.Printf("Error trans args to get note id: %s", transErr)
		return shim.Error("Incorrect type of arguments. Id expecting int")
	}

	var note = Note {
		Id:	noteId,
		Title: args[1],
		Content: args[2],
	}

	carAsBytes, _ := json.Marshal(note)
	err := APIstub.PutState(args[0], carAsBytes)
	if err != nil {
		return shim.Error(err.Error())
	}

	return shim.Success(nil)
}

更新便签的实现

更新便签与新增便签稍有差别,需要先从给定的Note ID中找到note对象,如果对象不存在进行报错,如果对象存在再进行更新。 具体代码如下

func (s *SmartContract) update(APIstub shim.ChaincodeStubInterface, args []string) sc.Response {
	if len(args) != 3 {
		return shim.Error("Incorrect number of arguments. Expecting 3")
	}

	noteAsBytes, _ := APIstub.GetState(args[0])
	if noteAsBytes == nil {
		return shim.Error("Note not found.")
	}
	note := Note{}

	json.Unmarshal(noteAsBytes, ¬e)
	note.Title = args[1]
	note.Content = args[2]

	noteAsBytes, _ = json.Marshal(note)
	err := APIstub.PutState(args[0], noteAsBytes)
	if err != nil {
		return shim.Error(err.Error())
	}
	return shim.Success(nil)
}

获取所有的便签

Fabric链码提供的接口中支持遍历功能,通过指定start和endkey,以字典排序查询到相应记录,如果start和endkey都设置为空字符串,查询的是所有记录。与新增便签一样,查询出来的note对象也是以byte数组方式存储的,需要进行解码。之后以Id为key,以note对象为value构建Map,并将Map编码为byte数组返回。 具体的代码如下

func (s *SmartContract) queryAll(APIstub shim.ChaincodeStubInterface) sc.Response {
	resultsIterator, err := APIstub.GetStateByRange("", "")
	if err != nil {
		return shim.Error(err.Error())
	}
	defer resultsIterator.Close()

	// buffer is a JSON array containing QueryResults
	notes := map[int]Note{}

	for resultsIterator.HasNext() {
		queryResponse, err := resultsIterator.Next()
		if err != nil {
			return shim.Error(err.Error())
		}

		var tmpNote Note
		noteId, keyTransErr := strconv.Atoi(queryResponse.Key)
		if keyTransErr != nil {
			fmt.Printf("Error trans note id: %s", keyTransErr)
			continue
		}
		if transErr := json.Unmarshal(queryResponse.Value, &tmpNote); err != nil {
			fmt.Printf("Error trans note: %s", transErr)
			notes[noteId] = Note{}
		} else {
			notes[noteId] = tmpNote
		}
	}

	result, _ := json.Marshal(notes)
	return shim.Success(result)
}

链码完整代码

package main

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

	"github.com/hyperledger/fabric/core/chaincode/shim"
	sc "github.com/hyperledger/fabric/protos/peer"
)

// Define the Smart Contract structure
type SmartContract struct {
}

type Note struct {
	Id		int		`json:"id"`
	Title	string	`json:"title"`
	Content	string	`json:"content"`
}


func (s *SmartContract) Init(APIstub shim.ChaincodeStubInterface) sc.Response {
	return shim.Success(nil)
}

func (s *SmartContract) Invoke(APIstub shim.ChaincodeStubInterface) sc.Response {
	function, args := APIstub.GetFunctionAndParameters()
	if function == "queryAll" {
		return s.queryAll(APIstub)
	} else if function == "insert" {
		return s.insert(APIstub, args)
	} else if function == "update" {
		return s.update(APIstub, args)
	}

	return shim.Error("Invalid Smart Contract function name.")
}

func (s *SmartContract) queryAll(APIstub shim.ChaincodeStubInterface) sc.Response {
	resultsIterator, err := APIstub.GetStateByRange("", "")
	if err != nil {
		return shim.Error(err.Error())
	}
	defer resultsIterator.Close()

	// buffer is a JSON array containing QueryResults
	notes := map[int]Note{}

	for resultsIterator.HasNext() {
		queryResponse, err := resultsIterator.Next()
		if err != nil {
			return shim.Error(err.Error())
		}

		var tmpNote Note
		noteId, keyTransErr := strconv.Atoi(queryResponse.Key)
		if keyTransErr != nil {
			fmt.Printf("Error trans note id: %s", keyTransErr)
			continue
		}
		if transErr := json.Unmarshal(queryResponse.Value, &tmpNote); err != nil {
			fmt.Printf("Error trans note: %s", transErr)
			notes[noteId] = Note{}
		} else {
			notes[noteId] = tmpNote
		}
	}

	result, _ := json.Marshal(notes)
	return shim.Success(result)
}

func (s *SmartContract) insert(APIstub shim.ChaincodeStubInterface, args []string) sc.Response {

	if len(args) != 3 {
		return shim.Error("Incorrect number of arguments. Expecting 3")
	}

	noteId, transErr := strconv.Atoi(args[0])
	if transErr != nil {
		fmt.Printf("Error trans args to get note id: %s", transErr)
		return shim.Error("Incorrect type of arguments. Id expecting int")
	}

	var note = Note {
		Id:	noteId,
		Title: args[1],
		Content: args[2],
	}

	carAsBytes, _ := json.Marshal(note)
	err := APIstub.PutState(args[0], carAsBytes)
	if err != nil {
		return shim.Error(err.Error())
	}

	return shim.Success(nil)
}

func (s *SmartContract) update(APIstub shim.ChaincodeStubInterface, args []string) sc.Response {

	if len(args) != 3 {
		return shim.Error("Incorrect number of arguments. Expecting 3")
	}

	noteAsBytes, _ := APIstub.GetState(args[0])
	if noteAsBytes == nil {
		return shim.Error("Note not found.")
	}
	note := Note{}

	json.Unmarshal(noteAsBytes, ¬e)
	note.Title = args[1]
	note.Content = args[2]

	noteAsBytes, _ = json.Marshal(note)
	err := APIstub.PutState(args[0], noteAsBytes)
	if err != nil {
		return shim.Error(err.Error())
	}
	return shim.Success(nil)
}

// The main function is only relevant in unit test mode. Only included here for completeness.
func main() {
	// Create a new Smart Contract
	err := shim.Start(new(SmartContract))
	if err != nil {
		fmt.Printf("Error creating new Smart Contract: %s", err)
	}
}

链码部署

进入Fabric列表页,找到希望安装链码的网络,点击右侧的“通道管理”链接

进入通道管理页面后,找到希望安装链码的通道,点击右侧的“链码管理”链接

进入链码管理页面后点击左侧的“新增链码”按钮

在弹出的链码配置框中填写链码配置信息(单个链码文件请置于文件夹下,将文件夹整体打包上传)

点击确认后会显示已上传的链码列表

链码安装

已上传的链码可以进行安装,点击链码列表页中对应链码右侧的”安装“按钮,进行链码的安装,安装完成后链码状态会变为安装完成

链码实例化

安装成功的链码可以进行实例化,点击对应链码右侧的”实例化“按钮,进行链码的实例化,实例化成功后链码状态变为运行中,至此链码安装完成

相似文档
  • Dapp应用层要做什么: Dapp应用层最主要的是实现用户侧的交互逻辑,包括web页面和页面事件响应。同时不同的操作会带来不同的事件,我们还需要针对页面事件去调用后端链码方法,存入便签、更新便签、读取便签等。 【百度智能云】可信计算平台
  • Dapp部署是指将我们开发完成的Dapp应用层进行部署。因为Dapp应用层只是一个前端React App,理论上我们只是寻找一个Dapp js的托管服务器。当用户访问Dapp的线上地址时,浏览器获得HTML+CSS+JS,之后所有的交互响应都不再与托管服务器有关。 【百度智能云】可信计算平台
  • Quorum联盟链操作演示: 介绍百度智能云Quorum联盟链和使用联盟链配置便签的演示操作。 【百度智能云】可信计算平台
  • XUPERBAAS常见问题: 1. XUPERBAAS 如何处理欠费网络? XUPERBAAS 会保留欠费网络七天,七天后会自动删除网络。欠费期间网络不可用,充值后网络才可恢复使用。 【百度智能云】可信计算平台
  • 协议生效时间:2022年03月01日。 本服务等级协议(Service Level Agreement,以下简称 "SLA")规定了百度智能云向客户提供的超级链BaaS平台(Baidu Xuper BaaS)的服务可用性等级指标及赔偿方案。 【百度智能云】可信计算平台
官方微信
联系客服
400-826-7010
7x24小时客服热线
分享
  • QQ好友
  • QQ空间
  • 微信
  • 微博
返回顶部