Hyperledger Fabric外部链码构建与运行

外部链码构建与运行



官方文档
在Hyperledger Fabric 2.0版本之前,链码的构建和运行是节点实现的一部分,并且定制化是困难的。所有链码在节点上实例化是通过”构建“即根据语言指定的逻辑在节点上硬编码。构建过程将生成Docker容器镜像作为客户端连接节点用来运行可执行的链码。
这种方法将链代码实现限制为只能使用几种语言实现,要求Docker成为部署环境的一部分,并阻止将链代码作为长时间运行的服务器进程运行。

外部构建模式

Hyperledger Fabric外部构建器和启动器大致基于Heroku Buildpacksbuildpack实现只是将程序归档转换为可以运行的程序或脚本的集合。buildpack模型已针对链码包进行了调整,并扩展为支持链码执行和发现。

外部构建和运行API

外部构建和运行由4个脚本程序组成:

  • bin/detect:确定是否应使用此buildpack来构建chaincode程序包并启动它
  • bin/build:转换链码包为可执行的链码
  • bin/release(可选):为peer节点提供关于链码的元数据
  • bin/run(可选):运行链码

bin/detect

bin/detect脚本决定是否应使用此buildpack来构建chaincode程序包并启动它,peer节点通过两个参数调用detect:

bin/detect CHAINCOD_SOURCE_DIR CHAINCODE_METADATA_DIR

detect被调用,CHAINCOD_SOURCE_DIR包含的链码资源以及CHAINCODE_METADATA_DIR包含的metadata.json文件将从链码包中安装到节点。CHAINCOD_SOURCE_DIRCHAINCODE_METADATA_DIR应该被作为只读输入。如果将buildpack应用于chaincode源程序包,detect必须返回退出码0;否则,其他任何退出代码都将指示buildpack不应用内于chaincode源程序包。
下面是一个简单的用于go语言链码的detect脚本例子:

#!/bin/bash

CHAINCODE_METADATA_DIR="$2"

# 使用jq工具从metadata.json中获取链码类型,如果链码类型为golang,则成功退出
if [ "$(jq -r .type "$CHAINCODE_METADATA_DIR/metadata.json" | tr '[:upper:]' '[:lower:]')" = "golang" ]; then
    exit 0
fi

exit 1

bin/build

bin/build脚本用于构建,编译,或者转换链码包的内容到可以被releaserun使用的类型。节点通过三个参数调用build:

bin/build CHAINCODE_SOURCE_DIR CHAINCODE_METADATA_DIR BUILD_OUTPUT_DIR

build被调用,CHAINCOD_SOURCE_DIR包含的链码资源以及CHAINCODE_METADATA_DIR包含的metadata.json文件将从链码包中安装到节点。BUILD_OUTPUT_DIR是一个文件夹用于存放releaserun需要的文件。build脚本应该将CHAINCOD_SOURCE_DIRCHAINCODE_METADATA_DIR作为只读输入,BUILD_OUTPUT_DIR作为可写输出。

下面是一个简单的用于go语言链码的build脚本例子:

#!/bin/bash

CHAINCODE_SOURCE_DIR="$1"
CHAINCODE_METADATA_DIR="$2"
BUILD_OUTPUT_DIR="$3"

# 从 metadata.json获取包内容
GO_PACKAGE_PATH="$(jq -r .path "$CHAINCODE_METADATA_DIR/metadata.json")"
if [ -f "$CHAINCODE_SOURCE_DIR/src/go.mod" ]; then
    cd "$CHAINCODE_SOURCE_DIR/src"
    go build -v -mod=readonly -o "$BUILD_OUTPUT_DIR/chaincode" "$GO_PACKAGE_PATH"
else
    GO111MODULE=off go build -v  -o "$BUILD_OUTPUT_DIR/chaincode" "$GO_PACKAGE_PATH"
fi

# 存储状态数据库索引元数据提供给release
if [ -d "$CHAINCODE_SOURCE_DIR/META-INF" ]; then
    cp -a "$CHAINCODE_SOURCE_DIR/META-INF" "$BUILD_OUTPUT_DIR/"
fi

bin/release

bin/release脚本为节点提供链码元数据。该脚本是可选的。如果没有提供,这一步将会跳过。节点通过两个参数调用release

bin/release BUILD_OUTPUT_DIR RELEASE_OUTPUT_DIR

