基于区块链技术的超级账本(Hyperledger)-从理论到实战 什么是区块链?简单来说区块链就是⼀个分布式的记账本,或者分布式的数据库。
区块链的数据结构是⼀个链表,交易数据被存储到链表的区块中,区块链的第⼀个区块叫创世区块,除了创世块以外,每个区块还包含前⼀个区块的哈希指针,这个哈希指针的值是根据前⼀个区块的实际数据计算出来的。哈希指针指向前⼀个区块,后⾯的区块可以查前⾯所有区块的信息。 账本的数据结构就是这样的⼀个链表,那么分布式的含义是什么呢?
区块链的众多参与者组成了⼀个松散⾃治的 P2P ⽹络,我们把区块链⽹络的参与者叫做节点,每个节点都拥有⼀个账本拷贝,所有账本的信息都是⼀致的,在区块链⾥没有中⼼节点。每当有新的交易进来,所有节点的账本都会更新,并且最终保持⼀致。更新的⽅式不是去修改某个区块的值,⽽是保存交易记录。⽐如在⽐特币系统中,它没有⽤户资产记录这样的概念,不像普通数据库那样⽤⼀条数据存储资产,⽐特币⽤户资产的值是通过把所有的交易记录串联聚合后得到的,账户⾥资产的来源可以⼀直向上追溯,直到创世块为⽌。区块链⾥的交易数据根据具体场景,可以是任何需要记录的信息。 为了⽀持信息的持续更新,以及对账本进⾏管理(写⼊交易,进⾏查询等),区块链⽹络引⼊了智能合
约来实现对账本的访问和控制。智能合约不仅仅可⽤于在区块链⽹络中打包信息,它们也可以被⽤于⾃动的执⾏由参与者定义的特定交易操作。
⽐如智能合约可以规定物流中的运输费⽤,根据物流的快慢收取不同的费⽤,根据货物的到达时间进⾏⾃动转账等。上传到区块链⽹络中的的智能合约会被打包到某⼀个区块中,因此智能合约⼀旦写⼊区块链,也是不可更改的。
共识机制
区块链⽹络中交易信息同步的过程,确保交易只有获得适当参与者批准后才更新,所有的参与者都会将同样的信息按照同样的顺序更新,这样的过程叫做共识。共识机制是区块链的核⼼之⼀。
区块链的第⼀个应⽤⽐特币,采⽤的是Proof of Work(⼯作量证明)的共识机制。简单介绍⼀下⽐特币的共识机制,算法的具体细节⼤家可以去查⽩⽪书。节点收到⼀个交易后,会根据判断标准对该交易进⾏有效性校验,⽆效的交易会被废弃。通过有效性验证之后的交易将会被⼴播给其他节点。其他节点会做同样的独⽴校验,当有效的交易达到整个⽹络所有节点时,即全⽹达成了“该交易有效”的共识。每个节点都会收到很多有效但是还未被打包到区块中的交易,这些交易被组装成 Merkle Tree,Merkle Tree 的第⼀个交易⽐较特殊,叫做 coinbase,由节点⾃⼰创建,将挖矿奖励⽀付到矿⼯⾃⼰的地址。挖矿奖励包括新创建的⽐特币和打包进该区块所有交易的⼿续费总额。然后节点计算⼀个符
合难度的哈希值,挖矿就是通过修改参数不断计算区块哈希值,直⾄达到难度要求,也就间接证明了该节点付出了对应的⼯作量,这就是⼯作量证明。笔者的另⼀篇⽂章⾥⽤了⼀个 ABAP ⽅法CL_ABAP_MESSAGE_DIGEST=>CALCULATE_HASH_FOR_CHAR 来计算区块的哈希值。
当节点计算出⼀个符合难度的区块哈希时,即说明该矿⼯挖矿成功了,该节点将该区块组装到本地的区块链,同时也将此区块⼴播给其他节点。其他节点接收到该区块后会验证该区块是否有效,有可能有两个节点同时挖出了新的区块 B1 和 B2,它们的上⼀个区块都是同⼀个区块P。有的节点可能会先收到 B1,有的会先收到 B2,这时区块链出现了暂时性的两个分叉。要打破这种局⾯,要看下⼀个区块是基于 B1 ⽣成还是基于 B2 ⽣成。如果基于 B1,B1 这条链就变成了最长链,其他包含 B2 的节点会重新选择最长链,⽽ B2 作为孤块被丢弃掉。
到⽬前为⽌,我们可以将区块链看做是⼀个共享的,去中⼼化的多备份系统,通过智能合约更新交易数据,同时借助共识的协作流程使⽹络中所有的节点保持⼀致。
这⾥的交易可以指代任何数据,例如:,合同,记录或者其它任何信息。
区块链的类型
公有链:⽹络中的节点可以任意接⼊,⽹络中数据读写权限不受限制,所有节点都参与共识过程。⽐特币,以太坊等都属于公有链。
私有链:⽹络中的节点被⼀个组织控制,由其独享该区块链的写⼊权限,私有链和其他的分布式存储没有太⼤区别。
联盟链:多个公司或组织通过授权接⼊,由某些节点参与共识过程。Hyperledger Fabric属于联盟链。
什么是 Hyperledger Fabric?
Hyperledger Fabric 是 Linux 基⾦会发起的 Hyperledger 项⽬之⼀。Hyperledger Fabric 专为在企业环境中使⽤⽽设计的开源的基于区块链的分布式账本。Hyperledger Fabric 可⽤于全球供应链管理、⾦融交易、资产记账、⼈⼒资源、保险、健康和数字⾳乐等领域。
Hyperledger Fabric 中的账本⼦系统(ledger)包括两个组件:世界观(world state)和事务⽇志(transaction log)。世界观记录了账本在特定时间点的现状,是⼀个键值数据库。交易⽇志记录产⽣世界状态当前值的所有交易,是世界观的更新历史。账本的世界观的底层数据库可以更换,可以选择使⽤ levelDB 或 couchDB。
供应链金融管理
Hyperledger Fabric 是第⼀个⽀持以通⽤语⾔编写智能合约的区块链平台,可以使⽤java,nodejs 和 go 语⾔来编写智能合约。Hyperledger Fabric 中的智能合约也叫链码(chain code)。
和其他公有区块链平台最⼤的不同,Hyperledger Fabric 是私有的并且需要授权才能接⼊,它拥有⼀
个 MSP(Membership Service Provider)模块专门提供成员管理服务。
CA(Certificate Authority) 负责权限管理,成员⾝份相关证书管理 (Enrollment CertificateAuthority) 和维护交易相关证书管理 (Transaction Certificate Authority) 等等。
Hyperledger Fabric 提供了建⽴ channel 的功能,这允许参与者为交易新建⼀个单独的账本。当⽹络中的⼀些参与者是竞争对⼿时,这个功能变得尤为重要。因为这些参与者并不希望所有的交易信息——⽐如提供给部分客户的特定价格信息——都对⽹络中所有参与者公开。只有在同⼀个 channel 中的参与者,才会拥有该 channel 中的账本,⽽其他不在此 channel 中的参与者则看不到这个账本。
Hyperledger Fabric 使⽤独⽴的排序节点(order)来提供共识服务,负责排序交易,提供全局确认的交易顺序。
应⽤程序通过 SDK 访问 Hyperledger Fabric。
最新版 Hyperledger Fabric 的设计中,根据功能将节点⾓⾊解耦开,让不同节点处理不同类型的⼯作负载。从业务逻辑上⼜将节点分为背书节点(Endorser)和提交节点(Committer)。
Endorser peer:负责对来⾃客户端的交易进⾏合法性和权限检查(模拟交易),通过检查则签名并返回结果给客户端。
Committer peer:负责维护账本,将达成⼀致顺序的批量交易结果进⾏状态检查,⽣成区块,执⾏合法的交易,并写⼊账本,同⼀个物理节点可以同时担任 endorser 和committer 两个⾓⾊。
Hyperledger Fabric 交易流程:共识
共识流程主要分 Proposal,Packaging 和 Validation 三个阶段。
Proposal
玻璃夹胶机应⽤提交⼀个交易 proposal,然后将其提交给所有的背书节点,后者接到后,将其作为输⼊执⾏链码⽣成相应的交易 proposal 响应。此时并不会更新 Ledger,⽽是对交易proposal 响应签名,并将其返回给应⽤。应⽤收到签名后的响应,共识流程的第⼀阶段就完成了。
Packaging
这个阶段是 order 节点对交易进⾏排序打包。Order 节点从各个应⽤接收交易 proposal响应,然后对这些交易进⾏排序,排序之后打包成区块。
Validation
共识流程的最后⼀个阶段,由 order 节点将区块分发给所有和它连接的节点,这些节点将确认区块中的交易都经过背书节点签名,然后将确认后的区块更新到 ledger 中。
整个流程称为共识,所有节点都已对交易内容和顺序达成⼀致,这⼀过程由 order 节点控制。共识是⼀个多步骤的过程,只有在整个流程完成时才会更新账本,可能每个节点的更新时间稍有不同。
构建⼀个 Hyperledger Fabric 平台绝⾮易事,既需要硬件基础设施的投⼊,也需要全⽅位的开发和运营管理(DevOps)。除了平台本⾝,⼀套完整的解决⽅案,还包括设备接⼊,访问控制,服务监控等管理功能。
SAP Cloud Platform(下⽂简称 SCP )提供了开箱即⽤的 Hyperledger Fabric Service,为开发者提供了强⼤的服务⽀持:直观友好的可视化监控与操作界⾯,帮助开发者按需申请区块链⽹络,创建管理节点、渠道,⽽⽆需考虑底层硬件资源。
简单易⽤的智能合约开发与测试环境,⽅便开发者对应⽤代码进⾏管理。
安全,隐私性⽅⾯的保障,并对相关资源进⾏了性能优化。
下⾯是具体的实战步骤,该步骤使⽤ go 语⾔开发⼀组微服务,这组微服务包含读和写两个API,能够将数据写⼊架设于 SAP 云平台上的超级账本服务。
简单地说,应⽤程序通过智能合约接⼝同超级账本进⾏读写操作。我们将开发⼀个 Hello World 的智能合约,部署到 SAP 云平台上。出于
简单起见,我们没有开发应⽤,⽽是简单地在 SAP 云平台的 API 控制台上直接消费这个 Hello World 的智能合约,对云平台上的超级账本进⾏读和写。
打开超级账本项⽬ Fabric 的 github 仓库地址:
发现 Fabric 项⽬是 Google 的编程语⾔ GoLang 开发的,因此咱们这个练习也使⽤ Go 语⾔来进⾏智能合约的开发。
1. 从 Google ⽹站上将 Go 语⾔ 1.11 版的⼆进制包下载到本地,解压到 /usr/local ⽬录下:
sudo tar -C /usr/local -xzf /home/vagrant/Downloads/go1.11.
将该⽬录配置到环境变量 PATH 中去:
2. Fabric 项⽬已经将智能合约同超级账本的通信封装到⼀个名叫 shim 的接⼝中,我们只需要在我们编写的智能合约代码中直接调⽤该
shim 接⼝即可。
我们使⽤ import 将这个 shim 接⼝的依赖引⼊进来,在第14⾏定义⼀个结构体,包含 ID 和 Value 两个字段。这个结构体即是待写⼊超级账本的数据结构,ABAP 顾问可以将其视为 ABAP 数据字典⾥定义的结构体。
第46⾏定义的⽅法 Invoke 是这个最简单的智能合约的核⼼代码,cc *MessageStore 这个语法和 C 语⾔很像,定义了⼀个类型为MessageStore 的指针变量 cc。这个指针变量同 C++ 的 this 指针和 ABAP 的 me 引⽤作⽤类似,在⽅法被调⽤时,指向了⽅法的调⽤者。Invoke 后⾯括号⾥的 stub shim.ChaincodeStubInterface 定义了该⽅法的输⼊参数(形参)stub, 类型为 shim.ChaincodeStubInterface。
这个 Invoke ⽅法不会通过应⽤程序显式调⽤,⽽是通过超级账本程序回调:当⽅法被调⽤时,指针 cc 和输⼊参数 stub 已经⾃动被 Fabric 框架赋上了对应值。在 Invoke ⽅法运⾏的上下⽂⾥,通过输⼊参数 stub 判断出当前回调的场景是读还是写,然后进⼊对应的分⽀。分⽀内部调⽤我们⾃⼰开发的 write 和 read ⽅法同超级账本进⾏交互。
雨棚制作
这种通过同⼀个回调函数内部的 switch case 来处理多个场景的做法,ABAP 和 Java 开发者应该都不陌⽣。⽐如下图是通过InvocationHandler 实现 Java 动态代理的例⼦,其中 invoke ⽅法的逻辑结构和本⽂智能合约代码的结构⾮常相似。
关于 ABAP 和 Java ⾥各种静态代理和动态代理的写法,请参考我的博客:
3. 将开发好的智能合约源⽂件构建成可执⾏⽂件。这⼀步确保在部署智能合约到 SAP 云平台之前,先在本地开发环境将所有潜在错误全
电极扁钢部检测出并修复。
4. 登录 SAP 云平台,在 Service Marketplace ⾥点击 Hyperledger Fabric 的超链接:
创建⼀个新的 Service 实例:
创建过程中需要填写 channel 的 ID 和密匙。
区块链分为公有链,私有链和联盟链,⽽超级账本属于联盟链。在联盟链⾥,有⼀个专门的称为 MSP(Membership Service Provider)的模块,提供成员管理服务,只有授权⽤户才能接⼊区块链⽹络。这⾥我事先在 SAP 云平台上创建了⼀个渠道并进⾏认证,因此此处直接输⼊⼀个合法的渠道 ID 和密匙。关于 SAP 云平台上超级账本渠道的创建和成员授权接⼊的步骤,请参考这篇 SAP 。
Service 实例创建完毕后,点击 Create Service Key 按钮创建 key,⽬的是⽣成⽤于OAuth 认证的 clientId 和 clientSecret,⽅便接下来的API 调⽤。
点击 Service 实例的 Referencing Apps ⾯板,点击按钮 Open Dashboard:
点击 Deploy Chaincode,选择本地构建好的 zip 包,进⾏上传并部署。这个按钮同 SAP 云平台 CloudFoundry 环境部署本地应⽤的逻辑相同。
部署成功后,点击 Test Chaincode 超链接进⼊ API 控制台。
该控制台集成了 Swagger 框架,在调⽤ post 请求进⾏超级账本的写操作和 get 请求进⾏读操作之前,先要点击 Authorize 按钮进⾏⾝份认证:
输⼊第四步创建 Service Key 后⽣成的 clientID 和 clientSecret 进⾏认证:
认证成功后,可以在 Swagger 的控制台⾥调⽤ post 和 get 请求了。
通讯仪⾸先发送 post 请求,请求负载就是⼀个简单的 json 对象,id 为 i042416,value 为Hello World:
post 请求在 SAP 云平台上的超级账本执⾏成功,返回 200 响应码:
自制巧克力模具
紧接着执⾏ get 请求,输⼊刚才写⼊的数据 id: i042416:
get 请求能够将之前通过 post 请求写⼊账本的数据成功读出来:
登录 SAP 云平台超级账本控制台,能看到之前通过 post 写⼊的数据已经加⼊到区块链尾部的区块了。点击区块可以查看数据明细:
在超级账本控制台的 API Calls 和 Logs ⾯板⾥也能看到每次超级账本读写的详细信息。
总结
SAP 云平台的超级账本服务,成功地帮助了希望使⽤这项区块链技术的企业避免了硬件基础设施的投⼊,同时屏蔽了⼤部分超级账本平台管理的底层细节。通过 SAP 云平台提供的控制台,即可实现对超级账本进⾏设备接⼊,访问控制,服务监控等管理功能。同时,通过 Go 语⾔编写的智能合约⼀旦部署到 SAP 云平台,⽣成的 Restful API 能够被其他编程语⾔⽅便地消费。调⽤这些 API 写⼊超级账本区块链中的数据将⽆法再被篡改。使⽤ SAP 云平台的超级账本服务,应⽤开发⼈员可以⽆需将过多精⼒花费在超级账本体系架构本⾝,从⽽能够专注于应⽤逻辑的编写上去。