fabric-contract-api-go快速上手

hi,好久没有更新Fabric相关文章,今天给大家带来fabric-contract-api-go快速上手,相较于原文省略较多,希望深入理解的小伙伴可以点原文学习。

背景

Fabric提供了大量的API来开发智能合约,支持 Go, Node.js, 和Java。本文对fabric-contract-api-go进行简单梳理,可以使读者快速上手。

原文:https://github.com/hyperledger/fabric-contract-api-go/blob/main/tutorials/getting-started.md

一、环境准备

装好Docker、Go的ubuntu,版本尽量新一点。详细请参考原文。

二、contractapi 简述

contractapi 通过打包一个或多个合约打包成一个chaincode(链码),在链码中使用的合约需要实现 contractapi.ContractInterface接口(实现接口相当于继承其中的方法与属性),最简单的方式就是在我们自己创建的合约中嵌入contractapi.Contract结构体。代码示例:

go 复制代码
package main
import (
    "errors"
    "fmt"

    "github.com/hyperledger/fabric-contract-api-go/contractapi"
)
// SimpleContract contract for handling writing and reading from the world state
type SimpleContract struct {
    contractapi.Contract
}
三、合约函数编写的一些规则

合约仅可以返回0个、1个或2个值。0个值的情况下,所有调用都返回成功;1个值的情况下可以返回规定中的任意类型或error;2个值的情况下,第一个值是数据,第二个值是error。

四、Create合约函数解释

Create函数可以在Fabric的world state中存储键值对。因为需要和world state交互,我们需要传入交易的上下文,在示例代码中使用了默认的contractapi.TransactionContextInterfaceTransactionContextInterface是一个接口类型,实现该接口的交易上下文可以传入。然后交易上下文获取

go 复制代码
// Create adds a new key with value to the world state
func (sc *SimpleContract) Create(ctx contractapi.TransactionContextInterface, key string, value string) error {
    existing, err := ctx.GetStub().GetState(key)

    if err != nil {
        return errors.New("Unable to interact with world state")
    }

    if existing != nil {
        return fmt.Errorf("Cannot create world state pair with key %s. Already exists", key)
    }

    err = ctx.GetStub().PutState(key, []byte(value))

    if err != nil {
        return errors.New("Unable to interact with world state")
    }

    return nil
}

附上package shim的官方解释:

复制代码
// Package shim provides APIs for the chaincode to access its state
// variables, transaction context and call other chaincodes.

stub的官方解释:

复制代码
// ChaincodeStub is an object passed to chaincode for shim side handling of
// APIs.

个人理解:我们在编写合约时使用stub来对账本进行操作,shim提供了API进行实际的操作,即链码与peer节点之间的通信。

五、完整的合约:
go 复制代码
package main

import (
    "errors"
    "fmt"

    "github.com/hyperledger/fabric-contract-api-go/contractapi"
)

// SimpleContract contract for handling writing and reading from the world state
type SimpleContract struct {
    contractapi.Contract
}

// Create adds a new key with value to the world state
func (sc *SimpleContract) Create(ctx contractapi.TransactionContextInterface, key string, value string) error {
    existing, err := ctx.GetStub().GetState(key)

    if err != nil {
        return errors.New("Unable to interact with world state")
    }

    if existing != nil {
        return fmt.Errorf("Cannot create world state pair with key %s. Already exists", key)
    }

    err = ctx.GetStub().PutState(key, []byte(value))

    if err != nil {
        return errors.New("Unable to interact with world state")
    }

    return nil
}

// Update changes the value with key in the world state
func (sc *SimpleContract) Update(ctx contractapi.TransactionContextInterface, key string, value string) error {
    existing, err := ctx.GetStub().GetState(key)

    if err != nil {
        return errors.New("Unable to interact with world state")
    }

    if existing == nil {
        return fmt.Errorf("Cannot update world state pair with key %s. Does not exist", key)
    }

    err = ctx.GetStub().PutState(key, []byte(value))

    if err != nil {
        return errors.New("Unable to interact with world state")
    }

    return nil
}

// Read returns the value at key in the world state
func (sc *SimpleContract) Read(ctx contractapi.TransactionContextInterface, key string) (string, error) {
    existing, err := ctx.GetStub().GetState(key)

    if err != nil {
        return "", errors.New("Unable to interact with world state")
    }

    if existing == nil {
        return "", fmt.Errorf("Cannot read world state pair with key %s. Does not exist", key)
    }

    return string(existing), nil
}
六、使用合约

在同一个文件夹中创建一个main.go,添加main函数。通过 contractapi.NewChaincode()方法使用先前的合约创建出来一个chaincode。

go 复制代码
package main

import (
    "github.com/hyperledger/fabric-contract-api-go/contractapi"
)

func main() {
    simpleContract := new(SimpleContract)

    cc, err := contractapi.NewChaincode(simpleContract)

    if err != nil {
        panic(err.Error())
    }

    if err := cc.Start(); err != nil {
        panic(err.Error())
    }
}
相关推荐
深度学习04072 分钟前
【Linux服务器】-安装ftp与sftp服务
linux·运维·服务器
小白爱电脑2 小时前
什么是2.5G交换机?
运维·网络·5g·千兆宽带
?ccc?2 小时前
容器技术技术入门与 Docker 环境部署
运维·docker·容器
时时刻刻看着自己的心2 小时前
docker启动报错
运维·docker·容器
我科绝伦(Huanhuan Zhou)3 小时前
华为泰山服务器重启后出现 XFS 文件系统磁盘“不识别”(无法挂载或访问),但挂载点目录仍在且无数据
运维·服务器·华为
匆匆那年9673 小时前
Docker容器中安装MongoDB,导入数据
运维·docker·容器
望获linux3 小时前
【Linux基础知识系列】第四十三篇 - 基础正则表达式与 grep/sed
linux·运维·服务器·开发语言·前端·操作系统·嵌入式软件
万米商云4 小时前
企业物资集采平台解决方案:跨地域、多仓库、百部门——大型企业如何用一套系统管好百万级物资?
大数据·运维·人工智能
挑战者6668884 小时前
CentOS 系统高效部署 Dify 全攻略
linux·运维·centos
网硕互联的小客服6 小时前
服务器经常出现蓝屏是什么原因导致的?如何排查和修复?
运维·服务器·stm32·单片机·网络安全