golang企业级区块链开发框架插件Hyperledger的使用

Golang企业级区块链开发框架插件Hyperledger的使用

编码规范

我们使用Go语言开发,并遵循《Effective Go》和《Go Code Review Comments》中概述的最佳实践和编码风格。

建议新贡献者在提交pull request前阅读以下内容:

  • Practical Go
  • Go Proverbs

所有pull request都会执行以下工具检查,必须解决这些工具报告的错误才能合并代码:

  • gofmt -s
  • goimports
  • go vet

测试

所有生产代码变更都需附带单元测试。这些测试应该:

  • 执行速度快
  • 对新修改代码有很好的覆盖率
  • 支持并行执行

我们常用的测试匹配库:

  • gomega
  • testify/assert

测试所需的fixture或数据应生成或置于版本控制下:

  • 生成的fixture应放在ioutil.TempDir创建的临时目录中,测试结束后清理
  • 版本控制的fixture应放在testdata文件夹中,并附带生成说明
  • 不鼓励跨包共享fixture

当需要fake或mock时,必须使用生成工具:

  • counterfeiter
  • mockery

API文档

Hyperledger Fabric的Golang API文档可在GoDoc中查看。

生成gRPC代码

如果修改了任何.proto文件,运行以下命令生成/更新对应的.pb.go文件:

cd $GOPATH/src/github.com/hyperledger/fabric
make protos

添加或更新Go包

Hyperledger Fabric使用vendor机制管理依赖。所有依赖包都放在$GOPATH/src/github.com/hyperledger/fabric/vendor文件夹中。我们使用dep工具管理vendor文件夹中的包。

示例代码

以下是一个简单的Hyperledger Fabric链码示例:

package main

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

// SimpleChaincode 示例链码结构
type SimpleChaincode struct {
	contractapi.Contract
}

// Init 链码初始化方法
func (s *SimpleChaincode) Init(ctx contractapi.TransactionContextInterface) error {
	fmt.Println("Chaincode initialized")
	return nil
}

// Invoke 链码调用方法
func (s *SimpleChaincode) Invoke(ctx contractapi.TransactionContextInterface) (string, error) {
	fmt.Println("Chaincode invoked")
	return "Hello from chaincode", nil
}

func main() {
	chaincode, err := contractapi.NewChaincode(&SimpleChaincode{})
	if err != nil {
		fmt.Printf("Error creating chaincode: %s", err.Error())
		return
	}

	if err := chaincode.Start(); err != nil {
		fmt.Printf("Error starting chaincode: %s", err.Error())
	}
}

更多关于golang企业级区块链开发框架插件Hyperledger的使用的实战教程也可以访问 https://www.itying.com/category-94-b0.html

1 回复

更多关于golang企业级区块链开发框架插件Hyperledger的使用的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html


Hyperledger Fabric Golang 开发指南

Hyperledger Fabric 是企业级区块链开发的首选框架之一,下面我将介绍如何使用 Golang 进行 Hyperledger Fabric 开发。

1. 环境准备

首先需要安装必要的工具和依赖:

// 安装 Hyperledger Fabric 相关工具
// 1. 安装 Docker 和 Docker Compose
// 2. 安装 Go (推荐 1.14+)
// 3. 安装 Hyperledger Fabric 二进制文件和示例
curl -sSL https://bit.ly/2ysbOFE | bash -s -- 2.2.3 1.4.9

2. 链码(智能合约)开发

链码是 Hyperledger Fabric 的核心业务逻辑,使用 Go 开发链码的基本结构:

package main

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

// SmartContract 提供合约函数定义
type SmartContract struct {
    contractapi.Contract
}

// InitLedger 初始化账本
func (s *SmartContract) InitLedger(ctx contractapi.TransactionContextInterface) error {
    assets := []Asset{
        {ID: "asset1", Color: "blue", Size: 5, Owner: "Tomoko", AppraisedValue: 300},
        {ID: "asset2", Color: "red", Size: 5, Owner: "Brad", AppraisedValue: 400},
    }

    for _, asset := range assets {
        assetJSON, err := json.Marshal(asset)
        if err != nil {
            return err
        }

        err = ctx.GetStub().PutState(asset.ID, assetJSON)
        if err != nil {
            return fmt.Errorf("failed to put to world state. %v", err)
        }
    }

    return nil
}