调用release时,BUILD_OUTPUT_DIR包含构建程序填充的归档,应将其视为只读输入。RELEASE_OUTPUT_DIRrelease必须放置归档以供节点使用的目录。

release执行完成,节点将会从RELEASE_OUTPUT_DIR消费两种类型的元数据:

  • CouchDB定义的状态数据库索引。
  • 外部链码服务连接信息(chaincode/server/connection.json)

如果链码要求CouchDB索引定义,release需要将索引放置在RELEASE_OUTPUT_DIR下的state/couchdb/indexes文件夹内。索引必须含有.json扩展名。

在使用链码服务器实现的情况下,release负责使用链码服务器的地址以及与链码通信所需的任何TLS资产来填充chaincode/server/connection.json。将服务器连接信息提供给节点时,将不会调用run

下面是一个简单的用于go语言链码的release脚本例子:

#!/bin/bash

BUILD_OUTPUT_DIR="$1"
RELEASE_OUTPUT_DIR="$2"

# 从 META-INF/* 拷贝索引文件到输出文件夹
if [ -d "$BUILD_OUTPUT_DIR/META-INF" ] ; then
   cp -a "$BUILD_OUTPUT_DIR/META-INF/"* "$RELEASE_OUTPUT_DIR/"
fi

bin/run

bin/run脚本用于链码的运行。节点通过两个参数调用run

bin/run BUILD_OUTPUT_DIR RUN_METADATA_DIR

BUILD_OUTPUT_DIR包含build程序填充的归档,而RUN_METADATA_DIR包含有一个名为chaincode.json的文件,该文件包含链码连接和注册到节点所需的信息,run将被调用。bin/run脚本对于BUILD_OUTPUT_DIR以及RUN_METADATA_DIR文件夹应为只读输入。chaincode.json文件包含的关键信息有:

  • chaincode_id:连接到链码包的唯一ID
  • peer_address:``peer节点的ChaincodeSupport中的gRPC服务端点主机地址,格式为host:port.
  • client_cert:peer生成的PEM编码的TLS客户端证书。当链码与节点建立连接时将会被使用。
  • client_key:peer生成的PEM编码的客户端秘钥。当链码与节点建立连接时将会被使用。
  • root_cert:peer节点的ChaincodeSupport中的gRPC服务端点主机使用的PEM编码的TLS根证书。

run停止时,与peer连接的链码也会终止。如果另一个请求访问链码,节点将会尝试通过调用run启动链码的另一个实例。在调用链码时,chaincode.json文件内容不能够被缓存。

下面是一个简单的用于go语言链码的run脚本例子:

#!/bin/bash

BUILD_OUTPUT_DIR="$1"
RUN_METADATA_DIR="$2"

# 为go语言链码shim包配置环境变量
export CORE_CHAINCODE_ID_NAME="$(jq -r .chaincode_id "$RUN_METADATA_DIR/chaincode.json")"
export CORE_PEER_TLS_ENABLED="true"
export CORE_TLS_CLIENT_CERT_FILE="$RUN_METADATA_DIR/client.crt"
export CORE_TLS_CLIENT_KEY_FILE="$RUN_METADATA_DIR/client.key"
export CORE_PEER_TLS_ROOTCERT_FILE="$RUN_METADATA_DIR/root.crt"

# 为go语言链码shim包获取秘钥和证书材料
jq -r .client_cert "$RUN_METADATA_DIR/chaincode.json" > "$CORE_TLS_CLIENT_CERT_FILE"
jq -r .client_key  "$RUN_METADATA_DIR/chaincode.json" > "$CORE_TLS_CLIENT_KEY_FILE"
jq -r .root_cert   "$RUN_METADATA_DIR/chaincode.json" > "$CORE_PEER_TLS_ROOTCERT_FILE"
if [ -z "$(jq -r .client_cert "$RUN_METADATA_DIR/chaincode.json")" ]; then
    export CORE_PEER_TLS_ENABLED="false"
fi

# 执行链码并使用链码进程替代脚本
exec "$BUILD_OUTPUT_DIR/chaincode" -peer.address="$(jq -r .peer_address "$ARTIFACTS/chaincode.json")"

外部构建和运行的配置

core.yamlchaincode配置区域下添加一个externalBuilder元素配置节点以使用外部构建器.每一个外部构建器的定义必须包含名字(用于日志)和包含构建器脚本的bin文件夹的上一级路径。

