Hyperledger Fabric

  • 作为Hyperledger的一个主要项目,知名度也最高,这个项目于2015年12月开源
  • 最初由IBM 和 DAH(Digital Asset Holdings,由高盛、IBM、荷兰银行、埃森哲、 澳洲证券交易所、法国巴黎银行、Broadridge的金融解决方案、花旗银行、 CME Ventures、德意志交易所集团、 ICAP、桑坦德风投、证券托管清算公司(DTCC)、PNC金融服务集团投资) 贡献提交

  • 实现语言:Golang

概念术语

Auditability(审计性):在一定权限和许可下,可以对链上的交易进行审计和检查。

Block(区块):代表一批得到确认的交易信息的整体,准备被共识加入到区块链中。

Blockchain(区块链):由多个区块链接而成的链表结构,除了首个区块,每个区块都包 括前继区块内容的 hash 值。

Certificate Authority(CA):负责身份权限管理,又叫 Member Service 或 Identity Service。

Chaincode(链上代码或链码):区块链上的应用代码,扩展自“智能合约”概念,支持 golang、nodejs 等,运行在隔离的容器环境中。

Committer(提交节点):1.0 架构中一种 peer 节点角色,负责对 orderer 排序后的交易 进行检查,选择合法的交易执行并写入存储。

Confidentiality(保密):只有交易相关方可以看到交易内容,其它人未经授权则无法看 到。

Endorser(背书节点):1.0 架构中一种 peer 节点角色,负责检验某个交易是否合法, 是否愿意为之背书、签名。

Enrollment Certificate Authority(ECA,注册 CA):负责成员身份相关证书管理的 CA。

Ledger(账本):包括区块链结构(带有所有的可验证交易信息,但只有最终成功的交 易会改变世界观)和当前的世界观(world state)。

Ledger 仅存在于 Peer 节点。 MSP(Member Service Provider,成员服务提供者):成员服务的抽象访问接口,实现 对不同成员服务的可拔插支持。

Non-validating Peer(非验证节点):不参与账本维护,仅作为交易代理响应客户端的 REST 请求,并对交易进行一些基本的有效性检查,之后转发给验证节点。

Orderer(排序节点):1.0 架构中的共识服务角色,负责排序看到的交易,提供全局确 认的顺序。

Permissioned Ledger(带权限的账本):网络中所有节点必须是经过许可的,非许可过 的节点则无法加入网络。

Privacy(隐私保护):交易员可以隐藏交易的身份,其它成员在无特殊权限的情况下, 只能对交易进行验证,而无法获知身份信息。

Transaction(交易):执行账本上的某个函数调用。具体函数在 chaincode 中实现。

Transactor(交易者):发起交易调用的客户端。

Transaction Certificate Authority(TCA,交易 CA):负责维护交易相关证书管理的 CA。

Validating Peer(验证节点):维护账本的核心节点,参与一致性维护、对交易的验证和 执行。

World State(世界观):是一个键值数据库,chaincode 用它来存储交易相关的状态。


fabric 1.0 中每个 peer 结点会维护四个 db,

分别是 id store,存储 chainID;

stateDB,存储 world state;

versioned DB,存储 key 的版本变化;

还有 blockdb,存储 block。


逻辑架构

  • 身份验证(Membership)
    • 提供可插拔的方式实现成员管理,负责会员注册,身份保护,内容保密,交易审计功能,以保证平台访问的安全性。
  • 账本服务
    • 分布式账本的管理,账本数据的更新由共识服务(包括账本的分布式计算与存储、排序服务、网络协议、背书验证等)来完成。
  • 智能合约
    • 可编程的账本,提供在区块链上运行业务逻辑的能力。
  • APIs,事件以及SDKs
    • 事件流贯穿于其他各个组件中间,为各个组件中的异步通信提供了技术实现。
    • 多语言实现的原生SDK,帮助DLT app的开发。


区块链服务

区块链服务提供一个分布式账本平台。

一般地,多个交易被打包进区块中,多个区块构成一 条区块链。

区块链代表的是账本状态机发生变更的历史过程。


