知识记录
交易流程
详细的交易过程
(1)提案/背书
在提案/背书阶段,客户端应用会发送一个交易提案到一组Peer节点,Peer节点会调用智能合约发起一个更新账本的申请,然后对结果进行背书。此时,背书Peer节点不会将更新提案应用到自己的账本副本中,而是会将背书的结果返回至客户端应用。背书结果中包含背书节点的签名和对应的带有版本号的交易数据读/写集。
客户端应用如果收集了策略中规定的足够数量的背书,则将交易发送至排序服务
(2)排序/打包
在交易的第2阶段,排序服务会通过共识协议对交易进行排序。在Fabric网络中,共识协议是可插拔的,即可以从多个配置好的共识协议中选择使用其中的一个,并且可以动态增加共识协议。
排序服务从不同的客户端接收交易,并按通道对它们进行排序。排序服务不需要查看交易的内容,也不会执行交易的操作。排序服务可以为每个通道的交易创建区块,将交易打包到区块,并使用自己的数字证书为区块签名,然后利用Gossip 协议将签名后的区块向所有 Peer 节点广播。
(3)验证/记账
根据应用程序在提交交易到账本之前指定的背书策略对交易进行验证。应用程序指定的背书策略中包括需要哪个Peer节点或需要多少个Peer节点对给定智能合约的正确执行提供担保。每个交易都需要经过背书策略中指定数量的Peer节点进行背书。如果要求多个Peer节点对交易进行背书,则并发执行背书可以提高系统的性能。
所有的 Peer节点都会从排序服务接收到经过排序的区块。Peer节点会验证排序服务对区块的签名,然后对读集合中的数据进行验证,以判断交易是否有效。每个有效的区块都会被写入区块链账本中。区块中每个交易中的写集合都会被更新到状态数据库中。
完整的交易过程
(1)客户端初始化交易
在Fabric网络中交易由客户端应用发起,发起交易的方式是向背书节点发送交易提案。提案是向通道上指定的Peer 节点提出的背书请求。提案可以是初始化(init)请求,也可以是读/写请求。
可以使用Fabric SDK构造交易提案。交易提案的作用是请求调用一个链码,以便读写账本。Fabric SDK是一个将请求绑定到对应程序包的进程。SDK持有客户端的数字证书因此为客户端所接受,可以代表客户端对其发起的交易提案进行签名,然后向选择的背书节点发送请求。
在发送交易提案到背书节点前,客户端SDK需要知道网络中所有背书节点的列表。在图2-8中有5个背书节点,分别是P12、P14、P22、P24和P32。背书节点在配置文件 confgtx.yaml 中定义,confgtx.yaml中保存着前文提到的背书策略。
每个背书节点上都安装了一个链码,还存储着一个账本副本。所有Peer 节点上的账本副本都保持同步。
(2)背书节点验证签名并执行交易
背书是指定 Peer 节点执行链码交易并对客户端应用的交易提案返回一个“提案响应”的处理过程。提案响应中包括执行链码的响应信息、结果(读集合和写集合)、事件,以及作为Peer 节点执行链码证据的数字签名。
链码应用程序应符合背书策略。背书策略可以指定如下配置信息。
背书节点:指通道中必须执行特定交易的Peer节点。这些特定交易都与特定链码应用程序绑定在一起。
交易被接受的前提条件:比如要求交易得到最少数量背书节点的背书、最小百分比背书节点的背书或分配给特定链码应用程序的所有背书节点的背书。
有些背书节点可能已经离线工、其余的背书节点在收到交易提案后,会按照事先定义好的步骤对交易进行验证,具体如下。
交易提案消息是否符合要求。
交易提案之前有没有被记账过。
签名是否有效。
提交交易提案的客户端是否有权限在当前通道上执行交易。
背书节点会以交易提案作为参数调用链码的函数,链码会基于数据库的当前状态执行模拟交易,并得到交易的结果。交易结果包括链码的响应值和交易的读/写集。读/写集中包含模拟交易时从当前状态数据库中读取的数据,以及执行交易时向状态数据库中写入的数据。此步骤中并不实际更新账本,读/写集和背书节点的签名将作为提案响应返回SDK。
(3)检查提案响应
客户端应用在收到所有背书节点的响应后,对背书响应列表进行验证,检查其是否满足背书策略的规则。不同的通道拥有不同的背书策略。
客户端应用会对背书节点的签名进行有效性校验。如果链码只希望查询账本,则客户端应用将检查查询响应,而不会将交易提交至排序服务。在交易发送至排序服务之前,客户端应用会检查提案响应以确保满足指定的背书策略的规则。
(4)客户端将背书信息集成到交易中
背书响应通过验证后,客户端应用会将其发送到合适的排序服务。背书信息最终会出现在区块中。在图2-8所示的示例网络中由组织Org2和Org3提供的两个排序节点组成排序服务。在生产网络中,通常会启动多个排序节点,以防出现故障影响网络的正常运行。
SDK会将交易提案和背书响应都封装到交易信息中,然后将其发送至排序服务。发送至排序服务的交易信息中包含以下信息。
模拟交易时产生的读/写集。
背书节点的签名。
通道 ID。
排序服务并不会对交易信息中的所有信息进行检查,而只会从网络的所有通道中接收所有交易,然后按时间对它们进行排序,为每个通道创建一个区块,用于存储该通道的交易。
对交易的排序在网络范围内进行,不同应用程的交易背书和提交的读写集会同时被排序。
排序服务由一组排序节点组成,它并不对交易和智能合约进行处理,也不维护共享账本,排序服务接收经过背书的交易,并为这些交易指定一个记账节点,由记账节点将这些交易写入账本中。
(5)验证交易
当区块被经过排序的交易填满后,它会被发送至网络中的领导节点。理想状态下,Fabric网络中应该有一个领导节点,但是这并不是强制要求。如果没有领导节点,则排序节点需夏逐一确认此区块已经被传送至所有的记账节点,这样做会增加网络的负载。为了避免这种情况,联盟中的每个组织都会提名自己的领导节点。每个组织可以有多个领导节点,以防止出现故障。有的组织如果只有一个领导节点,而且该领导节点没有对请求做出响应则会在活动的 Peer 节点中启动一个投票机制,选举新的领导节点。
借助通道,所有的排序节点都可以得到通道中的领导节点列表。排序节点会将准备好的区块发送至所有活动的领导节点。
领导节点会将区块发送给同一组织内的其他记账节点。区块会通过Gossip协议而被传送至通道中的所有Peer 节点。区块中的交易会被验证以确认如下事项。
满足背书策略的规则。
从交易执行生成读集合后,读集合中的变量与账本状态相比并没有发生变化
根据验证的结果,区块中的交易会被标记为有效或无效。
(6)更新账本
Peer 节点会根据链码的策略检查背书是否有效,同时要对读/写集进行检查,判断其是否与世界状态数据一致;特别是当背书节点模拟交易时,需要判断已经存在的读数据是否与世界状态数据一致。
当记账节点完成验证交易后,交易将会被写入账本中(也就是将区块追加到区块链中),并使用读/写集中的写数据更新状态数据库。
每个Peer 节点均可与多个通道相关联。因此,在Fabric 网络中可以存在多个区块链。
最后,每个记账节点都会将交易记账的结果异步通知到发起交易的客户端应用。
带有私有数据的交易流
(1)客户端应用提交一个提案请求,调用链码中读取或写入私有数据的函数。只有私有数据集中经过授权的 Peer 节点上的链码才能访问私有数据。
(2)私有数据或在链码中用于生成私有数据的数据包含在提案的transient 字段中transient 字段的作用是防止私有数据被记录在区块中,具体情况将在9.6节结合私有数据编程进行介绍。
(3)背书节点会模拟交易并将私有数据存储在一个临时的数据存储区中,然后基于集合策略(通过 Gossip 协议)将私有数据分发给经过授权的Peer节点。
(4)背书节点会向客户端发送背书响应,其中包含公有数据和所有私有数据的键和值的哈希值。
(5)客户端应用向排序服务提交交易,交易数据中包含提案响应和私有数据的哈希值带有私有数据哈希值的交易和普通交易一样,都会被包含在区块中。这样,通道中所有的Peer 节点都可以对交易数据进行验证,而且不知道真正的私有数据。
(6)在写入区块时,Peer 节点依据集合策略来决定自己是否有权限访问私有数据。如果有权限,则首先检查自己的临时数据存储区,并判断在链码背书时是否已经接收到私有数据。如果没有权限,则从其他经过授权的Peer节点那里拉取私有数据的哈希值,然后将其与区块中私有数据的哈希值进行比较,校验交易的有效性。经过验证和写入阶段,私有数据已被存储在 Peer 节点的私有状态数据库及其私有写集合中。最后,私有数据会从临时数据存储区中被删除。
交易模拟和读/写集
在对交易进行背书时,有一个模拟交易的过程。在此过程中会生成交易的读/写集。读集合中包含一组唯一的关键字和它们的版本(注意不是由键和键的值数据所组成的键值对,而是由键和版本号组成的数据),以记录模拟过程中所读取的数据;写集合中包含一组唯-的关键字及它们的新值,新值就是在交易过程中写入区块链的值。如果交易删除某个关键字,则在写集合里该关键字会被记录一个删除标记。
如果在模拟交易的过程中多次修改一个关键字的值,则写集合里只保留最后一次写入的值。
关键字的版本号只在读集合中记录,写集合中只保存关键字及其最新值,并不包含版本号版本号的最低要求是可用于标识关键字的不重复的标识符,可以通过以下两种方式实现版本号。
使用自增数字作为版本号。
基于区块链的高度生成版本号。
部署Fabric生产网络
步骤
(1)根据实际情况设计生产网络的网络配置,具体包括如下内容。
参与网络的组织及对应需要搭建的CA Server。
需要创建的通道、参与通道的组织及它们的Peer 节点
需要设置的排序节点及管理它们的组织。
需要部署的链码。
(2)准备和搭建基础设施,包括租用云主机、安装Go语言环境和其他所需要的软件
(3)搭建网络发起者所需要的核心网络,其中包括搭建网络发起者的各个主要的Fabric 组件。
(4)邀请其他的参与组织加入网络,并依次安装这些组织的Fabric组件。在生产网络中部署Fabric组件的方法将在7.2节中介绍。
(5)创建和管理通道,并将相关组织的Peer节点加入通道。
(6)上传并部署链码。
(7)安装使用Fabric生产网络的应用程序,调试应用程序与链码的通信,并测试应用程序的主要功能。
设计生产网络的结构和配置
生产网络的结构取决于其根据实际需求而提供的具体服务,每个组件在每个功能点上都有很多配置选项。本小节将结合具体的应用场景给出一些建议。
与开发环境相比,生产网络对安全性、资源管理和高可用性的要求更高一些。在设计生产网络的结构时,需要考虑诸如以下问题。
(1)需要部署多少个节点才能满足高可用性的要求?
(2)在什么样的数据中心部署生产网络可以同时满足数据存储和数据恢复的需求?
(3)如何确保私钥和信任根的安全?
除此之外,在部署组件之前还应该在以下几个方面做好设计。
(1)生产网络的基本结构:例如生产网络中需要创建几个通道,每个通道的参与组织包括哪些,每个组织都有多少个Peer 节点;排序服务由多少个排序节点组成,谁来管理和维护这些排序节点。
(2)CA配置:在生产网络中如何部署CA也是必须考虑的重要因素。在生产网络中应该使用TLS进行加密通信,这样就需要设置一个 TLS CA,用于生成 TLS 证书。关于搭建CA的具体方法将在7.2.2小节中介绍。
(3)选择数据库的类型:有些通道可能会要求所有数据模块化处理,这就需要使用CouchDB作为状态数据库。在6.1.5小节已经介绍了启用 CouchDg 作为状态数据库的方法。而对于更注重操作速度的网络,则可能会决定所有Peer节点都使用LeveIDB。需要注意的是,通道中不能既包含使用LevelDB的Peer 节点,又包含使用CouchDB的Peer 节点。因为当CouchDB强制在键值对上启用一些数据约束时,在levelDB中有效的键和值在CouchDB中不一定有效。
(4)使用通道还是私有数据集:有些情况适合选择通道作为确保数据隐私和交易隔离的最佳方式;而有些情况则适合尽量少地使用通道,此时私有数据集足以满足生产网络对数据隐私保护的要求。
(5)容器的编排方式:在大多数情况下,生产网络采用容器化部署。容器编排是指将容器的部署、管理、弹性伸缩(添加或移除节点)等都进行自动化处理。在大中型网络中容器编排可以带来极大的管理便利。区块链是分布式系统,生产网络中包含各种不同的组件。不同的用户可能会选择使用不同的容器编排方式。有的用户会为Peer进程、排序服务日志服务、CouchDB、链码等创建独立的容器,而有的用户则会选择将有些组件合并在一个容器中。因此,需要根据实际情况做好容器编排。
(6)链码的部署方式:可以使用内置的构建和运行方式,也可以使用自定义的构建和运行方式。自定义的构建和运行方式包括两种,一种是使用外部构建器和加载器,另一种是以外部服务使用链码。关于链码的部署将在第9章中介绍。由于篇幅有限、本书不具体介绍以外部服务使用链码的方法。
(7)使用防火墙:在生产网络中,属于一个组织的组件可能需要访问其他组织的组件。出于安全的考虑有必要使用防火墙,并做好相关的网络配置。例如,利用Fabric SDK访问所有组织背书节点的应用程序,以及利用Fabric SDK访问排序服务接收新区块的Peer节点,这两种访问都需要通过防火墙实现。
以上因素可以在设计生产网络的结构和配置时进行衡量,并做出决策。无论选择哪些组件、如何部署、都需要选择一款实用性高的管理系统,例如Kubemetes,这样才能更高效地管理和操作生产网络,以满足具体的业务需求。
在设计生产网络的结构时,还应该考虑符合所在国家的相关法律、法规及行业标准的要求。例如,在国内的生产网络和系统都应该按照《中华人民共和国网络安全法》定进行信息系统安全等级保护测评,以保证其满足相关级别的安全指标要求。
在生产网络中部署Fabric区块链的各组件
在生产网络中,可以按照如下步骤部署Fabric区块链的各组件。
(1)创建资源集群。
(2)搭建 CA。
(3)使用CA创建身份和MSP。
(4)部署Peer节点。
(5)部署排序节点
创建资源集群
通常而言,Fabric 区块链的部署方式是不确定的,可以根据实际情况随意部署Fabric区块链。例如,可以在笔记本电脑上部署和管理Peer节点,尽管不建议这么做,因为笔记本电脑不适合长时间连续工作,但是,如果暂时没有足够的服务器和台式计算机资源,也可以使用笔记本电脑来部署Peer节点(Fabric组件)。
尽管Fabric区块链并没有明确禁止怎样使用资源去部署组件,但是只要有可能,建议使用容器部署各种Fabric组件,并使它们互相连接。容器可以部署在本地或局域网,也可以部署在云端。容器化部署可以实现在一个物理服务器上彼此隔离地部署多个组件,从而充分发挥资源的作用。
可以根据实际需求选择使用Kubemetes或Docker Swarm实现容器化部署。无论怎样选择,都需要首先评估其是否拥有让组件高效运行的物理资源。可以根据实际的业务需求来设计Fabric 区块链的规模,并决定每类组件部署的实际数量,然后评估需要的物理服务器的配置和数量。可以参考以下原则设置物理资源。
如果计划将一个Peer 节点加入多个高容量的通道中,则该Peer 节点的物理服务器应该具有更多的 CPU 和内存资源。
如果只计划将一个Peer节点加入一个通道中,则该Peer 节点的配置可以稍微低一些。
通常,如果只部署一个排序节点,则它分配的物理资源应该是一个Peer 节点的3倍。
建议排序服务至少有3个排序节点,最好有5个排序节点。
一个 CA Server 大概会占用 10 倍于 Peer 节点的物理资源。
还应该考虑给集群增加存储设备,因为在搭建集群时很难预估长期运行所需要的存储设备。增加持久化存储设备的目的是使MSP、账本和已安装链码的数据不存储在容器的文件系统中,这样可以避免在容器关闭时造成数据丢失。
最开始搭建好Fabric生产网络时,建议进行压力测试,以验证生产网络的资源配置是否满足实际需求,并根据测试结果调整资源配置。很多云服务提供商都提供商业化的压力测试工具,例如阿里云的 PTS( Performance Testing Service,性能测试服务 )和腾讯的 WeTest平台,也可以选择使用LoadRunner或JMeter 等压力测试工具。
搭建 CA
在Fabric生产网络中,第一个部署的组件应该是CA。因为与节点相关的证书(包括节点管理员的证书)都是由CA生成的,所以这些证书应该在部署节点之前就准备好。尽管并不是必须使用Fabric CA(也可以选择使用其他第三方CA)生成这些证书,但是Fabric CA可以创建组件和组织需要的MSP目录结构。如果选择使用FabricCA来生成证书,则Fabric CA 还需要为自己创建 MSP 文件夹。
根据 CA的作用可以将其分为下面两类。
(1)一类CA用于生成管理员所属组织的证书。此类CA也称为登录 CA。登录CA可以只有一个 CA Server,也可以是由一个根 CA 和若干个中间 CA 组成的 CA Server 集群。此种类型的CA也可以为组织创建MSP,以及为其他用户生成证书。
(2)另一类CA用于生成TLS安全通信所需要的证书,因此,此类CA也称为TLS CA。
TLS证书可以防止在通信过程中出现中间人攻击。
在生产网络中,建议为每个组织至少部署一个CA,而其他的CA用于TLS通信:假定需要为一个组织A部署3个相关联的Peer节点,并且需要为另一个负责排序服务的组织B部署一个相关联的排序节点,则至少需要4个CA,其中2个CA为组织A服务,作用如下。
一个CA用于生成管理员和用户证书,并生成代表相关组织的MSP目录结构。
另一个 CA 负责 TLS 通信。
另外2个CA为组织B服务,它们的作用与上面所述作用类似。
使用CA创建身份和MSP
搭建CA后,可以利用它们为与组织相关的身份和组件生成证书。而组织由MSP所代表。每个组织都至少应该完成如下工作。
1.注册并登录一个管理员身份,并创建一个 MSP
当与组织相关联的CA搭建好后,首先注册一个用户,然后登录一个身份。具体操作如下。
(1)由CA 的管理员指定登录身份的用户名和密码,还要设置身份的属性和附属信息(例如,指定身份的角色是admin,并根据需要设置组织管理员的必要信息)。CA会为一个身份生成下面2个证书。
公钥证书:网络中所有成员都可以拥有的证书,其中包含对应身份的公钥。
私钥证书:保存在keystore 文件夹下,用于对该身份所采取的动作进行签名。
(2)注册身份后,可以使用用户名和密码进行登录。
(3)CA还会创建一个名为msp的文件夹,其中包含发行身份证书的CA的公钥证书以及信任根 CA的公钥证书。
组织的管理员通常也是节点的管理员。必须在创建节点的本地MSP之前创建组织的管理员身份,因为在创建本地MSP时需要用到节点管理员的证书。
2.注册并登录节点身份
节点身份必须使用登录CA和TLS CA进行注册和登录。当使用登录CA来注册节点时,指定的角色不是admin或user,而是peer或orderer。节点的 MSP 结构也叫作本地 MSP,因为指定身份所赋予的权限只与本地节点相关。本地MSP在创建节点身份时生成,在启节点时会被用到。
部署Peer节点
准备好所有需要的证书和MSP后,就可以创建Peer节点了。
Peer节点是生产网络的基础元素,因为Peer节点用于存储账本和智能合约,并且用于封装生产网络中的共享进程和共享信息。在生产网络下部署Peer节点之前需要考虑如下因素。
1.生成Peer节点的身份和MSP
可以参照7.2.3小节的内容完成本操作。需要注意的是,cryptogen 工具只能用于测试网络,而不能在生产网络中使用。也可以不使用Fabric CA,而选择使用其他第三方CA来生成 Peer节点的身份。但是这样就需要手动创建Peer节点所需要部署的MSP目录结构,当然,可以参照测试网络中Peer节点的MSP目录结构进行创建,位置为test-network/organizations/peerOrganizations,其中包含orgl.example.com 、org2.example.co和 org3.example.com等子目录,每个子目录存储一个组织的资源文件。org1.example.com的目录结构如图 7-1所示。
2.启用 TLS
出于安全通信的考虑,在生产网络中应该启用TLS。因此,除了使用组织的登录CA注册Peer身份外,还需要组织的TLS CA注册Peer身份。生成的TLS证书会在与生产网络通信时用到。
3.状态数据库
每个Peer节点都维护一个状态数据库,状态数据库中存储着账本上所有键的最新值。Fabric 区块链支持内置的LeveIDB和外置的 CouchDB两种类型的状态数据库。如果需要支持富查询,则建议选择CouchDB;如果只进行按键查询,且对查询速度有较高要求,则建议使用默认的LeveDB。LeveDB内嵌在 Peer 进程中,因此非常便于管理。
一个通道中的所有Peer节点都必须使用相同的状态数据库,因此,Peer节点状态数据库的选择实际上取决于它希望加入的通道。
4.调整 Peer 节点的资源配置
通常,Peer 节点会有几个与之相关联的容器,具体如下。
Peer 容器:封装 Peer 进程,为其所在的通道验证并写入交易。Peer 容器的存储包含其所在通道的历史交易。如果状态数据库选择LeveIDB,则其数据也会存储在Peer容器本地。如果 Peer 节点上安装了链码,则 Peer 容器的存储还应考虑链码的大小。综上所述,Peer 容器的存储空间大小取决于其所属通道的数量、每个通道中交易的数量及Peer节点上安装的链码大小。
CouchDB 容器(可选):如果选择CouchDB作为状态数据库,则每个通道都会启动一个 CouchDB 容器。
链码加载容器(可选):用于为每个链码加载一个独立的容器。链码加载容器可以在Peer容器中启动一个Docker 容器。需要注意的是,链码加载容器并不是智能合约真正运行的容器,它只是为智能合约提供了比和Peer一起部署的容器更小一些的资源。只有在运行智能合约且需要创建容器时,链码加载容器才会存在。
链码容器:链码运行的容器。前面提到的链码加载容器会将每个链码部署到独立的
容器中,即使一个通道中有多个Peer节点,它们都部署了相同的链码,这些链码在运行时也会被分别部署到彼此独立的容器中。
在生产网络中还需要考虑网络的高可用性,即使个别Peer节点掉线也不影响网络的正常运行。要达到这个效果,就要设置一些冗余的Peer节点,并且定期检测Peer 节点的性能以便出现异常时及早发现并处理。
部署排序节点
在Fabric生产网络中部署排序节点的过程如下。
1.规划排序服务
首先根据网络规模和交易数量来确定构成排序服务的排序节点数量。正如本章前面建议的,排序服务至少有3个排序节点,最好有5个排序节点;这些排序节点可以由一个组织维护,也可以由多个组织共同管理。
2.配置每个排序节点的参数
准备好在生产网络下搭建排序服务后,需要编辑排序节点Docker镜像中的配置文件orderer.yaml 中的参数。orderer.yaml位于 Docker 镜像中的/etc/hyperledger/fabric/目录下。可以参照5.3.3小节理解 orderer.yaml 中配置参数的作用。
3.部署排序节点
可以参照如下步骤部署排序节点。
(1)准备好排序服务需要的二进制文件和配置文件,具体如下。
建议将二进制文件存放在 fabric/bin 目录下。从下载的 Fabric 源代码中的 fabric/cmd目录下复制二进制文件到 fabric/bin 目录下。
建议将配置文件存放在fabric/config目录下。从下载的Fabric 源代码中的fabric/scripts/config 日录下复制配置文件到 fabric/config 目录下。
将fabric/bin添加到环境变量ATH
(2)使用Fabric CA或第三方CA为排序节点生成证书,具体如下。
排序组织的 MSP。
排序节点的TLS CA证书:
排序节点的本地 MSP。
(3)创建系统通道的创世区块。
(4)配置orderer.yaml。
(5)启动排序节点。
实验记录
CentOS7.9 GLIBC_2.28 not found
安装C compliler
yum install gcc -y
升级GCC编译器
1 2 3 4 yum -y install centos-release-scl yum -y install devtoolset-8-gcc devtoolset-8-gcc-c++ devtoolset-8-binutils scl enable devtoolset-8 bash echo "source /opt/rh/devtoolset-8/enable" >>/etc/profile
升级make
1 2 3 4 5 6 7 8 9 wget http://ftp.gnu.org/gnu/make/make-4.2.tar.gz tar -xzvf make-4.2.tar.gz cd make-4.2 sudo ./configure sudo make sudo make install sudo rm -rf /usr/bin/make sudo cp ./make /usr/bin/ make -v
升级glic-2.28
1 2 3 4 5 6 7 8 9 10 11 wget https://mirror.bjtu.edu.cn/gnu/libc/glibc-2.28.tar.xz tar -xf glibc-2.28.tar.xz -C /usr/local cd /usr/local/glibc-2.28/ mkdir build cd build/ yum install -y bison sudo ../configure --prefix=/usr --disable-profile --enable-add-ons --with-headers=/usr/include --with-binutils=/usr/bin make make install strings /lib64/libc.so.6 | grep GLIBC make localedata/install-locales
来源:https://www.cnblogs.com/FengZeng666/p/15989106.html
mysql无法开启
systemctl status mysqld
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 [root@local mysql]# systemctl status mysqld ● mysqld.service - MySQL Server Loaded: loaded (/usr/lib/systemd/system/mysqld.service; enabled; vendor preset: disabled) Active: failed (Result: exit-code) since Fri 2024-06-21 09:16:31 EDT; 1min 50s ago Docs: man:mysqld(8) http://dev.mysql.com/doc/refman/en/using-systemd.html Process: 9181 ExecStart=/usr/sbin/mysqld $MYSQLD_OPTS (code=exited, status=1/FAILURE) Process: 9152 ExecStartPre=/usr/bin/mysqld_pre_systemd (code=exited, status=0/SUCCESS) Main PID: 9181 (code=exited, status=1/FAILURE) Status: "Server shutdown complete (with return value = 1)" Jun 21 09:16:29 systemd[1]: Starting MySQL Server... Jun 21 09:16:31 systemd[1]: mysqld.service: main process exited, code=exited, status=1/FAILURE Jun 21 09:16:31 systemd[1]: Failed to start MySQL Server. Jun 21 09:16:31 systemd[1]: Unit mysqld.service entered failed state. Jun 21 09:16:31 systemd[1]: mysqld.service failed.
cat /var/log/mysqld.log
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 2024-06-21T12:50:11.343450Z 0 [System] [MY-015015] [Server] MySQL Server - start. 2024-06-21T12:50:12.618088Z 0 [System] [MY-010116] [Server] /usr/sbin/mysqld (mysqld 8.4.0) starting as process 3109 2024-06-21T12:50:13.618033Z 1 [System] [MY-013576] [InnoDB] InnoDB initialization has started. 2024-06-21T12:50:15.650779Z 1 [ERROR] [MY-012592] [InnoDB] Operating system error number 2 in a file operation. 2024-06-21T12:50:15.650820Z 1 [ERROR] [MY-012593] [InnoDB] The error means the system cannot find the path specified. 2024-06-21T12:50:15.650855Z 1 [ERROR] [MY-012216] [InnoDB] Cannot open datafile for read-only: 'mysql.ibd' OS error: 71 mysqld: Can't open file: 'mysql.ibd' (errno: 0 - ) 2024-06-21T12:50:16.146304Z 1 [ERROR] [MY-010334] [Server] Failed to initialize DD Storage Engine 2024-06-21T12:50:16.146567Z 0 [ERROR] [MY-010020] [Server] Data Dictionary initialization failed. 2024-06-21T12:50:16.146647Z 0 [ERROR] [MY-010119] [Server] Aborting 2024-06-21T12:50:16.148910Z 0 [System] [MY-010910] [Server] /usr/sbin/mysqld: Shutdown complete (mysqld 8.4.0) MySQL Community Server - GPL. 2024-06-21T12:50:16.148947Z 0 [System] [MY-015016] [Server] MySQL Server - end. 2024-06-21T12:54:26.723826Z 0 [System] [MY-015015] [Server] MySQL Server - start. 2024-06-21T12:54:26.943934Z 0 [System] [MY-010116] [Server] /usr/sbin/mysqld (mysqld 8.4.0) starting as process 8150 2024-06-21T12:54:26.951838Z 1 [System] [MY-013576] [InnoDB] InnoDB initialization has started. 2024-06-21T12:54:28.417079Z 1 [ERROR] [MY-012592] [InnoDB] Operating system error number 2 in a file operation. 2024-06-21T12:54:28.417122Z 1 [ERROR] [MY-012593] [InnoDB] The error means the system cannot find the path specified. 2024-06-21T12:54:28.417154Z 1 [ERROR] [MY-012216] [InnoDB] Cannot open datafile for read-only: 'mysql.ibd' OS error: 71 mysqld: Can't open file: 'mysql.ibd' (errno: 0 - ) 2024-06-21T12:54:28.484964Z 1 [ERROR] [MY-010334] [Server] Failed to initialize DD Storage Engine 2024-06-21T12:54:28.485235Z 0 [ERROR] [MY-010020] [Server] Data Dictionary initialization failed. 2024-06-21T12:54:28.485273Z 0 [ERROR] [MY-010119] [Server] Aborting 2024-06-21T12:54:28.487463Z 0 [System] [MY-010910] [Server] /usr/sbin/mysqld: Shutdown complete (mysqld 8.4.0) MySQL Community Server - GPL. 2024-06-21T12:54:28.487499Z 0 [System] [MY-015016] [Server] MySQL Server - end.
解决方案
1 2 3 systemctl stop mysqld rm -rf /var/lib/mysql/* systemctl start mysqld
x509:ECDSA verification failure报错
报错信息
1 Failed validating bootstrap block: initializing channelconfig failed: could not create channel Orderer sub-group config: setting up the MSP manager failed: the supplied identity is not valid: x509: certificate signed by unknown authority (possibly because of "x509: ECDSA verification failure" while trying to verify candidate authority certificate
原因
将服务都停了后,又重复执行了证书生成脚本和创世区块生成命令导致。
1 2 3 4 5 cd /data/blockchain/hyperledger/fabric_cluster cryptogen generate --config=./config/crypto-config.yaml cd /data/blockchain/hyperledger/fabric_cluster configtxgen -profile SampleMultiNodeEtcdRaft -channelID mychannel -configPath ./config -outputBlock ./channel-artifacts/genesis.block
生产环境请不要多次执行上面两命令。
测试环境解决办法: 删除证书和创世区块文件,重新生成,再启动。
来源:https://www.cnblogs.com/zoujiaojiao/p/13361475.html
failed - 0 sub-policies were satisfied, but this policy requires 1 of the ‘Writers’ sub-policies to be satisfied: permission denied
原因
生成通道创世区块的channelID
要与生成创建通道使用的配置交易文件的channelID
要不一样,猜测是测试网络生成通道后,生产网络网络中不能生成相同的通道,需要修改通道名字。
报错信息
1 2 Error: got unexpected status: FORBIDDEN -- config update for existing channel did not pass initial checks: implicit policy evaluation failed - 0 sub-policies were satisfied, but this policy requires 1 of the 'Writers' sub-policies to be satisfied: permission denied
解决方案1
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 测试网络命令 #生成系统通道syschannel的创世区块: cd /data/blockchain/hyperledger/fabric_cluster configtxgen -profile SampleMultiNodeEtcdRaft -channelID syschannel -configPath ./config -outputBlock ./channel-artifacts/genesis.block #生成创建应用通道使用的配置交易文件 configtxgen -profile TwoOrgsChannel -configPath ./config -outputCreateChannelTx ./channel-artifacts/channel.tx -channelID mychannel 生产网络命令 #进入容器cli-peer0-org1的内部。 docker exec -it cli-peer0-org1 bash # 在容器中创建通道mychannel。(其实此命令可不用) peer channel create -o orderer0.consortiums.com:7050 -c mychannel -f /hyperledger/opt/peer/channel-artifacts/channel.tx --tls --cafile /hyperledger/opt/peer/crypto-config/ordererOrganizations/consortiums.com/orderers/orderer0.consortiums.com/msp/tlscacerts/tlsca.consortiums.com-cert.pem #将当前Peer节点加入通道中。 peer channel join -b /hyperledger/opt/peer/channel-artifacts/genesis.block #更新锚节点 #进入容器cli-peer0-org1的内部。 docker exec -it cli-peer0-org1 bash #更新组织org1的锚节点,命令如下。 peer channel update -o orderer0.consortiums.com:7050 -c mychannel -f /hyperledger/opt/peer/channel-artifacts/Org1MSPanchors.tx --tls --cafile /hyperledger/opt/peer/crypto-config/ordererOrganizations/consortiums.com/orderers/orderer0.consortiums.com/msp/tlscacerts/tlsca.consortiums.com-cert.pem
解决方案2
创世区块通道名字不改,进入cli-peer0-org1
容器之后,不需要创建通道mychannel
,直接将Peer节点加入通道和更新组织的锚节点。
章节资料
03
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 ip addr cd /etc/sysconfig/network-scripts vi ifcfg-enp0s3 #重新启动网络 service network restart #ping通百度 ping www.baidu.com #ifcfg-enp0s8的内容如下: TYPE=Ethernet PROXY_METHOD=none BROWSER_ONLY=no BOOTPROTO=static IPADDR=192.168.56.101 NETMASK=255.255.255.0 DNS1=202.106.0.20 DNS2=8.8.8.8 GATEWAY=192.168.56.1 DEFROUTE=yes IPV4_FAILURE_FATAL=no IPV6INIT=yes IPV6_AUTOCONF=yes IPV6_DEFROUTE=yes IPV6_FAILURE_FATAL=no IPV6_ADDR_GEN_MODE=stable-privacy NAME=enp0s8 UUID=b86ee2d0-57a8-4e49-8eaf-803edd59d4df DEVICE=enp0s8 ONBOOT=yes #2.在CentOS中安装Docker #(1)升级yum包: sudo yum update #(2)卸载旧版本 sudo yum remove docker docker-common docker-selinux docker-engine #(3)安装需要的软件包 sudo yum install -y yum-utils device-mapper-persistent-data lvm2 #(4)选择安装Docker的版本,执行如下命令设置yum源。 sudo yum-config-manager --add-repo http://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo #查看所有仓库中所有docker版本。 yum list docker-ce --showduplicates | sort -r #查看Docker的版本。 docker --version #3.Docker服务管理 #启动Docker服务。 systemctl start docker #查看Docker服务的状态。 systemctl status docker #设置自动启动Docker服务。 systemctl enable docker #4.配置Docker镜像加速器 sudo mkdir -p /etc/docker vi /etc/docker/daemon.json #应用配置,重启Docker服务。 sudo systemctl daemon-reload sudo systemctl restart docker 5.使用Docker容器 #使用docker run命令可以运行Docker镜像 docker run hello-world #查看本机Docker镜像 docker images #拉取ubuntu docker pull ubuntu #运行镜像 docker run -it ubuntu /bin/bash #查看Docker容器信息 docker ps -a #启动Docker容器 docker start Docker容器ID #停止Docker容器 docker stop Docker容器ID #删除Docker容器 Docker rm <Docker容器ID> #删除Docker镜像 Docker rmi <Docker镜像ID> #2.在CentOS中安装Docker #安装wget yum install -y wget #(1)下载Go 1.15.3的安装包: cd /usr/local/ wget https://studygolang.com/dl/golang/go1.15.3.linux-amd64.tar.gz #(2)解压缩GO语言源码到$HOME目录: tar -C $HOME -xzf go1.15.3.linux-amd64.tar.gz #(3)创建保存Go语言程序的目录$HOME/gocode: mkdir $HOME/gocode #(4)执行下面的命令,设置GO语言的环境变量。 vi ~/.bashrc #然后在文件中添加如下代码: export GOPATH=$HOME/gocode export GOROOT=$HOME/go export PATH=$PATH:$GOROOT/bin export PATH=$PATH:$GOPATH/bin #编译.bashrc文件 source ~/.bashrc #查看GO语言的版本 go version #卸载较低版本的Git yum remove -y git #安装git的命令如下: yum -y install git #查看git的版本信息。 git version #安装curl: yum install -y curl #从GitHub下载与CentOS版本相匹配的Docker Compose sudo curl -L https://get.daocloud.io/docker/compose/releases/download/1.29.2/docker-compose-`uname -s`-`uname -m` > /usr/local/bin/docker-compose #为安装脚本添加执行权限。 sudo chmod +x /usr/local/bin/docker-compose #查看Docker Compose的版本信息。 docker-compose -v #创建一个保存Hyperledger源代码的目录 mkdir $GOPATH/src mkdir $GOPATH/src/github.com mkdir $GOPATH/src/github.com/hyperledger #1.下载Fabric源代码 cd $GOPATH/src/github.com/hyperledger git clone https://gitee.com/mirrors/fabric.git #下载Fabric区块链的示例代码 cd $GOPATH/src/github.com/hyperledger/fabric/scripts/ git checkout release-2.3 git clone https://gitee.com/hyperledger/fabric-samples.git #3.安装Fabric区块链 cd $GOPATH/src/github.com/hyperledger/fabric/scripts/ sh bootstrap.sh #在执行 bootstrap.sh脚本的时候,通过参数-b控制跳过调用download()函数下载 这两个文件 cd $GOPATH/src/github.com/hyperledger/fabric/scripts/ ./bootstrap.sh -b #编辑/etc/profile,在文档最后,添加如下代码: export PATH="/$GOPATH/src/github.com/hyperledger/fabric/scripts/fabric-samples/bin:$PATH" #使环境变量生效。 source /etc/profile #执行如下命令: configtxgen --help #启动测试网络。 cd $GOPATH/src/github.com/hyperledger/fabric/scripts/fabric-samples/test-network ./network.sh up #关闭测试网络。 cd $GOPATH/src/github.com/hyperledger/fabric/scripts/fabric-samples/test-network ./network.sh down #在启动测试网络的同时启用内置的CA服务 ./network.sh up -ca #检查Org1管理员用户的MSP文件夹 tree organizations/peerOrganizations/org1.example.com/users/Admin@org1.example.com/ cd $GOPATH/src/github.com/hyperledger/fabric/scripts/fabric-samples/test-network ./network.sh createChannel
1 2 3 4 #daemon.json { "registry-mirrors": ["https://docker.mirrors.ustc.edu.cn/"] }
04
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 #安装libtool、libtdhl-dev程序包和gcc编译器。 yum install libtool-ltdl-devel yum -y install gcc-c++ #编辑~/.bashrc,在最后添加如下代码: export PATH=$PATH:/root/go/bin/fabric-ca/bin/ #然后执行下面的命令编译.bashrc文件。 source ~/.bashrc #初始化Fabric CA Server。 fabric-ca-server init -b admin:adminpw #启动Fabric CA Server。 fabric-ca-server start -b admin:adminpw #【例4-1】设置环境变量FABRIC_CA_SERVER_PORT为7055。 export FABRIC_CA_SERVER_PORT=7055 #启动Fabric CA服务器端。 fabric-ca-server start -b admin:adminpw #【例4-2】 fabric-ca-server start -b admin:adminpw -p 7056 #安装MySQL数据库: yum install mysql-community-server -y #从日志中查看MySQL数据库的临时密码。 grep "temporary password" /var/log/mysqld.log #对MySQL数据库进行安全设置。 mysql_secure_installation #登录到MySQL数据库。 mysql -u root -h localhost -p #开通任何IP地址都可以远程连接到MySQL数据库。 use mysql; update user set host='%' where user='root' and host='localhost'; flush privileges; #关闭防火墙。 systemctl stop firewalld #查看MySQL数据库的端口工作情况。 netstat -an|grep 3306 #取消MySQL数据库的strict模式 SET GLOBAL sql_mode = 'NO_ENGINE_SUBSTITUTION' #重新初始化Fabric CA Server。 fabric-ca-server init -b admin:adminpw #例4-4 mkdir /root/go/bin/fabric-ca/clients mkdir /root/go/bin/fabric-ca/clients/admin export FABRIC_CA_CLIENT_HOME=/root/go/bin/fabric-ca/clients/admin #在Navicat中连接MySQL数据库,执行如下命令: SET GLOBAL sql_mode = 'NO_ENGINE_SUBSTITUTION' #打开一个新的终端窗口,执行如下命令启动Fabric CA Server。 fabric-ca-server start -b admin:adminpw #在原有终端窗口中执行如下命令在Fabric CA客户端登录一个已有的身份admin。 fabric-ca-client enroll -u http://admin:adminpw@localhost:7054 #例4-5 fabric-ca-client register --id.name peer1-org1 --id.type peer --id.secret userpwd -u http://localhost:7054 #在Fabric CA客户端使用新用户peer1-org1登录。 export FABRIC_CA_CLIENT_HOME=$HOME/fabric-ca/clients/peer1-org1 fabric-ca-client enroll -u http://peer1-org1:userpwd@localhost:7054 #以orderer用户的身份登录到CA服务器ca-orderer,指定用户的MSP目录为${PWD}/organizations/ordererOrganizations/example.com/orderers/orderer.example.com/ msp。 fabric-ca-client enroll -u https://orderer:ordererpw@localhost:9054 --caname ca-orderer -M "${PWD}/organizations/ordererOrganizations/example.com/orderers/ orderer.example.com/msp" #启动测试网络. cd /$GOPATH/src/github.com/hyperledger/fabric/scripts/fabric-samples/test-network ./network.sh up -ca #查看排序服务的MSP目录结构。 cd /$GOPATH/src/github.com/hyperledger/fabric/scripts/fabric-samples/test-network/organizations/ordererOrganizations/example.com/msp tree #将cryptogen等工具文件复制到/root/orgs/文件夹下。 cd /root/orgs cp -r $GOPATH/src/github.com/hyperledger/fabric/scripts/fabric-samples/bin/ ./ #生成默认的crypto-config.yaml文件。 cryptogen showtemplate >> crypto-config.yaml #生成证书。 cd /root/orgs ./bin/cryptogen generate --config=./crypto-config.yaml
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 #crypto-config.yaml OrdererOrgs: - Name: Orderer Domain: example.com Specs: - Hostname: orderer PeerOrgs: - Name: Org1 Domain: org1.example.com EnableNodeOUs: false Template: Count: 2 Users: Count: 3 - Name: Org2 Domain: org2.example.com EnableNodeOUs: false Template: Count: 2 Users: Count: 2
05
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 #查看系统通道的创世区块 ll /opt/app/go/fabric/scripts/fabric-samples/test-network/system-genesis-block #查看configtxgen工具的使用方法 cd $GOPATH/src/github.com/hyperledger/fabric/scripts/fabric-samples/bin/ ./configtxgen --help #【例5-2】 演示在测试网络中添加组织Org3 #启动测试网络并创建通道channel1。 cd $GOPATH/src/github.com/hyperledger/fabric/scripts/fabric-samples/test-network ./network.sh up ./network.sh createChannel -c channel1 #向通道channel1中添加组织Org3 cd addOrg3 ./addOrg3.sh up -c channel1
06
1 2 3 4 5 6 7 8 #启动测试网络后 network.sh up -s couchdb #查看5984端口的状态。 netstat -ntlp |grep 5984 #访问如下URL可以打开CouchDB的管理页面 http://127.0.0.1:5984/_utils
07
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 #禁用防火墙 systemctl stop firewalld systemctl disable firewalld #将cryptogen所在的路径添加到环境变量PATH中。 export PATH=$GOPATH/src/github.com/hyperledger/fabric/scripts/fabric-samples/bin:$PATH #生成证书和密钥文件。 cd /root/fabric_cluster cryptogen generate --config=./config/crypto-config.yaml #生成通道mychannel的创世区块: cd /root/fabric_cluster configtxgen -profile SampleMultiNodeEtcdRaft -channelID mychannel -configPath ./config -outputBlock /root/fabric_cluster/channel-artifacts/genesis.block #查看创建的创世区块。 ls /root/fabric_cluster/channel-artifacts #4.生成创建通道使用的配置交易文件 configtxgen -profile TwoOrgsChannel -configPath ./config -outputCreateChannelTx /root/fabric_cluster/channel-artifacts/channel.tx -channelID mychannel #为组织Org1配置锚节点: configtxgen -profile TwoOrgsChannel -configPath ./config -outputAnchorPeersUpdate /root/fabric_cluster/channel-artifacts/Org1MSPanchors.tx -channelID mychannel -asOrg Org1MSP #为组织Org2配置锚节点: configtxgen -profile TwoOrgsChannel -configPath ./config -outputAnchorPeersUpdate /root/fabric_cluster/channel-artifacts/Org2MSPanchors.tx -channelID mychannel -asOrg Org2MSP #使用配置文件docker-compose-up.yaml启动Docker容器。 docker-compose -f /root/fabric_cluster/docker-compose/docker-compose-up.yaml up -d #进入容器cli-peer0-org1的内部。 docker exec -it cli-peer0-org1 bash #在容器中创建通道mychannel。 peer channel create -o orderer0.consortiums.com:7050 -c mychannel -f /hyperledger/opt/peer/channel-artifacts/channel.tx --tls --cafile /hyperledger/opt/peer/crypto-config/ordererOrganizations/consortiums.com/orderers/orderer0.consortiums.com/msp/tlscacerts/tlsca.consortiums.com-cert.pem #将当前Peer节点加入通道中。 peer channel join -b /hyperledger/opt/peer/channel-artifacts/genesis.block #3.更新锚节点 #(1)进入容器cli-peer0-org1的内部。 docker exec -it cli-peer0-org1 bash #(2)更新组织org1的锚节点,命令如下。 peer channel update -o orderer0.consortiums.com:7050 -c mychannel -f /hyperledger/opt/peer/channel-artifacts/Org1MSPanchors.tx --tls --cafile /hyperledger/opt/peer/crypto-config/ordererOrganizations/consortiums.com/orderers/orderer0.consortiums.com/msp/tlscacerts/tlsca.consortiums.com-cert.pem #(1)进入容器cli-peer0-org2的内部。 docker exec -it cli-peer0-org2 bash #(2)更新组织org2的锚节点,命令如下。 peer channel update -o orderer0.consortiums.com:7050 -c mychannel -f /hyperledger/opt/peer/channel-artifacts/Org2MSPanchors.tx --tls --cafile /hyperledger/opt/peer/crypto-config/ordererOrganizations/consortiums.com/orderers/orderer0.consortiums.com/msp/tlscacerts/tlsca.consortiums.com-cert.pem
1 2 3 4 5 6 7 8 9 10 11 #hosts 127.0.0.1 orderer0.consortiums.com 127.0.0.1 orderer1.consortiums.com 127.0.0.1 orderer2.consortiums.com 127.0.0.1 orderer3.consortiums.com 127.0.0.1 orderer4.consortiums.com 127.0.0.1 peer0.org1.com 127.0.0.1 peer1.org1.com 127.0.0.1 peer0.org2.com 127.0.0.1 peer1.org2.com
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 #crypto-config.yaml OrdererOrgs: - Name: Orderer Domain: consortiums.com Specs: - Hostname: orderer0 - Hostname: orderer1 - Hostname: orderer2 - Hostname: orderer3 - Hostname: orderer4 PeerOrgs: - Name: Org1 Domain: org1.com EnableNodeOUs: true Template: Count: 2 #生成证书的数量 Users: Count: 1 #生成用户证书个数 - Name: Org2 Domain: org2.com EnableNodeOUs: true Template: Count: 2 Users: Count: 1
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 #configtx.yaml --- Organizations: - &OrdererOrg Name: OrdererOrg ID: OrdererMSP MSPDir: /root/fabric_cluster/crypto-config/ordererOrganizations/consortiums.com/msp Policies: Readers: Type: Signature Rule: "OR('OrdererMSP.member')" Writers: Type: Signature Rule: "OR('OrdererMSP.member')" Admins: Type: Signature Rule: "OR('OrdererMSP.admin')" - &Org1 Name: Org1MSP ID: Org1MSP MSPDir: /root/fabric_cluster/crypto-config/peerOrganizations/org1.com/msp Policies: Readers: Type: Signature Rule: "OR('Org1MSP.admin', 'Org1MSP.peer', 'Org1MSP.client')" Writers: Type: Signature Rule: "OR('Org1MSP.admin', 'Org1MSP.client')" Admins: Type: Signature Rule: "OR('Org1MSP.admin')" Endorsement: Type: Signature Rule: "OR('Org1MSP.peer')" AnchorPeers: - Host: peer0.org1.com Port: 7051 - &Org2 Name: Org2MSP ID: Org2MSP MSPDir: /root/fabric_cluster/crypto-config/peerOrganizations/org2.com/msp Policies: Readers: Type: Signature Rule: "OR('Org2MSP.admin', 'Org2MSP.peer', 'Org2MSP.client')" Writers: Type: Signature Rule: "OR('Org2MSP.admin', 'Org2MSP.client')" Admins: Type: Signature Rule: "OR('Org2MSP.admin')" Endorsement: Type: Signature Rule: "OR('Org2MSP.peer')" AnchorPeers: - Host: peer0.org2.com Port: 7051 Capabilities: Channel: &ChannelCapabilities V2_0: true Orderer: &OrdererCapabilities V2_0: true Application: &ApplicationCapabilities V2_0: true Application: &ApplicationDefaults Organizations: Policies: Readers: Type: ImplicitMeta Rule: "ANY Readers" Writers: Type: ImplicitMeta Rule: "ANY Writers" Admins: Type: ImplicitMeta Rule: "MAJORITY Admins" LifecycleEndorsement: Type: ImplicitMeta Rule: "MAJORITY Endorsement" Endorsement: Type: ImplicitMeta Rule: "MAJORITY Endorsement" Capabilities: <<: *ApplicationCapabilities Orderer: &OrdererDefaults OrdererType: etcdraft Addresses: # 排序节点集群 - orderer0.consortiums.com:7050 - orderer1.consortiums.com:7050 - orderer2.consortiums.com:7050 - orderer3.consortiums.com:7050 - orderer4. consortiums.com:7050 # 打包区块的最长时间间隔,即每2s执行一次打包区块 BatchTimeout: 2s # 指定区块中可以包含的最大交易上限 BatchSize: MaxMessageCount: 10 AbsoluteMaxBytes: 99 MB PreferredMaxBytes: 512 KB Organizations: Policies: Readers: Type: ImplicitMeta Rule: "ANY Readers" Writers: Type: ImplicitMeta Rule: "ANY Writers" Admins: Type: ImplicitMeta Rule: "MAJORITY Admins" # 指定从排序节点发送到沿着节点的区中必须包含任意有写权限节点的签名 BlockValidation: Type: ImplicitMeta Rule: "ANY Writers" Channel: &ChannelDefaults Policies: # 指定谁可以调用'Deliver' API Readers: Type: ImplicitMeta Rule: "ANY Readers" # 指定谁可以调用 'Broadcast' API Writers: Type: ImplicitMeta Rule: "ANY Writers" # 指定谁可以修改通道配置 Admins: Type: ImplicitMeta Rule: "MAJORITY Admins" Capabilities: <<: *ChannelCapabilities Profiles: TwoOrgsChannel: Consortium: SampleConsortium <<: *ChannelDefaults Application: <<: *ApplicationDefaults Organizations: - *Org1 - *Org2 Capabilities: <<: *ApplicationCapabilities SampleMultiNodeEtcdRaft: <<: *ChannelDefaults Capabilities: <<: *ChannelCapabilities Orderer: <<: *OrdererDefaults OrdererType: etcdraft EtcdRaft: Consenters: - Host: orderer0.consortiums.com Port: 7050 ClientTLSCert: /root/fabric_cluster/crypto-config/ordererOrganizations/consortiums.com/orderers/orderer0.consortiums.com/tls/server.crt ServerTLSCert: /root/fabric_cluster/crypto-config/ordererOrganizations/consortiums.com/orderers/orderer0.consortiums.com/tls/server.crt - Host: orderer1.consortiums.com Port: 7050 ClientTLSCert: /root/fabric_cluster/crypto-config/ordererOrganizations/consortiums.com/orderers/orderer1.consortiums.com/tls/server.crt ServerTLSCert: /root/fabric_cluster/crypto-config/ordererOrganizations/consortiums.com/orderers/orderer1.consortiums.com/tls/server.crt - Host: orderer2.consortiums.com Port: 7050 ClientTLSCert: /root/fabric_cluster/crypto-config/ordererOrganizations/consortiums.com/orderers/orderer2.consortiums.com/tls/server.crt ServerTLSCert: /root/fabric_cluster/crypto-config/ordererOrganizations/consortiums.com/orderers/orderer2.consortiums.com/tls/server.crt - Host: orderer3.consortiums.com Port: 7050 ClientTLSCert: /root/fabric_cluster/crypto-config/ordererOrganizations/consortiums.com/orderers/orderer3.consortiums.com/tls/server.crt ServerTLSCert: /root/fabric_cluster/crypto-config/ordererOrganizations/consortiums.com/orderers/orderer3.consortiums.com/tls/server.crt - Host: orderer4.consortiums.com Port: 7050 ClientTLSCert: /root/fabric_cluster/crypto-config/ordererOrganizations/consortiums.com/orderers/orderer4.consortiums.com/tls/server.crt ServerTLSCert: /root/fabric_cluster/crypto-config/ordererOrganizations/consortiums.com/orderers/orderer4.consortiums.com/tls/server.crt Addresses: - orderer0.consortiums.com:7050 - orderer1.consortiums.com:7050 - orderer2.consortiums.com:7050 - orderer3.consortiums.com:7050 - orderer4.consortiums.com:7050 Organizations: - *OrdererOrg Capabilities: <<: *OrdererCapabilities Application: <<: *ApplicationDefaults Organizations: - <<: *OrdererOrg Consortiums: SampleConsortium: Organizations: - *Org1 - *Org2
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 #base.yaml version: '2' # 语法格式版本 services: order-base: # 在docker-compose-up.yaml中会通过该名字引入下面的配置 image: hyperledger/fabric-orderer #使用的Docker镜像 environment: - FABRIC_LOGGING_SPEC=DEBUG #日志级别 - ORDERER_GENERAL_LISTENADDRESS=0.0.0.0 #排序节点的监听地址 - ORDERER_GENERAL_LISTENPORT=7050 #排序节点的监听端口 - ORDERER_GENERAL_BOOTSTRAPMETHOD=file #启动排序节点的方法 - ORDERER_GENERAL_BOOTSTRAPFILE=/var/hyperledger/orderer/orderer.genesis.block # 创世区块的路径 - ORDERER_GENERAL_LOCALMSPID=OrdererMSP #节点所属组织的MSP唯一标识,需与系统通道配置中保持一致 - ORDERER_GENERAL_LOCALMSPDIR=/var/hyperledger/orderer/msp # msp文件所在目录 - ORDERER_GENERAL_TLS_ENABLED=true # 启用 TLS - ORDERER_GENERAL_TLS_PRIVATEKEY=/var/hyperledger/orderer/tls/server.key #排序节点使用的TLS私钥文件 - ORDERER_GENERAL_TLS_CERTIFICATE=/var/hyperledger/orderer/tls/server.crt # 排序节点使用的TLS服务端证书文件 - ORDERER_GENERAL_TLS_ROOTCAS=[/var/hyperledger/orderer/tls/ca.crt] # 排序节点使用的TLS CA信任根证书,用于校验客户端证书 - ORDERER_GENERAL_CLUSTER_CLIENTCERTIFICATE=/var/hyperledger/orderer/tls/server.crt #客户端证书文件,访问其他orderer节点时需要TLS双向认证 - ORDERER_GENERAL_CLUSTER_CLIENTPRIVATEKEY=/var/hyperledger/orderer/tls/server.key - ORDERER_GENERAL_CLUSTER_ROOTCAS=[/var/hyperledger/orderer/tls/ca.crt] # 客户端私钥文件 working_dir: /root/fabric_cluster/opt # 工作目录,即Docker容器的挂载目录 command: orderer #容器启动后默认执行的命令 volumes: - /root/fabric_cluster/channel-artifacts/genesis.block:/var/hyperledger/orderer/orderer.genesis.block #将宿主机中的创世区块映射到Docker容器中 peer-base: # 在docker-compose-up.yaml中会通过该名字引入下面的配置 image: hyperledger/fabric-peer #使用的Docker镜像 environment: #定义环境变量 - CORE_VM_ENDPOINT=unix:///host/var/run/docker.sock #虚拟机管理系统的访问端节点 - FABRIC_LOGGING_SPEC=DEBUG #日志级别 - CORE_PEER_TLS_ENABLED=true #启用TLS - CORE_PEER_GOSSIP_USELEADERELECTION=true #节点是否使用动态算法选出领导节点 - CORE_PEER_GOSSIP_ORGLEADER=false # 是否静态指定组织的领导节点 - CORE_PEER_PROFILE_ENABLED=true #是否启用HTTP分析服务 - CORE_PEER_TLS_CERT_FILE=/etc/hyperledger/fabric/tls/server.crt # Peer节点的证书文件路径 - CORE_PEER_TLS_KEY_FILE=/etc/hyperledger/fabric/tls/server.key # Peer节点的私钥文件路径 - CORE_PEER_TLS_ROOTCERT_FILE=/etc/hyperledger/fabric/tls/ca.crt # Peer节点的验证根证书文件路径 - CORE_CHAINCODE_EXECUTETIMEOUT=300s #在初始化和调用链码方法时节点等待的超时时间 working_dir: /root/fabric_cluster/opt/peer #工作目录 command: peer node start volumes: - /var/run/:/host/var/run/ cli-base: # 在docker-compose-up.yaml中会通过该名字引入下面的配置 image: hyperledger/fabric-tools #使用的Docker镜像 tty: true stdin_open: true environment: #环境变量 - GOPATH=/root/go #Go语言项目目录 - CORE_VM_ENDPOINT=unix:///host/var/run/docker.sock #虚拟机管理系统的访问端节点 - FABRIC_LOGGING_SPEC=DEBUG #日志级别 - CORE_PEER_TLS_ENABLED=true #启用TLS working_dir: / root/fabric_cluster/opt/peer #工作目录 command: /bin/bash volumes: - /var/run/:/host/var/run/ - / root/fabric_cluster/chaincode/go/:/hyperledger/cluster/chaincode/go # 存储链码的目录 - /root/fabric_cluster/crypto-config:/hyperledger/opt/peer/crypto-config/ - /root/fabric_cluster/channel-artifacts:/hyperledger/opt/peer/channel-artifacts ca-base: image: hyperledger/fabric-ca
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 #docker-compose-up.yaml version: '2' services: orderer0.consortiums.com: container_name: orderer0.consortiums.com #容器名 extends: #引入base.yaml中定义的配置项 file: base.yaml service: order-base volumes: #定义宿主机文件夹到容器中卷的映射关系 - /root/fabric_cluster/crypto-config/ordererOrganizations/consortiums.com/orderers/orderer0.consortiums.com/msp:/var/hyperledger/orderer/msp - /root/fabric_cluster/crypto-config/ordererOrganizations/consortiums.com/orderers/orderer0.consortiums.com/tls/:/var/hyperledger/orderer/tls ports: # 定义宿主机端和容器中端口的映射关系 - 7050:7050 orderer1.consortiums.com: container_name: orderer1.consortiums.com extends: file: base.yaml service: order-base volumes: - /root/fabric_cluster/crypto-config/ordererOrganizations/consortiums.com/orderers/orderer1.consortiums.com/msp:/var/hyperledger/orderer/msp - /root/fabric_cluster/crypto-config/ordererOrganizations/consortiums.com/orderers/orderer1.consortiums.com/tls/:/var/hyperledger/orderer/tls ports: - 8050:7050 orderer2.consortiums.com: container_name: orderer2.consortiums.com extends: file: base.yaml service: order-base volumes: - /root/fabric_cluster/crypto-config/ordererOrganizations/consortiums.com/orderers/orderer2.consortiums.com/msp:/var/hyperledger/orderer/msp - /root/fabric_cluster/crypto-config/ordererOrganizations/consortiums.com/orderers/orderer2.consortiums.com/tls/:/var/hyperledger/orderer/tls ports: - 9050:7050 orderer3.consortiums.com: container_name: orderer3.consortiums.com extends: file: base.yaml service: order-base volumes: - /root/fabric_cluster/crypto-config/ordererOrganizations/consortiums.com/orderers/orderer3.consortiums.com/msp:/var/hyperledger/orderer/msp - /root/fabric_cluster/crypto-config/ordererOrganizations/consortiums.com/orderers/orderer3.consortiums.com/tls/:/var/hyperledger/orderer/tls ports: - 10050:7050 orderer4.consortiums.com: container_name: orderer4.consortiums.com extends: file: base.yaml service: order-base volumes: - /root/fabric_cluster/crypto-config/ordererOrganizations/consortiums.com/orderers/orderer4.consortiums.com/msp:/var/hyperledger/orderer/msp - /root/fabric_cluster/crypto-config/ordererOrganizations/consortiums.com/orderers/orderer4.consortiums.com/tls/:/var/hyperledger/orderer/tls ports: - 11050:7050 peer0.org1.com: container_name: peer0.org1.com extends: file: base.yaml service: peer-base environment: - CORE_PEER_ID=peer0.org1.com #Peer节点实例的标识ID - CORE_PEER_ADDRESS=peer0.org1.com:7051 #Peer节点的P2P连接地址 - CORE_PEER_LISTENADDRESS=0.0.0.0:7051 #Peer节点的监听地址 - CORE_PEER_CHAINCODEADDRESS=peer0.org1.com:7052 #链码连接该Peer节点的地址 - CORE_PEER_CHAINCODELISTENADDRESS=0.0.0.0:7052 # Peer节点监听链码连接请求的地址 - CORE_PEER_GOSSIP_BOOTSTRAP=peer1.org1.com:8051 #初始化gossip的引导节点列表 - CORE_PEER_GOSSIP_EXTERNALENDPOINT=peer0.org1.com:7051#向组织外节点发布的访问端点 - CORE_PEER_LOCALMSPID=Org1MSP #本地MSP的标识ID volumes: #定义宿主机文件夹到容器中卷的映射关系 - /root/fabric_cluster/crypto-config/peerOrganizations/org1.com/peers/peer0.org1.com/msp:/etc/hyperledger/fabric/msp - /root/fabric_cluster/crypto-config/peerOrganizations/org1.com/peers/peer0.org1.com/tls:/etc/hyperledger/fabric/tls ports: - 7051:7051 peer1.org1.com: container_name: peer1.org1.com extends: file: base.yaml service: peer-base environment: - CORE_PEER_ID=peer1.org1.com - CORE_PEER_ADDRESS=peer1.org1.com:8051 - CORE_PEER_LISTENADDRESS=0.0.0.0:8051 - CORE_PEER_CHAINCODEADDRESS=peer1.org1.com:8052 - CORE_PEER_CHAINCODELISTENADDRESS=0.0.0.0:8052 - CORE_PEER_GOSSIP_BOOTSTRAP=peer0.org1.com:7051 - CORE_PEER_GOSSIP_EXTERNALENDPOINT=peer1.org1.com:8051 - CORE_PEER_LOCALMSPID=Org1MSP volumes: - /root/fabric_cluster/crypto-config/peerOrganizations/org1.com/peers/peer1.org1.com/msp:/etc/hyperledger/fabric/msp - /root/fabric_cluster/crypto-config/peerOrganizations/org1.com/peers/peer1.org1.com/tls:/etc/hyperledger/fabric/tls ports: - 8051:8051 peer0.org2.com: container_name: peer0.org2.com extends: file: base.yaml service: peer-base environment: - CORE_PEER_ID=peer0.org2.com - CORE_PEER_ADDRESS=peer0.org2.com:9051 - CORE_PEER_LISTENADDRESS=0.0.0.0:9051 - CORE_PEER_CHAINCODEADDRESS=peer0.org2.com:9052 - CORE_PEER_CHAINCODELISTENADDRESS=0.0.0.0:9052 - CORE_PEER_GOSSIP_BOOTSTRAP=peer1.org2.com:10051 - CORE_PEER_GOSSIP_EXTERNALENDPOINT=peer0.org2.com:9051 - CORE_PEER_LOCALMSPID=Org2MSP volumes: - /root/fabric_cluster/crypto-config/peerOrganizations/org2.com/peers/peer0.org2.com/msp:/etc/hyperledger/fabric/msp - /root/fabric_cluster/crypto-config/peerOrganizations/org2.com/peers/peer0.org2.com/tls:/etc/hyperledger/fabric/tls ports: - 9051:9051 peer1.org2.com: container_name: peer1.org2.com extends: file: base.yaml service: peer-base environment: - CORE_PEER_ID=peer1.org2.com - CORE_PEER_ADDRESS=peer1.org2.com:10051 - CORE_PEER_LISTENADDRESS=0.0.0.0:10051 - CORE_PEER_CHAINCODEADDRESS=peer1.org2.com:10052 - CORE_PEER_CHAINCODELISTENADDRESS=0.0.0.0:10052 - CORE_PEER_GOSSIP_BOOTSTRAP=peer0.org2.com:9051 - CORE_PEER_GOSSIP_EXTERNALENDPOINT=peer1.org2.com:10051 - CORE_PEER_LOCALMSPID=Org2MSP volumes: - /root/fabric_cluster/crypto-config/peerOrganizations/org2.com/peers/peer1.org2.com/msp:/etc/hyperledger/fabric/msp - /root/fabric_cluster/crypto-config/peerOrganizations/org2.com/peers/peer1.org2.com/tls:/etc/hyperledger/fabric/tls ports: - 10051:10051 cli-peer0-org1: container_name: cli-peer0-org1 extends: file: base.yaml service: cli-base environment: - CORE_PEER_ID=cli-peer0-org1 - CORE_PEER_ADDRESS=peer0.org1.com:7051 - CORE_PEER_LOCALMSPID=Org1MSP - CORE_PEER_TLS_CERT_FILE=/hyperledger/opt/peer/crypto-config/peerOrganizations/org1.com/peers/peer0.org1.com/tls/server.crt - CORE_PEER_TLS_KEY_FILE=/hyperledger/opt/peer/crypto-config/peerOrganizations/org1.com/peers/peer0.org1.com/tls/server.key - CORE_PEER_TLS_ROOTCERT_FILE=/hyperledger/opt/peer/crypto-config/peerOrganizations/org1.com/peers/peer0.org1.com/tls/ca.crt - CORE_PEER_MSPCONFIGPATH=/hyperledger/opt/peer/crypto-config/peerOrganizations/org1.com/users/Admin@org1.com/msp cli-peer1-org1: container_name: cli-peer1-org1 extends: file: base.yaml service: cli-base environment: - CORE_PEER_ID=cli-peer1-org1 - CORE_PEER_ADDRESS=peer1.org1.com:8051 - CORE_PEER_LOCALMSPID=Org1MSP - CORE_PEER_TLS_CERT_FILE=/hyperledger/opt/peer/crypto-config/peerOrganizations/org1.com/peers/peer1.org1.com/tls/server.crt - CORE_PEER_TLS_KEY_FILE=/hyperledger/opt/peer/crypto-config/peerOrganizations/org1.com/peers/peer1.org1.com/tls/server.key - CORE_PEER_TLS_ROOTCERT_FILE=/hyperledger/opt/peer/crypto-config/peerOrganizations/org1.com/peers/peer1.org1.com/tls/ca.crt - CORE_PEER_MSPCONFIGPATH=/hyperledger/opt/peer/crypto-config/peerOrganizations/org1.com/users/Admin@org1.com/msp cli-peer0-org2: container_name: cli-peer0-org2 extends: file: base.yaml service: cli-base environment: - CORE_PEER_ID=cli-peer0-org2 - CORE_PEER_ADDRESS=peer0.org2.com:9051 - CORE_PEER_LOCALMSPID=Org2MSP - CORE_PEER_TLS_CERT_FILE=/hyperledger/opt/peer/crypto-config/peerOrganizations/org2.com/peers/peer0.org2.com/tls/server.crt - CORE_PEER_TLS_KEY_FILE=/hyperledger/opt/peer/crypto-config/peerOrganizations/org2.com/peers/peer0.org2.com/tls/server.key - CORE_PEER_TLS_ROOTCERT_FILE=/hyperledger/opt/peer/crypto-config/peerOrganizations/org2.com/peers/peer0.org2.com/tls/ca.crt - CORE_PEER_MSPCONFIGPATH=/hyperledger/opt/peer/crypto-config/peerOrganizations/org2.com/users/Admin@org2.com/msp cli-peer1-org2: container_name: cli-peer1-org2 extends: file: base.yaml service: cli-base environment: - CORE_PEER_ID=cli-peer1-org2 - CORE_PEER_ADDRESS=peer1.org2.com:10051 - CORE_PEER_LOCALMSPID=Org2MSP - CORE_PEER_TLS_CERT_FILE=/hyperledger/opt/peer/crypto-config/peerOrganizations/org2.com/peers/peer1.org2.com/tls/server.crt - CORE_PEER_TLS_KEY_FILE=/hyperledger/opt/peer/crypto-config/peerOrganizations/org2.com/peers/peer1.org2.com/tls/server.key - CORE_PEER_TLS_ROOTCERT_FILE=/hyperledger/opt/peer/crypto-config/peerOrganizations/org2.com/peers/peer1.org2.com/tls/ca.crt - CORE_PEER_MSPCONFIGPATH=/hyperledger/opt/peer/crypto-config/peerOrganizations/org2.com/users/Admin@org2.com/msp ca-org1: container_name: ca-org1 extends: file: base.yaml service: ca-base environment: - FABRIC_CA_SERVER_CA_NAME=ca-org1 - FABRIC_CA_SERVER_CA_CERTFILE=/etc/hyperledger/fabric-ca-server-config/ca.org1.com-cert.pem - FABRIC_CA_SERVER_CA_KEYFILE=/etc/hyperledger/fabric-ca-server-config/MIGHAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBG0wawIBAQQg4Hwt/FeN1y7ePgsRCXgkX0om4wKggwkkQC6R6Sdwg2mhRANCAARAysXo0jF5Az5jUObnGRNHU6kvCCAI2n/8uFdOo/i8iPvB/8BTtgrx+rSl6f/oVnw9vRNlVOEW/ZfB03/e3epu - FABRIC_CA_SERVER_TLS_CERTFILE=/etc/hyperledger/fabric-ca-server-config/ca.org1.com-cert.pem - FABRIC_CA_SERVER_TLS_KEYFILE=/etc/hyperledger/fabric-ca-server-config/MIGHAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBG0wawIBAQQg4Hwt/FeN1y7ePgsRCXgkX0om4wKggwkkQC6R6Sdwg2mhRANCAARAysXo0jF5Az5jUObnGRNHU6kvCCAI2n/8uFdOo/i8iPvB/8BTtgrx+rSl6f/oVnw9vRNlVOEW/ZfB03/e3epu ports: - 7054:7054 command: sh -c 'fabric-ca-server start -b admin:adminpw -d' volumes: - /root/fabric_cluster/crypto-config/peerOrganizations/org1.com/ca:/etc/hyperledger/fabric-ca-server-config ca-org2: container_name: ca-org2 extends: file: base.yaml service: ca-base environment: - FABRIC_CA_SERVER_CA_NAME=ca-org2 - FABRIC_CA_SERVER_CA_CERTFILE=/etc/hyperledger/fabric-ca-server-config/ca.org2.com-cert.pem - FABRIC_CA_SERVER_CA_KEYFILE=/etc/hyperledger/fabric-ca-server-config/MIGHAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBG0wawIBAQQgSAjLaVDM5Zahbnm6fo9cNGe3/aSGMH5ThCC30YJXlfihRANCAAR8/093Yml+C6HBLaH3JN0QpvTPV4Ks52ViBalBghhSCRfgJMBlUawEyavvuwUWUm0OH835p7kW9JTxL+eKy3Sn - FABRIC_CA_SERVER_TLS_CERTFILE=/etc/hyperledger/fabric-ca-server-config/ca.org2.com-cert.pem - FABRIC_CA_SERVER_TLS_KEYFILE=/etc/hyperledger/fabric-ca-server-config/MIGHAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBG0wawIBAQQgSAjLaVDM5Zahbnm6fo9cNGe3/aSGMH5ThCC30YJXlfihRANCAAR8/093Yml+C6HBLaH3JN0QpvTPV4Ks52ViBalBghhSCRfgJMBlUawEyavvuwUWUm0OH835p7kW9JTxL+eKy3Sn ports: - 8054:7054 command: sh -c 'fabric-ca-server start -b admin:adminpw -d' volumes: - /root/fabric_cluster/crypto-config/peerOrganizations/org2.com/ca:/etc/hyperledger/fabric-ca-server-config
09
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 #在测试网络中部署链码 ./network.sh deployCC -ccn basic -ccp ../asset-transfer-basic/chaincode-go -ccl go #设置Go语言的网络代理 go env -w GOPROXY=https://goproxy.io,direct go env -w GO111MODULE=on #启动测试网络,并创建通道mychannel cd /$GOPATH/src/github.com/hyperledger/fabric/scripts/fabric-samples/test-network ./network.sh up ./network.sh createChannel #1.准备运行命令的环境 cd /$GOPATH/src/github.com/hyperledger/fabric/scripts/fabric-samples/test-network export PATH=${PWD}/../bin:$PATH export FABRIC_CFG_PATH=$PWD/../config/ export CORE_PEER_TLS_ENABLED=true export CORE_PEER_LOCALMSPID="Org1MSP" export CORE_PEER_TLS_ROOTCERT_FILE=${PWD}/organizations/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/tls/ca.crt export CORE_PEER_MSPCONFIGPATH=${PWD}/organizations/peerOrganizations/org1.example.com/users/Admin@org1.example.com/msp export CORE_PEER_ADDRESS=localhost:7051 #【例9-1】 使用peer chaincode invoke命令调用链码中的InitLedger函数 peer chaincode invoke -o localhost:7050 --ordererTLSHostnameOverride orderer.example.com --tls --cafile ${PWD}/organizations/ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-cert.pem -C mychannel -n basic --peerAddresses localhost:7051 --tlsRootCertFiles ${PWD}/organizations/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/tls/ca.crt --peerAddresses localhost:9051 --tlsRootCertFiles ${PWD}/organizations/peerOrganizations/org2.example.com/peers/peer0.org2.example.com/tls/ca.crt -c '{"function":"InitLedger","Args":[]}' #【例9-2】 使用peer chaincode query命令调用链码通过GetAllAssets函数查询账本中所有资产的信息,命令如下: peer chaincode query -C mychannel -n basic -c '{"Args":["GetAllAssets"]}' #【例9-3】 使用peer chaincode invoke命令调用链码的TransferAsset函数将资产asset6转移给Johney,命令如下: peer chaincode invoke -o localhost:7050 --ordererTLSHostnameOverride orderer.example.com --tls --cafile ${PWD}/organizations/ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-cert.pem -C mychannel -n basic --peerAddresses localhost:7051 --tlsRootCertFiles ${PWD}/organizations/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/tls/ca.crt --peerAddresses localhost:9051 --tlsRootCertFiles ${PWD}/organizations/peerOrganizations/org2.example.com/peers/peer0.org2.example.com/tls/ca.crt -c '{"function":"TransferAsset","Args":["asset6","Johney"]}' #【例9-4】 执行peer chaincode query命令调用链码的ReadAsset函数查看资产asset6的详细信息,命令如下: peer chaincode query -C mychannel -n basic -c '{"Args":["ReadAsset","asset6"]}' 因为前面都是查看组织Org1的Peer节点上的账本,这里切换环境变量如下,查看组织Org2的Peer节点上的账本,两个账本的内容应该是一致的。 #Environment variables for Org2 export CORE_PEER_TLS_ENABLED=true export CORE_PEER_LOCALMSPID="Org2MSP" export CORE_PEER_TLS_ROOTCERT_FILE=${PWD}/organizations/peerOrganizations/org2.example.com/peers/peer0.org2.example.com/tls/ca.crt export CORE_PEER_MSPCONFIGPATH=${PWD}/organizations/peerOrganizations/org2.example.com/users/Admin@org2.example.com/msp export CORE_PEER_ADDRESS=localhost:9051 #首先需要安装gcc、C++编译器以及内核文件,命令如下: yum -y install gcc gcc-c++ kernel-devel 然后执行如下命令,构建orderer、peer和configtxgen工具的二进制文件。 cd /$GOPATH/src/github.com/hyperledger/fabric/ make orderer peer configtxgen #查看构建的结果 ls /root/gocode/src/github.com/hyperledger/fabric/build/bin #设置环境变量 export PATH=$(pwd)/build/bin:$PATH export FABRIC_CFG_PATH=$(pwd)/sampleconfig #3.生成创世区块 sudo mkdir /var/hyperledger configtxgen -profile SampleDevModeSolo -channelID syschannel -configPath $FABRIC_CFG_PATH -outputBlock $(pwd)/sampleconfig/genesisblock FABRIC_LOGGING_SPEC=chaincode=debug CORE_PEER_CHAINCODELISTENADDRESS=0.0.0.0:7052 peer node start --peer-chaincodedev=true #9.5.2 启动排序节点 ORDERER_GENERAL_GENESISPROFILE=SampleDevModeSolo orderer #9.5.3 在开发模式下启动Peer节点 FABRIC_LOGGING_SPEC=chaincode=debug CORE_PEER_CHAINCODELISTENADDRESS=0.0.0.0:7052 peer node start --peer-chaincodedev=true #9.5.4 创建通道 configtxgen -channelID ch2 -outputCreateChannelTx ch2.tx -profile SampleSingleMSPChannel -configPath $FABRIC_CFG_PATH peer channel create -o 127.0.0.1:7050 -c ch2 -f ch2.tx peer channel join -b ch2.block #9.5.5 在开发模式下构建链码 cd $GOPATH/src/github.com/hyperledger/fabric/my_contracts/sample9_5 go mod init go build -o ./simpleChaincode #9.5.6 启动链码 cd $GOPATH/src/github.com/hyperledger/fabric/my_contracts/sample9_5 CORE_CHAINCODE_LOGLEVEL=debug CORE_PEER_TLS_ENABLED=false CORE_CHAINCODE_ID_NAME=simpleChaincode:1.0 ./simpleChaincode -peer.address 127.0.0.1:7052 #9.5.7 批准和写入链码定义 #1.批准链码定义 peer lifecycle chaincode approveformyorg -o 127.0.0.1:7050 --channelID ch2 --name simpleChaincode --version 1.0 --sequence 1 --init-required --signature-policy "OR ('SampleOrg.member')" --package-id simpleChaincode:1.0 #2.查看通道成员批准链码定义的情况 peer lifecycle chaincode checkcommitreadiness -o 127.0.0.1:7050 --channelID ch2 --name simpleChaincode --version 1.0 --sequence 1 --init-required --signature-policy "OR ('SampleOrg.member')" #3.将链码定义写入通道 peer lifecycle chaincode commit -o 127.0.0.1:7050 --channelID ch2 --name simpleChaincode --version 1.0 --sequence 1 --init-required --signature-policy "OR ('SampleOrg.member')" --peerAddresses 127.0.0.1:7051 #9.5.8 调用链码 CORE_PEER_ADDRESS=127.0.0.1:7051 peer chaincode invoke -o 127.0.0.1:7050 -C ch2 -n simpleChaincode -c '{"Args":["Create","a","100"]}' --isInit #(1)如果测试网络已经启动,则执行如下命令关闭测试网络,初始化测试环境。 cd /$GOPATH/src/github.com/hyperledger/fabric/scripts/fabric-samples/test-network ./network.sh down #(2)如果之前运行过本实例的链码容器,则执行如下命令删除之前的容器: docker rm -f $(docker ps -a | awk '($2 ~ /dev-peer.*.marblesp.*/) {print $1}') docker rmi -f $(docker images | awk '($1 ~ /dev-peer.*.marblesp.*/) {print $3}') #(3)以CouchDB为状态数据库启动测试网络,命令如下: cd /$GOPATH/src/github.com/hyperledger/fabric/scripts/fabric-samples/test-network ./network.sh up createChannel -s couchdb #(4)设置环境变量,切换为Org1 admin的身份。 export PATH=${PWD}/../bin:$PATH export FABRIC_CFG_PATH=$PWD/../config/ export CORE_PEER_TLS_ENABLED=true export CORE_PEER_LOCALMSPID="Org1MSP" export CORE_PEER_TLS_ROOTCERT_FILE=${PWD}/organizations/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/tls/ca.crt export CORE_PEER_MSPCONFIGPATH=${PWD}/organizations/peerOrganizations/org1.example.com/users/Admin@org1.example.com/msp export CORE_PEER_ADDRESS=localhost:7051 #(5)执行如下命令安装本实例的依赖包: cd ../chaincode/marbles02_private/go go env -w GOPROXY=https://goproxy.cn GO111MODULE=on go mod vendor (6)执行如下命令,打包marbles链码。 cd /$GOPATH/src/github.com/hyperledger/fabric/scripts/fabric-samples/test-network peer lifecycle chaincode package marblesp.tar.gz --path ../chaincode/marbles02_private/go/ --lang golang --label marblesp_1.0 #(7)执行如下命令,安装链码marbles。 peer lifecycle chaincode install marblesp.tar.gz #(8)将第7步中输出的package ID赋值到环境变量CC_PACKAGE_ID中,命令如下: export CC_PACKAGE_ID=marblesp_1.0:b6a48e74b3e6028164b2f6e59f6b8fad4bf279b8823e931adf4d9b2507498b6d #(9)代表组织Org1批准链码定义。 export CORE_PEER_LOCALMSPID="Org1MSP" export CORE_PEER_TLS_ROOTCERT_FILE=${PWD}/organizations/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/tls/ca.crt export CORE_PEER_MSPCONFIGPATH=${PWD}/organizations/peerOrganizations/org1.example.com/users/Admin@org1.example.com/msp export CORE_PEER_ADDRESS=localhost:7051 export ORDERER_CA=${PWD}/organizations/ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-cert.pem peer lifecycle chaincode approveformyorg -o localhost:7050 --ordererTLSHostnameOverride orderer.example.com --channelID mychannel --name marblesp --version 1.0 --collections-config ../chaincode/marbles02_private/collections_config.json --signature-policy "OR('Org1MSP.member','Org2MSP.member')" --package-id $CC_PACKAGE_ID --sequence 1 --tls --cafile $ORDERER_CA #(10)代表组织Org2批准链码定义。 export CORE_PEER_LOCALMSPID="Org2MSP" export CORE_PEER_TLS_ROOTCERT_FILE=${PWD}/organizations/peerOrganizations/org2.example.com/peers/peer0.org2.example.com/tls/ca.crt export CORE_PEER_MSPCONFIGPATH=${PWD}/organizations/peerOrganizations/org2.example.com/users/Admin@org2.example.com/msp export CORE_PEER_ADDRESS=localhost:9051 peer lifecycle chaincode approveformyorg -o localhost:7050 --ordererTLSHostnameOverride orderer.example.com --channelID mychannel --name marblesp --version 1.0 --collections-config ../chaincode/marbles02_private/collections_config.json --signature-policy "OR('Org1MSP.member','Org2MSP.member')" --package-id $CC_PACKAGE_ID --sequence 1 --tls --cafile $ORDERER_CA #(11)提交链码定义到通道。现在,组织Org1和Org2都已经批准了链码定义,可以执行如下命令提交链码定义到通道。 export ORDERER_CA=${PWD}/organizations/ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-cert.pem export ORG1_CA=${PWD}/organizations/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/tls/ca.crt export ORG2_CA=${PWD}/organizations/peerOrganizations/org2.example.com/peers/peer0.org2.example.com/tls/ca.crt peer lifecycle chaincode commit -o localhost:7050 --ordererTLSHostnameOverride orderer.example.com --channelID mychannel --name marblesp --version 1.0 --sequence 1 --collections-config ../chaincode/marbles02_private/collections_config.json --signature-policy "OR('Org1MSP.member','Org2MSP.member')" --tls --cafile $ORDERER_CA --peerAddresses localhost:7051 --tlsRootCertFiles $ORG1_CA --peerAddresses localhost:9051 --tlsRootCertFiles $ORG2_CA #(12)设置环境变量,切换至组织Org1的身份。 export CORE_PEER_LOCALMSPID="Org1MSP" export CORE_PEER_TLS_ROOTCERT_FILE=${PWD}/organizations/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/tls/ca.crt export CORE_PEER_MSPCONFIGPATH=${PWD}/organizations/peerOrganizations/org1.example.com/users/Admin@org1.example.com/msp export CORE_PEER_ADDRESS=localhost:7051 #(13)调用链码marblesp的InitMarble()函数,通过命令选项--transient传入暂态数据。 export MARBLE=$(echo -n "{\"name\":\"marble1\",\"color\":\"blue\",\"size\":35,\"owner\":\"tom\",\"price\":99}" | base64 | tr -d \\n) peer chaincode invoke -o localhost:7050 --ordererTLSHostnameOverride orderer.example.com --tls --cafile ${PWD}/organizations/ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-cert.pem -C mychannel -n marblesp -c '{"Args":["InitMarble"]}' --transient "{\"marble\":\"$MARBLE\"}" #(14)执行如下命令,查询名字为marble1的记录。 peer chaincode query -C mychannel -n marblesp -c '{"Args":["ReadMarble","marble1"]}' #(15)执行如下命令,查询私有数据,执行结果如图9-15所示。 peer chaincode query -C mychannel -n marblesp -c '{"Args":["ReadMarblePrivateDetails","marble1"]}'
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 #simple-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 } // 在世界状态数据库中添加一个键值对 func (sc *SimpleContract) Create(ctx CustomTransactionContextInterface, key string, value string) error { existing := ctx.GetData() 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 } // 在世界状态数据库中修改指定键的值 func (sc *SimpleContract) Update(ctx CustomTransactionContextInterface, key string, value string) error { existing := ctx.GetData() 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 } // 从世界状态数据库中根据键读取数据 func (sc *SimpleContract) Read(ctx CustomTransactionContextInterface, key string) (string, error) { existing := ctx.GetData() if existing == nil { return "", fmt.Errorf("Cannot read world state pair with key %s. Does not exist", key) } return string(existing), nil }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 #main.go package main import ( "errors" "github.com/hyperledger/fabric-contract-api-go/contractapi" ) //交易前处理函数 func GetWorldState(ctx CustomTransactionContextInterface) error { _, params := ctx.GetStub().GetFunctionAndParameters() if len(params) < 1 { return errors.New("Missing key for world state") } existing, err := ctx.GetStub().GetState(params[0]) if err != nil { return errors.New("Unable to interact with world state") } ctx.SetData(existing) return nil } func main() { simpleContract := new(SimpleContract) simpleContract.BeforeTransaction = GetWorldState simpleContract.TransactionContextHandler = new(CustomTransactionContext) cc, err := contractapi.NewChaincode(simpleContract) if err != nil { panic(err.Error()) } if err := cc.Start(); err != nil { panic(err.Error()) } }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 #transaction-context.go package main import ( "github.com/hyperledger/fabric-contract-api-go/contractapi" ) //定义接口CustomTransactionContextInterface,指定自定义交易上下文对象的结构体中必须实现的函数 type CustomTransactionContextInterface interface { contractapi.TransactionContextInterface GetData() []byte SetData([]byte) } // 自定义交易上下文对象 type CustomTransactionContext struct { contractapi.TransactionContext data []byte } // GetData return set data func (ctc *CustomTransactionContext) GetData() []byte { return ctc.data } // SetData provide a value for data func (ctc *CustomTransactionContext) SetData(data []byte) { ctc.data = data }
10
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 #下载Fabric SDK Go cd $GOPATH/src/github.com/hyperledger git clone https://github.com/hyperledger/fabric-sdk-go.git #检出最新代码 cd $GOPATH/src/github.com/hyperledger/fabric-sdk-go git checkout 614551a752802488988921a730b172dada7def1d #2.安装Fabric SDK Go的依赖包 cd $GOPATH/src/github.com/hyperledger/fabric-sdk-go export GOPROXY=https://goproxy.cn export GO111MODULE=on make depend make depend-install #手动生成相关依赖包 #手动下载gocov go get -u github.com/axw/gocov/ #手动安装gocov cd $GOPATH/src/github.com/axw/gocov/ go install #手动安装dep export GO111MODULE=on go env -w GOPROXY=https://goproxy.cn go get -u github.com/golang/dep/cmd/dep #(1)启动测试网络 cd /$GOPATH/src/github.com/hyperledger/fabric/scripts/fabric-samples/test-network ./network.sh up createChannel -ca #(2)部署智能合约 ./network.sh deployCC -ccn basic -ccp ../asset-transfer-basic/chaincode-go -ccl go #(3)运行示例程序assetTransfer.go cd ../ asset-transfer-basic/application-go go run assetTransfer.go