调用外部构建器脚本时还可以从节点获取环境变量名称的可选列表。

下面的示例定义了两个外部构建器:

chaincode:
  externalBuilders:
  - name: my-golang-builder
    path: /builders/golang
    environmentWhitelist:
    - GOPROXY
    - GONOPROXY
    - GOSUMDB
    - GONOSUMDB
  - name: noop-builder
    path: /builders/binary

在这个示例中,实现的构建器my-golang-builder被包含在/builders/golang文件夹内,它的脚本文件位于/builders/golang/bin.当节点调用任何与my-golang-builder相关的构建脚本时,将只会传播白名单内的环境变量的值。

这些环境变量总是传播到外部构建器:

  • LD_LIBRARY_PATH
  • LIBPATH
  • PATH
  • TMPDIR

externalBuilder配置存在时,节点将会迭代按顺序排列的构建器的列表。调用/bin/detect直到其中的一个成功执行。
如果没有构建器成功执行detect脚本,节点将会回滚使用初始的Docker通过节点实现构建进程。这说明外部的构建器是完全可选的。

在上面的示例中,节点将试图使用my-golang-builder,如果无效的话则使用noop-builder,还是无效的话最后使用节点内部构建进程。

链码包

Fabric 2.0引入了新的生命周期链码。链码包的格式从序列号协议缓冲消息变为了由gzip压缩的POSIX tape归档。链码包通过使用peer lifecycle chaincode package创建新的格式。

Lifecycle链码包内容

lifecycle链码包包含两个文件,第一个文件code.tar.gz是一个使用gzip压缩的POSIX tape归档。这个文件包括链码的源归档。由节点CLI创建并将链码的实现源码放置在src文件夹下,链码的元数据(如CouchDB索引文件)放置在META-INF文件夹。

第二个文件metadata.json是一个JSON格式的文档包含三个键:

  • type:链码的类型(例如GOLANG,JAVA,NODE)
  • path:对于go语言链码,则是GOPATH或者GOMOD到主链码包的相对路径,其他类型的链码未定义。
  • label:用于生成包ID的链码标签,在新的链码lifecycle过程中用于标识包的身份。

typepath字段仅由Docker平台构建使用。

链码包以及外部构建器

当链码包安装在节点上后,code.tar.gzmetadata.json的内容将不能调用外部构建器处理。除了label字段用于新的lifecycle对包ID进行计算。为用户提供了很大的灵活性,使他们可以打包将由外部构建者和启动者处理的源和元数据。

例如,可以构造一个自定义的链码包,该代码包在code.tar.gz中包含一个预编译的链码实现,并带有一个metadata.json文件,允许二进制构建包检测该自定义包,验证哈希值并作为链码运行。

另一个示例是chaincode程序包,其中仅包含状态数据库索引定义以及外部启动程序连接到正在运行的chaincode服务器所需的数据。在这种情况下,build过程将仅从过程中提取元数据,然后将其release给节点。

唯一的要求是code.tar.gz只能包含常规文件和目录条目,并且这些条目不能包含会导致文件写入链码包根路径逻辑外。

原文地址:https://www.cnblogs.com/cbkj-xd/p/12093201.html

时间: 2024-08-30 02:46:21

Hyperledger Fabric外部链码构建与运行的相关文章

Hyperledger Fabric Java SDK最新教程

Fabric Java SDK是Fabric区块链官方提供的用于Java应用开发的SDK,全称为Fabric-sdk-java,网上可用资料不多,本文列出了精心整理的针对Fabric Java SDK的最新精选教程. 如果希望快速掌握Fabric Java SDK的使用方法,建议访问汇智网的在线互动教程: Fabric区块链Java开发详解 1.官方文档 使用Fabric Java SDK开发必备的手册,从Java SDK源代码注释生成的每个接口.类和方法的简要说明,聊胜于无,但是要指望它达到真

HyperLedger Fabric 1.2 kafka生产环境部署(11.1)

11.1 Kafka模式简介       上一章介绍的Solo模式只存在一个排序(orderer)服务,是一种中心化结构,一旦排序(orderer)服务出现了问题,整个区块链网络将会崩溃,为了能在正式环境中稳定运行,需要对排序(orderer)服务采用集群方式,Hyperledger Fabric采用kafka方式实现排序(orderer)服务的集群,kafka模块被认为是半中心化结构.       顺便提一下,去中心化的BFT(拜占庭容错)排序(orderer)服务集群方式目前还在开发,还没有