交易内容

交易意味着围绕着某个链码进行操作。

交易可以改变世界状态。

交易中包括的内容主要有:

交易类型:目前包括 Deploy、Invoke、Query、Terminate 四种;

uuid:代表交易的唯一编号;

链码编号 chaincodeID:交易针对的链码;

负载内容的 hash 值:Deploy 或 Invoke 时候可以指定负载内容;

交易的保密等级 ConfidentialityLevel;

交易相关的 metadata 信息;

临时生成值 nonce:跟安全机制相关;

交易者的证书信息 cert;

签名信息 signature;

metadata 信息;

时间戳 timestamp。 

交易的数据结构(Protobuf 格式)定义为

message Transaction {

enum Type {

UNDEFINED = 0; // deploy a chaincode to the network and call `Init` function

CHAINCODE_DEPLOY = 1; // call a chaincode `Invoke` function as a transaction

CHAINCODE_INVOKE = 2; // call a chaincode `query` function

CHAINCODE_QUERY = 3; // terminate a chaincode; not implemented yet

CHAINCODE_TERMINATE = 4;

}

Type type = 1; //store ChaincodeID as bytes so its encrypted value can be stored

bytes chaincodeID = 2;

bytes payload = 3;

bytes metadata = 4;

string uuid = 5;

google.protobuf.Timestamp timestamp = 6;

ConfidentialityLevel confidentialityLevel = 7;

string confidentialityProtocolVersion = 8;

bytes nonce = 9;

bytes toValidators = 10;

bytes cert = 11;

bytes signature = 12;

}

在 1.0 架构中,一个 transaction 包括如下信息:

[ledger] [channel], proposal:[chaincode, ] endorsement:[proposal hash, simulation result, signature]

endorsements: proposal hash, simulation result, signature

function-spec: function name, arguments

proposal: [channel,] chaincode,


区块

区块打包交易,确认交易后的世界状态。

一个区块中包括的内容主要有:

版本号 version:协议的版本信息;

时间戳 timestamp:由区块提议者设定;

交易信息的默克尔树的根 hash 值:由区块所包括的交易构成;

世界观的默克尔树的根 hash 值:由交易发生后整个世界的状态值构成;

前一个区块的 hash 值:构成链所必须;

共识相关的元数据:可选值;

非 hash 数据:不参与 hash 过程,各个 peer 上的值可能不同,例如本地提交时间、交 易处理的返回值等;

注意具体的交易信息并不存放在区块中。

区块的数据结构(Protobuf 格式)定义为

message Block{

uint32 version = 1;

google.protobuf.Timestamp timestamp = 2;

repeated Transaction transactions = 3;

bytes stateHash = 4;

bytes previousBlockHash = 5;

bytes consensusMetadata = 6;

NonHashData nonHashData = 7;

}


一个真实的区块内容示例:

{

    "nonHashData": {

        "localLedgerCommitTimestamp": {

                "nanos": 975295157,

                "seconds": 1466057539

            },

        "transactionResults": [

        {

            "uuid": "7be1529ee16969baf9f3156247a0ee8e7eee99a6a0a816776acff65e6e1de f71249f4cb1cad5e0f0b60b25dd2a6975efb282741c0e1ecc53fa8c10a9aaa31137"

        }

        ]

    },

    "previousBlockHash": "RrndKwuojRMjOz/rdD7rJD/NUupiuBuCtQwnZG7Vdi/XXcTd2MDyAMsF AZ1ntZL2/IIcSUeatIZAKS6ss7fEvg==",

    "stateHash": "TiIwROg48Z4xXFFIPEunNpavMxnvmZKg+yFxKK3VBY0zqiK3L0QQ5ILIV85iy7U+ EiVhwEbkBb1Kb7w1ddqU5g==",

    "transactions": [

    {

        "chaincodeID": "CkdnaXRodWIuY29tL2h5cGVybGVkZ2VyL2ZhYnJpYy9leGFtcGxlcy9jaGFpbmNvZGUvZ28vY2hhaW5jb2RlX2V4YW1wbGUwMhKAATdiZTE1MjllZTE2OTY5YmFmOWYzMTU2MjQ3YTBlZThl N2VlZTk5YTZhMGE4MTY3NzZhY2ZmNjVlNmUxZGVmNzEyNDlmNGNiMWNhZDVlMGYwYjYwYjI1ZGQyYTY5NzVlZm IyODI3NDFjMGUxZWNjNTNmYThjMTBhOWFhYTMxMTM3",

        "payload": "Cu0BCAESzAEKR2dpdGh1Yi5jb20vaHlwZXJsZWRnZXIvZmFicmljL2V4YW1wbG VzL2NoYWluY29kZS9nby9jaGFpbmNvZGVfZXhhbXBsZTAyEoABN2JlMTUyOWVlMTY5NjliYWY5ZjMxNTYyNDdhMGVlOGU3ZWVlOTlhNmEwYTgxNjc3NmFjZmY2NWU2ZTFkZWY3MTI0OWY0Y2IxY2FkNWUwZjBiNjBiMjVkZDJhNj k3NWVmYjI4Mjc0MWMwZTFlY2M1M2ZhOGMxMGE5YWFhMzExMzcaGgoEaW5pdBIBYRIFMTAwMDASAWISBTIwMDAw" ,

        "timestamp": {

            "nanos": 298275779,

            "seconds": 1466057529

        },

        "type": 1,

        "uuid": "7be1529ee16969baf9f3156247a0ee8e7eee99a6a0a816776acff65e6e1def712 49f4cb1cad5e0f0b60b25dd2a6975efb282741c0e1ecc53fa8c10a9aaa31137"

    }

    ]

}


世界观

世界观用于存放链码执行过程中涉及到的状态变量,是一个键值数据库。

典型的元素为 [chaincodeID, ckey]: value 结构。

为了方便计算变更后的 hash 值,一般采用默克尔树数据结构进行存储。

树的结构由两个参数 ( numBuckets 和 maxGroupingAtEachLevel )来进行初始配置,并由 hashFunction 配置决定 存放键值到叶子节点的方式。

显然,各个节点必须保持相同的配置,并且启动后一般不建议 变动。

    numBuckets :叶子节点的个数,每个叶子节点是一个桶(bucket),所有的键值被hashFunction 散列分散到各个桶,决定树的宽度;

    maxGroupingAtEachLevel :决定每个节点由多少个子节点的 hash 值构成,决定树的深 度。

其中,桶的内容由它所保存到键值先按照 chaincodeID 聚合,再按照升序方式组成。


链码服务

链码包含所有的处理逻辑,并对外提供接口,外部通过调用链码接口来改变世界观。

接口和操作

链码需要实现 Chaincode 接口,以被 VP 节点调用。

type Chaincode interface { Init(stub *ChaincodeStub, function string, args []string) ([ ]byte, error) Invoke(stub *ChaincodeStub, function string, args []string) ([]byte, err or) Query(stub *ChaincodeStub, function string, args []string) ([]byte, error)}

链码目前支持的交易类型包括:部署(Deploy)、调用(Invoke)和查询(Query)。

部署:VP 节点利用链码创建沙盒,沙盒启动后,处理 protobuf 协议的 shim 层一次性发 送包含 ChaincodeID 信息的 REGISTER 消息给 VP 节点,进行注册,注册完成后,VP 节点通过 gRPC 传递参数并调用链码 Init 函数完成初始化;

调用:VP 节点发送 TRANSACTION 消息给链码沙盒的 shim 层,shim 层用传过来的参 数调用链码的 Invoke 函数完成调用;

查询:VP 节点发送 QUERY 消息给链码沙盒的 shim 层,shim 层用传过来的参数调用链 码的 Query 函数完成查询。

不同链码之间可能互相调用和查询。 

容器

在实现上,链码需要运行在隔离的容器中,超级账本采用了 Docker 作为默认容器。

对容器的操作支持三种方法:build、start、stop,对应的接口为 VM。