// CreateAsset 创建新资产
func (s *SmartContract) CreateAsset(ctx contractapi.TransactionContextInterface, id string, color string, size int, owner string, appraisedValue int) error {
    exists, err := s.AssetExists(ctx, id)
    if err != nil {
        return err
    }
    if exists {
        return fmt.Errorf("the asset %s already exists", id)
    }

    asset := Asset{
        ID:             id,
        Color:          color,
        Size:           size,
        Owner:          owner,
        AppraisedValue: appraisedValue,
    }
    assetJSON, err := json.Marshal(asset)
    if err != nil {
        return err
    }

    return ctx.GetStub().PutState(id, assetJSON)
}

// 主函数
func main() {
    chaincode, err := contractapi.NewChaincode(&SmartContract{})
    if err != nil {
        fmt.Printf("Error creating asset-transfer-basic chaincode: %v", err)
        return
    }

    if err := chaincode.Start(); err != nil {
        fmt.Printf("Error starting asset-transfer-basic chaincode: %v", err)
    }
}

3. 链码测试

可以使用 Fabric 提供的模拟框架进行测试:

package main

import (
    "testing"
    "github.com/hyperledger/fabric-chaincode-go/shimtest"
    "github.com/stretchr/testify/assert"
)

func TestInitLedger(t *testing.T) {
    chaincodeStub := shimtest.NewMockStub("chaincode", new(SmartContract))
    response := chaincodeStub.MockInit("1", [][]byte{})
    assert.Equal(t, int32(shim.OK), response.Status)
}

func TestCreateAsset(t *testing.T) {
    chaincodeStub := shimtest.NewMockStub("chaincode", new(SmartContract))
    
    // 先初始化
    chaincodeStub.MockInit("1", [][]byte{})
    
    // 测试创建资产
    response := chaincodeStub.MockInvoke("1", [][]byte{
        []byte("CreateAsset"),
        []byte("asset3"),
        []byte("yellow"),
        []byte("5"),
        []byte("Tom"),
        []byte("600"),
    })
    
    assert.Equal(t, int32(shim.OK), response.Status)
    
    // 验证资产已创建
    assetBytes := chaincodeStub.State["asset3"]
    assert.NotNil(t, assetBytes)
}

4. 客户端应用开发

使用 Fabric Go SDK 与区块链网络交互:

package main

import (
    "fmt"
    "github.com/hyperledger/fabric-sdk-go/pkg/core/config"
    "github.com/hyperledger/fabric-sdk-go/pkg/gateway"
    "log"
)

func main() {
    // 1. 加载连接配置文件
    ccpPath := "./connection-org1.yaml"
    gw, err := gateway.Connect(
        gateway.WithConfig(config.FromFile(filepath.Clean(ccpPath))),
        gateway.WithIdentity(gateway.NewX509Identity("Org1MSP", "cert.pem", "key.pem")),
    )
    if err != nil {
        log.Fatalf("Failed to connect to gateway: %v", err)
    }
    defer gw.Close()

    // 2. 获取网络通道
    network, err := gw.GetNetwork("mychannel")
    if err != nil {
        log.Fatalf("Failed to get network: %v", err)
    }

    // 3. 获取合约实例
    contract := network.GetContract("basic")

    // 4. 调用链码函数
    result, err := contract.SubmitTransaction("CreateAsset", "asset6", "blue", "35", "Tom", "1300")
    if err != nil {
        log.Fatalf("Failed to submit transaction: %v", err)
    }
    fmt.Println(string(result))

    // 5. 查询资产
    result, err = contract.EvaluateTransaction("ReadAsset", "asset6")
    if err != nil {
        log.Fatalf("Failed to evaluate transaction: %v", err)
    }
    fmt.Println(string(result))
}

5. 部署链码

部署链码到 Fabric 网络的基本步骤:

  1. 打包链码
peer lifecycle chaincode package basic.tar.gz --path ./chaincode --lang golang --label basic_1.0
  1. 安装链码
peer lifecycle chaincode install basic.tar.gz
  1. 批准链码定义
peer lifecycle chaincode approveformyorg -o orderer.example.com:7050 --channelID mychannel --name basic --version 1.0 --sequence 1 --package-id $PACKAGE_ID
  1. 提交链码定义
peer lifecycle chaincode commit -o orderer.example.com:7050 --channelID mychannel --name basic --version 1.0 --sequence 1

最佳实践

  1. 错误处理:链码中必须正确处理错误,避免panic
  2. 状态验证:在修改状态前验证数据是否存在
  3. 日志记录:使用shim提供的日志功能
  4. 测试覆盖:编写全面的单元测试
  5. 性能优化:避免链码中的复杂计算

Hyperledger Fabric 提供了强大的企业级区块链功能,结合 Golang 的高效开发能力,可以构建出高性能、安全的区块链应用。

回到顶部