Hyperledger Fabric 1.0 从零开始(二)——公网环境构建

1:环境构建 在本文中用到的宿主机环境是Centos ,版本为Centos.x86_647.2,通过Docker 容器来运行Fabric的节点,版本为v1.0.因此,启动Fabric网络中的节点需要先安装Docker.Docker-compose和Go语言环境,然后在网上拉取相关的Docker镜像,再通过配置compose文件来启动各个节点. 1.1:Docker安装 进入docker官网 GetDocker ->Centos ->Get CE(社区版)->Get Docker CE o

Hyperledger Fabric 1.0 从零开始(三)——内网(准离线)环境构建

有公网环境的服务器可以直接看 Hyperledger Fabric 1.0 从零开始(二)--公网环境构建 ,本篇内容与上篇相似,只不过环境搭建需要在内网下,也就是网络被限制的情况下. 1:环境构建与测试 在本文中用到的宿主机环境是Centos ,版本为Centos.x86_647.2,通过Docker 容器来运行Fabric的节点,版本为v1.0.因此,启动Fabric网络中的节点需要先安装Docker.Docker-compose和Go语言环境,然后在网上拉取相关的Docker镜像,再通过配

实战:区块链hyperledger fabric 初体验 - 3: 链码实例安装、实例化、调用及代码

本文链码实例为Fabric 官方实例examples/chaincode/go/chaincode_example02,实现简单的转账功能 进入到cli容器里面 $ docker exec -it fabric-cli bash 1. 链码安装 以在org1, peer0 为例 1.1 设置环境变量 export CORE_PEER_LOCALMSPID=Org2MSPexport CORE_PEER_ADDRESS=peer1.org2.example.com:7051export CORE_

Hyperledger Fabric链码之二

上篇文章中我们介绍了链码的概念,本文中我们将介绍Fabric下链码的编写和测试.我们会通过一个简单例子的方式来阐述链码API的使用. 链码API     每一个链码程序都必须实现一个链码接口, 这些方法用来响应接受到的交易.特别的,当链码接收到Instantiate``和``upgrade``类型的交易时会调用``Init``方法,执行一些需要的初始化,包括应用状态的初始化.当链码接收到``Invoke``类型的交易时候会调用``Invoke``方法来处理交易提议. 链码中调用的其他接口“shi

HyperLedger Fabric Introduction——区块链超级账本介绍

介绍 HyperLedger Fabric是一个基于模块化架构的分布式账本解决方案平台,它拥有深度加密.便捷扩展.部署灵活及可插拔等特性.它设计之初的目的是支持不同组件的可插拔实现,并适应整个经济生态系统中存在的复杂性和高精度性. HyperLedger Fabric与其它的区块链平台解决方案相比,提供了一种独特的扩展便捷和灵活部署的架构.它更多的适用于联盟链形式,即适合企业级之间的区块链联盟方向,建立在可信任的基础上.如果是企业级区块链部署的话,建议可以采用HyperLedger Fabric

Hyperledger Fabric启用CouchDB为状态数据库

Hyperledger Fabric 启用CouchDB作为状态数据库 一.概述 数据请求流 超级账本采用背书/共识模型,模拟执行和区块验证是在不同角色的节点中分开执行的.模拟执行是并发的,这样可以提高扩展性和吞吐量: 背书节点:模拟执行链码 Peer节点:验证交易并提交 2.超级账本存储元素 超级账本包含以下元素: 账本编号:快速查询存在哪些账本 账本数据: 实际的区块数据存储 区块索引: 快速查询区块/交易 状态数据: 最新的世界状态数据 历史数据: 跟踪键的历史 每个Peer节点会维护四个

HyperLedger Fabric关键技术(6.4)

本节介绍从最底层的账本开始,逐一讲解账本的结构和存储.智能合约的编写和部署.通道的操作.节点的背书和提交.排序的共识和客户端SDK的接口调用,与交易流程顺序相反,由里及表的说明Fabric最关键的技术,通过学习了这六种关键技术知识,能初步掌握Fabric的核心,了解Fabric运作原理. 6.3.1 帐本(Ledger) Fabric帐本(Ledger)是一系列有序和防篡改的状态转换的记录,结构由一个区块链构成,并将不可变的.有序的记录存放在区块中:同时包含一个状态数据库来记录当前的状态,账本的