type VM interface { build(ctxt context.Context, id string, args []string, env []string, attachstdin bool, attachstdout bool, reader io.Reader) error start(ctxt context.Context, id string, args []string, env []string, attachstdin bool, attachstdout bool) error stop(ctxt context.Context, id string, timeout uint, dontkill bool, dontremove bool) error }

链码部署成功后,会创建连接到部署它的 VP 节点的 gRPC 通道,以接受后续 Invoke 或 Query 指令。 

gRPC 消息

VP 节点和容器之间通过 gRPC 消息来交互。消息基本结构为

message ChaincodeMessage { enum Type { UNDEFINED = 0; REGISTER = 1; REGISTERED = 2; INIT = 3; READY = 4; TRANSAC TION = 5; COMPLETED = 6; ERROR = 7; GET_STATE = 8; PUT_STATE = 9; DEL_STATE = 10; INVO KE_CHAINCODE = 11; INVOKE_QUERY = 12; RESPONSE = 13; QUERY = 14; QUERY_COMPLETED = 15; QUERY_ERROR = 16; RANGE_QUERY_STATE = 17; } Type type = 1; google.protobuf.Timestamp timestamp = 2; bytes payload = 3; string uui d = 4;}

当发生链码部署时,容器启动后发送 REGISTER 消息到 VP 节点。如果成功,VP 节点返回 REGISTERED 消息,并发送 INIT 消息到容器,调用链码中的 Init 方法。

当发生链码调用时,VP 节点发送 TRANSACTION 消息到容器,调用其 Invoke 方法。如果成 功,容器会返回 RESPONSE 消息。

类似的,当发生链码查询时,VP 节点发送 QUERY 消息到容器,调用其 Query 方法。如果成 功,容器会返回 RESPONSE 消息。

 

成员权限管理

通过基于 PKI 的成员权限管理,平台可以对接入的节点和客户端的能力进行限制。

证书有三种,Enrollment,Transaction,以及确保安全通信的 TLS 证书。

注册证书 ECert:颁发给提供了注册凭证的用户或节点,一般长期有效;

交易证书 TCert:颁发给用户,控制每个交易的权限,一般针对某个交易,短期有效。

通信证书 TLSCert:控制对网络的访问,并且防止窃听。


网络架构

网络中的节点类型分为了orderer节点、endorser节点、committer节点 。

运行架构

application提供各种语言的SDK接口。

membership也就是fabric-ca提供成员服务,用来管理身份,提供授权和认证。

peer负责模拟交易和记账

Endorser(背书)用来当peer执行一个交易以后返回yes/no。
Committer将验证过的区块追加到通道上各个账本的副本。
Ledger就是账本啦。
Chaincode用来编写业务逻辑,交易指令用来修改资产,可以理解为 fabric 网络对外提供的一个交互接口(智能合约)。
Event是fabric提供的一个事件框架,比如链代码事件,拒绝事件,注册事件等,在编写代码的时候可以订阅这些事件来实现自己的业务逻辑。
o-service用来实现共识。


事务执行流程

  • 主要的事务执行流程如下图所示,首先应用程序通过SDK需要先把用户信息注册到区块链网络中(主要通过fabric-ca模块实现)
  • 注册并登录成功后,向背书节点发起一个事务请求,背书节点执行Chaincode,得到模拟的结果,但不将结果执行提交到本地账本,只是将结果返回给应用
  • 应用得到正确的背书请求结果后,则提交对应的处理结果给排序节点,排序节点并不关心交易数据具体是什么,负责对所有的交易进行一个排序并生成对应的区块
  • 排序节点处理完成后,会将生成的区块进行广播分发,提交节点则负责对提交的区块进行验证,验证通过后则写入账本,同一个物理节点可同时充当背书节点和提交节点的角色。

客户端:客户端应用使用 SDK 来跟 Fabric 打交道,构造合法的交易提案提交给endorser;收集到足够多 endorser 支持后可以构造合法的交易请求,发给 orderer 或代 理节点。

Endorser peer:负责对来自客户端的交易进行合法性和 ACL 权限检查(模拟交易),通 过则签名并返回结果给客户端。

Committer peer:负责维护账本,将达成一致顺序的批量交易结果进行状态检查,生成区 块,执行合法的交易,并写入账本,同一个物理节点可以同时担任 endorser 和 committer 的 角色。

Orderer:仅负责排序,给交易们一个全局的排序,一般不需要跟账本和交易内容打交 道。

CA:负责所有证书的维护,遵循 PKI。

 

 

事务处理流程

• 应用向一个或多个Peer节点发送对事务 的背书请求;

• 背书节点执行ChainCode,但并不将结果 提交到本地账本,只是将结果返回给应用;

• 应用收集所有背书节点的结果后,将结 果广播给Orderers;

• Orderers执行共识过程,并生成Block, 通过消息通道批量的将Block发布给Peer 节点;

• 各个Peer节点验证交易,并提交到本地 账本(lerdger)中。

事务流程(peer节点内)

• 每个ChainCode在部署时,都需 要和背书(ESCC)和验证 (VSCC)的系统ChainCode关联;

• ESCC决定如何对proposal进行背 书;

• VSCC决定事务的有效性(包括 背书的正确性);

Fabric核心概念

channel

  • 通道是构建在我们构建的区块链网络上的私有区块链,通过一种数据隔离机制来控制交易的可见性,保证只对交易干系人可见,也就是说在我们构建的区块链网络上允许有多个通道的实现。
  • 共识机制只针对同一个通道内的成员有效,一般一个通道单独维护一份账本
  • 多通道并存示例如下所示

 

chaincode

  • chaincode也称之为链码,是智能合约的实现方式。
  • 部署在Fabric区块链的网络节点上,是上层应用与区块链交互的唯一渠道
  • 生成Transaction的唯一来源 Transactions -> Blocks -> Ledger
  • 实现语言主要是Go,也支持Java语言的实现,不过目前还不太完善。关键需要实现chaincode接口中定义的方法,如下图所示。

 

  • 一个chaincode可以被部署到多个通道上,每个实例都是独立的
  • 一个chaincode原则上可以通过ACL查询其他通道上的chaincode
  • 节点内事务流向如下图所示,每个Chaincode在部署时,都需要和背书(ESCC)、验证(VSCC)的系统Chaincode关联。ESCC指定proposal(请求)的背书策略,VSCC则负责对事务的有效性进行验证(包括背书的正确性)

Orderer

    • 由一组节点组成并运行排序服务,提供原子广播

    • 排序服务是网络的一个重要部分,负责接受事务请求以及创建分发区块以及整个网络的相关配置

    • 它面向的客户端就是其他网络节点和应用客户端

    • 提供可插拔的共识机制(SOLO/Kafka/PBFT)

 

Peer

 

    • 是网络中维护账本状态和管理Chaincodes的组成部分
    • 从职责来看,可划分为背书节点(Endorser)和提交节点(Committer)
    • 节点间形成对等的 gossip(遵循该协议)网络

Ledger

 

  • 每个通道中会维护一个单独的交易数据账本,如下图所示,账本主要包含交易的日志信息和具体的交易数据。
  • 具体的交易数据由一个状态数据库来进行存储,默认采用goLevelDB实现,目前可替换为CouchDB的实现。

 

 

Membership Service Provider

  • MSP是指为client和peer提供证书的系统抽象组件
  • 管理应用、背书节点、排序节点的身份识别

 

 

Fabric-CA

  • 实现MSP的接口,默认的证书管理组件,它向网络成员及其用户颁发基于PKI的证书。CA为每个成员颁发一个根证书(rootCert),为每个授权用户颁发一个注册证书(eCert),为每个注册证书颁发大量交易证书(tCerts)
  • 支持高可用集群
  • 支持LDAP用户身份验证
  • 支持HSM(硬件安全模组)

Fabric CA提供以下功能:

  1. 身份注册,或者将连接到LDAP作为用户注册;
  2. 颁发登录证书(ECerts);
  3. 颁发交易证书(TCerts),保证链上交易的匿名性与不可连接性;
  4. 证书续期与撤销


消息协议

节点之间通过消息来进行交互,所有消息都由下面的数据结构来实现。

message Message {

enum Type {

UNDEFINED = 0;

DISC_HELLO = 1;

DISC_DISCONNECT = 2;

DISC_GET_PEERS = 3;

DISC_PEERS = 4;

DISC_NEWMSG = 5;

CHAIN_STATUS = 6;

CHAIN_TRANSACTION = 7;

CHAIN_GET_TRANSACTIONS = 8;

CHAIN_QUERY = 9;

SYNC_GET_BLOCKS = 11;

SYNC_BLOCKS = 12;

SYNC_BLOCK_ADDED = 13;

SYNC_STATE_GET_SNAPSHOT = 14;

SYNC_STATE_SNAPSHOT = 15;

SYNC_STATE_GET_DELTAS = 16;

SYNC_STATE_DELTAS = 17;

RESPONSE = 20;

CONSENSUS = 21;

}

Type type = 1;

bytes payload = 2;

google.protobuf.Timestamp timestamp = 3;

}

消息分为四大类:Discovery(探测)、Transaction(交易)、Synchronization(同步)、 Consensus(一致性)。

不同消息类型,对应到 payload 中数据不同,分为对应的子类消息结构。


隐私与安全

区块链的业务安全需求

– 不可更改的加密交易数据(分布式账本)

– 可追责、不可陷害

– 隐私保护:交易匿名、交易不可关联

– 监管和审计支持

 

Fabric的CA支撑环境

– CA是Membership的重要组件之一

– 满足于Fabric的安全需求,为参与各方实现:

• 用户注册

• 证书签发

• 证书吊销

• 发布证书链

– 基于RESTful/CLI等多种接口方式,服务于 Blockchain的各个环节,包括:

• T-Cert – Transaction Certificate (交易证书证书), 执行交易时使用

• E-Cert – Enrollment Certificate (注册证书),携带 实体信息的证书 

• CSR – 证书吊销列表

 

 

区块数据的结构 --- 区块链

– 把一段时间内生成的信息(包括数据或代码)打包成一个区块,盖上时间 戳,

与上一个区块衔接在一起,每下一个区块的页 首都包含了上一个区块的索引数据,

然后再在本页中写入新的信息,从而形成新的区块,首尾相连,最终形成了区块链。

 

区块数据的构成 --- 事务(交易)数据

– 每个区块中包含一系列的事务数据

– 事务中包含事务发起方的数字签名(TCert – 交易证书)

– 每个Block中包含所有事务的Hash, 用于共识时检查事务信息是否与其它节点一致

– 每个Block中包含World State的Hash, 用于共识时检查State信息是否与其它节点一致

 

– PKI相关的密码学在BlockChain中的应 用保障单个Peer上数据的完整性

• 数字签名

    – 不可抵赖,防篡改

• Hash

• 加密

    – 事务隐私保护

    – 数据访问控制

– 共识机制及BlockChain数据分布化, 可以防止某个Peer造假,达到高度自 治


区块数据的构成 --- 如何做到交易抗抵赖

– 由交易“提交方”使用自己的“数字证书”对每个交易做 “数字签名”来确保交易无法伪造

– 这笔交易确实是你提交的,别人无法伪造你的交易!

– 既然无法伪造一个交易,所以如果存在一个你的“交易”,那么你也无法抵赖

– 这里的“你”是指用户的数字身份,数字身份就是“某个数字证书的持有者”

 


如何防止分布式账本的伪造

– 利用数字签名,伪造一个他人的单个交易非常困难,除非能够获得他人数字证书的私钥

– 另外分布式账本可以防止如下类型的篡改:

• 删除历史交易

• 伪造自己的历史交易

 

 


如何保障私密

– 确保交易仅仅向有限的全体可见,不对非授权的全体公开

– 简单来看,分别使用授权用户的“公钥”加密“数据”,只有授权用户能够用自己的“私钥”解密数据

– 实际实现,则通过“对称加密和公钥加密”相结合的方式


如何既保障交易私密,又可以实现监管





猜你喜欢

转载自blog.csdn.net/weixin_41926234/article/details/80623553