#include "abieos_numeric.hpp"
#include <stdio.h>
#include <cassert>
using namespace abieos;
int main() {
std::string pubkey_str = std::string("EOS6S7kyRBUnwhKwfz41E7hCv9swCzT6AicNb7Skiz4LAeY7wG9WJ");
abieos::public_key pubkey = string_to_public_key(pubkey_str);
std::string decoded_pubkey_str = public_key_to_string(pubkey);
assert(decoded_pubkey_str == pubkey_str);
printf("Succcess!\n");
}
源代码地址:https://github.com/cppfuns/abieos-numeric-c-14/blob/master/test.cpp
目前想检测侧链个节点的健康状况,此文将测试插件
插件源代码地址:https://github.com/LiquidEOS/eos-producer-heartbeat-plugin
前端项目地址:https://github.com/LiquidEOS/eos-producer-heartbeat
检测的原理就是,提前准备个账号,部署好收集节点信息的合约
合约地址:https://github.com/LiquidEOS/eos-producer-heartbeat/blob/master/eosio_docker/contracts/heartbeat/heartbeat.cpp
各个节点定时(heartbeat-period)将数据push到这个合约(heartbeat-contract)。
cd <eosio-source-dir>
cd plugins
git clone https://github.com/LiquidEOS/eos-producer-heartbeat-plugin.git producer_heartbeat_plugin
cd producer_heartbeat_plugin
git checkout tags/v1.5.01
cd ../..
git apply plugins/producer_heartbeat_plugin/install.patch
./eosio_build.sh -s "EOS"
sudo ./eosio_install.sh
如果是测试,这一步非必要的。
$ cleos create key --to-console
Private key: 5JPxA1FPp2fMJj2hh1ax8cuJMQchffCi3GnBcobwL5SJhyxMS9n
Public key: EOS6pZfrTRMesCnSaE1XwYSFFUtsdGeH6Ljj6xGWxFk4N5Z3T13KT
下文中 PRODUCERACCT 为出块节点账户
cleos system newaccount PRODUCERACCT eosheartbeat EOS6pZfrTRMesCnSaE1XwYSFFUtsdGeH6Ljj6xGWxFk4N5Z3T13KT EOS6pZfrTRMesCnSaE1XwYSFFUtsdGeH6Ljj6xGWxFk4N5Z3T13KT --stake-net '50.00 EOS' --stake-cpu '50.00 EOS' --buy-ram-kbytes 10000
cleos set account permission PRODUCERACCT heartbeat '{"threshold":1,"keys":[{"key":"EOS6pZfrTRMesCnSaE1XwYSFFUtsdGeH6Ljj6xGWxFk4N5Z3T13KT","weight":1}]}' "active" -p PRODUCERACCT@active
cleos set action permission PRODUCERACCT eosheartbeat heartbeat heartbeat
cleos set action permission PRODUCERACCT theblacklist sethash heartbeat
plugin = eosio::producer_heartbeat_plugin
heartbeat-period = 1500
heartbeat-signature-provider = HEARTBEAT_PUB_KEY=KEY:HEARTBEAT_PRIVATE_KEY
heartbeat-contract = eosheartbeat
heartbeat-permission = heartbeat
heartbeat-oncall = telegram:johndoe
稍后测试后,在做补充
在 fabric 源码 sampleconfig 目录的两个配置文件,core.yaml,orderer.yaml
Peer 配置剖析 core.yaml
###############################################################################
#
# 日志部分
#
###############################################################################
logging: ## 日志级别有: critical、 error、 warning、 notice、 info、 debug 级别由大到小, 级别越小输出越详细
level: info ## 全局的默认日志级别
## 各个模块日志级别, 覆盖全局配置
cauthdsl: warning
gossip: warning
grpc: error
ledger: info
msp: warning
policies: warning
peer:
gossip: warning
# 日志的输出格式
format: '%{color}%{time:2006-01-02 15:04:05.000 MST} [%{module}] %{shortfunc} -> %{level:.4s} %{id:03x}%{color:reset} %{message}'
###############################################################################
#
# peer部分
#
###############################################################################
peer:
id: jdoe ## Peer节点ID
networkId: dev ## 网络ID
listenAddress: 0.0.0.0:7051 ## 节点监听的本地网络接口地址
chaincodeAddress: 0.0.0.0:7052 ## 链码容器连接时的监听地址 如未指定, 则使用listenAddress的IP地址和7052端口
address: 0.0.0.0:7051 ## 节点对外的服务地址 (对外的地址)
addressAutoDetect: false ## 是否自动探测服务地址 (默认 关闭, 如果启用TLS时,最好关闭)
gomaxprocs: -1 ## Go的进程限制数 runtime.GOMAXPROCS(n) 默认 -1
keepalive: ## 客户端和peer间的网络心跳连接配置
minInterval: 60s ## 最小的心跳间隔时间
client: ## 该节点和客户端 的交互配置
interval: 60s ## 和客户端 的心跳间隔 必须 interval >= minInterval
timeout: 20s ## 和客户端 间的网络连接超时时间
deliveryClient: ## 交付客户端用于与订购节点通信的心跳
interval: 60s
timeout: 20s
gossip: ## 节点间通信的gossip 协议的P2P通信 【主要包含了 启动 及 连接】
bootstrap: 127.0.0.1:7051 ## 启动节点后 向哪些节点发起gossip连接,以加入网络,且节点相互间都是同一个组织的
useLeaderElection: true ## 是否启动动态选举 组织的Leader 节点 与 orgLeader 互斥
orgLeader: false ## 是否指定本节点为 组织Leader 节点 与 useLeaderElection 互斥
endpoint: ## 本节点在组织内的gossip id
maxBlockCountToStore: 100 ## 保存到内存的区块个数上限
maxPropagationBurstLatency: 10ms ## 保存消息的最大时间,超过则触发转发给其他节点
maxPropagationBurstSize: 10 ## 保存的最大消息个数,超过则触发转发给其他节点
propagateIterations: 1 ## 消息转发的次数
propagatePeerNum: 3 ## 推送消息给指定个数的节点
pullInterval: 4s ## 拉取消息的时间间隔 (second) 必须大于 digestWaitTime + responseWaitTime
pullPeerNum: 3 ## 从指定个数的节点拉取消息
requestStateInfoInterval: 4s ## 从节点拉取状态信息(StateInfo) 消息间隔 (second)
publishStateInfoInterval: 4s ## 向其他节点推动状态信息消息的间隔 (second)
stateInfoRetentionInterval: ## 状态信息消息的超时时间 (second)
publishCertPeriod: 10s ## 启动后在心跳消息中包括证书的等待时间
skipBlockVerification: false ## 是否不对区块消息进行校验,默认为false
dialTimeout: 3s ## gRPC 连接拨号的超时 (second)
connTimeout: 2s ## 建立连接的超时 (second)
recvBuffSize: 20 ## 收取消息的缓冲大小
sendBuffSize: 200 ## 发送消息的缓冲大小
digestWaitTime: 1s ## 处理摘要数据的等待时间 (second) 可以大于 requestWaitTime
requestWaitTime: 1500ms ## 处理nonce 数据的等待时间 (milliseconds) 可以大于 digestWaitTime
responseWaitTime: 2s ## 终止拉取数据处理的等待时间 (second)
aliveTimeInterval: 5s ## 定期发送Alive 心跳消息的时间间隔 (second)
aliveExpirationTimeout: 25s ## Alive 心跳消息的超时时间 (second)
reconnectInterval: 25s ## 断线后重连的时间间隔 (second)
externalEndpoint: ## 节点被组织外节点感知时的地址,公布给其他组织的地址和端口, 如果不指定, 其他组织将无法知道本peer的存在
election: ## Leader 节点的选举配置
startupGracePeriod: 15s ## leader节点选举等待的时间 (second)
membershipSampleInterval: 1s ## 测试peer稳定性的时间间隔 (second)
leaderAliveThreshold: 10s ## pear 尝试进行选举的等待超时 (second)
leaderElectionDuration: 5s ## pear 宣布自己为Leader节点的等待时间 (second)
pvtData:
pullRetryThreshold: 60s
transientstoreMaxBlockRetention: 1000
pushAckTimeout: 3s
btlPullMargin: 10
reconcileBatchSize: 10
reconcileSleepInterval: 5m
events: ## 事件配置 (在1.3版本后配置去除)
address: 0.0.0.0:7053 ## 本地服务监听地址 (默认在所有网络接口上进心监听,端口 7053)
buffersize: 100 ## 最大缓冲消息数,超过则向缓冲中发送事件消息会被阻塞
timeout: 10ms ## 事件发送超时时间, 如果事件缓存已满, timeout < 0, 事件被丢弃; timeout > 0, 阻塞直到超时丢弃, timeout = 0, 阻塞直到发送出去
timewindow: 15m ## 允许peer和 客户端 时间不一致的最大时间差
keepalive: ## 客户端到peer间的事件心跳
minInterval: 60s
sendTimeout: 60s ## 在GRPC流上向客户端发送事件的超时时间
tls: ## tls配置
enabled: false ## 是否开启 TLS,默认不开启TLS
clientAuthRequired: false ## 客户端连接到peer是否需要使用加密
cert: ## 证书密钥的位置, 各peer应该填写各自相应的路径
file: tls/server.crt ## 本服务的身份验证证书,公开可见,访问者通过该证书进行验证
key:
file: tls/server.key ## 本服务的签名私钥
rootcert:
file: tls/ca.crt ## 信任的根CA整数位置
clientRootCAs: ## 用于验证客户端证书的根证书颁发机构的集合
files:
- tls/ca.crt
clientKey: ## 当TLS密钥用于制作客户端连接。如果不设置,将使用而不是peer.tls.key.file
file:
clientCert: ## 在进行客户端连接时用于TLS的X.509证书。 如果未设置,将使用peer.tls.cert.file
file:
serverhostoverride: ## 是否制定进行TLS握手时的主机名称
authentication: ## 身份验证包含与验证客户端消息相关的配置参数
timewindow: 15m ## 客户端请求消息中指定的当前服务器时间与客户端时间之间的可接受差异
fileSystemPath: /var/hyperledger/production ## peer数据存储位置(包括账本,状态数据库等)
BCCSP: ## 加密库配置 与Orderer 配置一样
Default: SW ## 使用软件加密方式 (默认 SW)
SW:
Hash: SHA2 ## Hash 算法类型,目前仅支持SHA2
Security: 256
FileKeyStore: ## 本地私钥文件路径,默认指向 <mspConfigPath>/keystore
KeyStore:
# Settings for the PKCS#11 crypto provider (i.e. when DEFAULT: PKCS11)
PKCS11: ## 设置 PKCS#11 加密算法 (默认PKCS11)
Library: ## 本地PKCS11依赖库
Label: ## token的标识
Pin: ## 使用Pin
Hash:
Security:
FileKeyStore:
KeyStore:
mspConfigPath: msp ## msp 的本地路径
localMspId: SampleOrg ## Peer 所关联的MSP 的ID
client: ## cli 公共客户端配置选项
connTimeout: 3s ## 连接超时时间
deliveryclient: ## 交付服务配置
reconnectTotalTimeThreshold: 3600s ## 交付服务交付失败后尝试重连的时间
connTimeout: 3s ## 交付服务和 orderer节点的连接超时时间
reConnectBackoffThreshold: 3600s ## 设置连续重试之间的最大延迟
localMspType: bccsp ## 本地MSP类型 (默认为 BCCSP)
profile: ## 是否启用Go自带的profiling 支持进行调试
enabled: false
listenAddress: 0.0.0.0:6060
adminService: ## admin服务用于管理操作,例如控制日志模块严重性等。只有对等管理员才能使用该服务
handlers:
authFilters:
-
name: DefaultAuth
-
name: ExpirationCheck ## 此筛选器检查身份x509证书过期
decorators:
-
name: DefaultDecorator
endorsers:
escc:
name: DefaultEndorsement
library:
validators:
vscc:
name: DefaultValidation
library:
validatorPoolSize: ## 处理交易验证的并发数, 默认是CPU的核数
discovery: ## 客户端使用发现服务来查询有关peers的信息,例如 - 哪些peer已加入某个channel,最新的channel配置是什么,最重要的是 - 给定chaincode和channel,哪些可能的peer满足认可 policy
enabled: true
authCacheEnabled: true
authCacheMaxSize: 1000
authCachePurgeRetentionRatio: 0.75
orgMembersAllowedAccess: false
###############################################################################
#
# vm环境配置,目前主要支持 Docker容器
#
###############################################################################
vm:
endpoint: unix:///var/run/docker.sock ## Docker Daemon 地址,默认是本地 套接字
docker:
tls: ## Docker Daemon 启用TLS时的相关证书配置, 包括信任的根CA证书、服务身份证书、签名私钥等等
enabled: false
ca:
file: docker/ca.crt
cert:
file: docker/tls.crt
key:
file: docker/tls.key
attachStdout: false ## 是否启用绑定到标准输出,启用后 链码容器 的输出消息会绑定到标准输出,方便进行调试
hostConfig: ## Docker 相关的主机配置,包括网络配置、日志、内存等等,这些配置在启动链码容器时进行使用
NetworkMode: host
Dns:
# - 192.168.0.1
LogConfig:
Type: json-file
Config:
max-size: "50m"
max-file: "5"
Memory: 2147483648
###############################################################################
#
# 链码相关配置
#
###############################################################################
chaincode:
id: ## 记录链码相关信息,包括路径、名称、版本等等,该信息会以标签形式写到链码容器
path:
name:
builder: $(DOCKER_NS)/fabric-ccenv:latest ## 通用的本地编译环境,是一个Docker 镜像
pull: false ##
golang: ## Go语言的链码部署生成镜像的基础Docker镜像
runtime: $(BASE_DOCKER_NS)/fabric-baseos:$(ARCH)-$(BASE_VERSION)
dynamicLink: false
car: ## car格式的链码部署生成镜像的基础Docker 镜像
runtime: $(BASE_DOCKER_NS)/fabric-baseos:$(ARCH)-$(BASE_VERSION)
java: ## java语言的基础镜像
Dockerfile: |
from $(DOCKER_NS)/fabric-javaenv:$(ARCH)-1.1.0
node: ## node.js的基础镜像
runtime: $(BASE_DOCKER_NS)/fabric-baseimage:$(ARCH)-$(BASE_VERSION)
startuptimeout: 300s ## 启动链码容器超时,等待超时时间后还没收到链码段的注册消息,则认为启动失败
executetimeout: 30s ## invoke 和 initialize 命令执行超时时间
deploytimeout: ## 部署链码的命令执行超时时间
mode: net ## 执行链码的模式,dev: 允许本地直接运行链码,方便调试; net: 意味着在容器中运行链码
keepalive: 0 ## Peer 和链码之间的心跳超市时间, <= 0 意味着关闭
system: ## 系统链码的相关配置 (系统链码白名单 ??)
cscc: enable
lscc: enable
escc: enable
vscc: enable
qscc: enable
systemPlugins: ## 系统链码插件
logging: ## 链码容器日志相关配置
level: info
shim: warning
format: '%{color}%{time:2006-01-02 15:04:05.000 MST} [%{module}] %{shortfunc} -> %{level:.4s} %{id:03x}%{color:reset} %{message}'
###############################################################################
#
# 账本相关配置
#
###############################################################################
ledger:
blockchain:
state: ## 状态DB的相关配置(包括 golevelDB、couchDB)、DN连接、查询最大返回记录数等
stateDatabase: goleveldb ## stateDB的底层DB配置 (默认golevelDB)
couchDBConfig: ## 如果启用couchdb,配置连接信息 (goleveldb 不需要配置这些)
couchDBAddress: 127.0.0.1:5984
username:
password:
maxRetries: 3 ## 运行时出错重试数
maxRetriesOnStartup: 10 ## 启动时出错的重试数
requestTimeout: 35s ## 请求超时时间
queryLimit: 10000 ## 每个查询最大返回数
maxBatchUpdateSize: 1000 ## 批量更新最大记录数
warmIndexesAfterNBlocks: 1
history:
enableHistoryDatabase: true ## 是否启用历史数据库,默认开启
###############################################################################
#
# 服务度量监控配置
#
###############################################################################
metrics:
enabled: false ## 是否开启监控服务
reporter: statsd
interval: 1s
statsdReporter:
address: 0.0.0.0:8125
flushInterval: 2s
flushBytes: 1432
promReporter: ## prometheus 普罗米修斯服务监听地址
Orderer 配置剖析 orderer.yaml
################################################################################
#
# Orderer的配置
#
################################################################################
General:
LedgerType: file ## 账本类型,支持ram、json、file 三种类型【建议用file】,其中ram保存在内存中;json、file保存在本地文件中 (通常为 /var/hyperledger/production/orderer 下)
ListenAddress: 127.0.0.1 ## 服务监听地址,一般需要制定为服务的特定网络接口地址 或者全网(0.0.0.0)
ListenPort: 7050 ## 服务监听端口 默认7050
TLS: ## 启用TLS 时的相关配置 (grpc 传输)
Enabled: false
PrivateKey: tls/server.key ## Orderer 签名私钥
Certificate: tls/server.crt ## Orderer 身份证书
RootCAs:
- tls/ca.crt ## 根证书
ClientAuthRequired: false ## 是否对客户端也进行认证
ClientRootCAs:
Keepalive: ## 设置GRPC 服务心跳检查
ServerMinInterval: 60s ## 客户端和 orderer 的 最小心跳间隔
ServerInterval: 7200s ## 客户端和 orderer 的心跳间隔时间
ServerTimeout: 20s ## 客户端和 Orderer 的超时时间
LogLevel: info ## 日志等级
## 日志输出格式
LogFormat: '%{color}%{time:2006-01-02 15:04:05.000 MST} [%{module}] %{shortfunc} -> %{level:.4s} %{id:03x}%{color:reset} %{message}'
GenesisMethod: provisional ## 创世块的提供方式 (系统通道初始区块的提供方式,支持 provisional 或者 file;前者根据GenesisProfile 指定默认的 $FABRIC_CFG_PATH/config.yaml 文件中的profile生成;后者使用GenesisFile 指定现成的初始区块文件)
GenesisProfile: SampleInsecureSolo ## 创世块使用的Profile;GenesisMethod: provisional 才有效
GenesisFile: genesisblock ## 使用现成创世块文件时,文件的路径 [创世块的位置] GenesisMethod: file 才有效
LocalMSPDir: msp ## 本地MSP文件的路径 【orderer节点所需的安全认证文件的位置】
LocalMSPID: SampleOrg ## Orderer所关联的MSP的ID MSP管理器用于注册安全认证文件的ID, 此ID必须与配置系统通道和创世区块时(configtx.yaml的OrdererGenesis部分)指定的组织中的某一个组织的ID一致
Profile: ## 为Go pprof性能优化工具启用一个HTTP服务以便作性能分析(https://golang.org/pkg/net/http/pprof)
Enabled: false ## 不启用
Address: 0.0.0.0:6060 ## Go pprof的HTTP服务监听的地址和端口
BCCSP: ## 加密库配置 具体参照Peer 配置
Default: SW
SW:
Hash: SHA2
Security: 256
FileKeyStore:
KeyStore:
Authentication:
TimeWindow: 15m
################################################################################
#
# 基于文件账本配置 (file和json两种类型)
#
################################################################################
FileLedger:
Location: /var/hyperledger/production/orderer ## 指定存放文件的位置,一般为 /var/hyperledger/production/orderer, 该目录下的 chains目录存放各个chain的区块,index目录存放 索引文件 (如果这项不指定, 每次节点重启都将使用一个新的临时位置)
Prefix: hyperledger-fabric-ordererledger ## 如果不指定Location,则在临时目录下创建账本时目录的名称
################################################################################
#
# 基于内存账本配置
#
################################################################################
RAMLedger:
HistorySize: 1000 ## 内存账本所支持存储的区块的数量, 如果内存中存储的区块达到上限, 继续追加区块会导致最旧的区块被丢弃
################################################################################
#
# kafka 集群配置
#
################################################################################
Kafka:
# kafka是一种基于发布/订阅模式的分布式消息系统
# fabric网络中, orderer节点集群组成kafka集群, 客户端是kafka集群的Producer(消息生产者), peer是kafka集群的Consumer(消息消费者)
# kafka集群使用ZooKeeper(分布式应用协调服务)管理集群节点, 选举leader.
Retry: ## 连接时的充实操作 kafka 会利用 sarama 客户端为chennel创建一个producer 负责向kafka 写数据,一个comsumer负责kafka读数据
ShortInterval: 5s ## 操作失败后的快速重试间隔时间
ShortTotal: 10m ## 快速重试阶段最对重试多久
LongInterval: 5m ## 快速充实阶段仍然失败后进入 慢重试阶段,慢重试的时间间隔
LongTotal: 12h ## 慢重试最多重试多久
# https://godoc.org/github.com/Shopify/sarama#Config
NetworkTimeouts: ## Sarama 网络超时时间
DialTimeout: 10s
ReadTimeout: 10s
WriteTimeout: 10s
Metadata: ## kafka集群leader 选举中的metadata 请求参数
RetryBackoff: 250ms ## leader选举过程中元数据请求失败的重试间隔
RetryMax: 3 ## 最大重试次数
Producer: ## 发送消息到kafka集群时的超时
RetryBackoff: 100ms ## 向kafka集群发送消息失败后的重试间隔
RetryMax: 3 ## 最大重试次数
Consumer: ## 从kafka集群接收消息时的超时
RetryBackoff: 2s ## 从kafka集群拉取消息失败后的重试间隔
Verbose: false ## 是否开启kafka的客户端的调试日志 (orderer与kafka集群交互是否生成日)
TLS: ## 与kafka集群的连接启用TLS时的相关配置
Enabled: false ## 是否开启TLS,默认不开启
PrivateKey: ## Orderer 身份签名私钥
# File: ## 私钥文件路径
Certificate: ## kafka的身份证书
# File: ## 证书文件路径
RootCAs: ## 验证kafka证书时的根证书
# File: ## 根证书文件路径
Version: ## kafka的版本
################################################################################
#
# Orderer节点的调试参数
#
################################################################################
Debug:
BroadcastTraceDir: ## 该orderer节点的广播服务请求保存的位置
DeliverTraceDir: ## 该orderer节点的传递服务请求保存的位置
## 以下配置是1.4最新的配置
################################################################################
#
# 操作配置
#
################################################################################
Operations:
# 操作服务地址端口
ListenAddress: 127.0.0.1:8443
# TLS 配置
TLS:
Enabled: false
Certificate:
PrivateKey:
ClientAuthRequired: false
RootCAs: []
################################################################################
#
# 度量配置
#
################################################################################
Metrics:
# 度量提供程序是 prometheus或disabled
Provider: disabled
# statsd 配置
Statsd:
# 网络协议
Network: udp
# 服务地址
Address: 127.0.0.1:8125
# 将本地缓存的计数器和仪表推送到 statsd 的时间间隔;时间被立即推送
WriteInterval: 30s
# 前缀预先添加到所有发出的 statsd 指标
Prefix:
################################################################################
#
# 共识配置
#
################################################################################
Consensus:
# 这里允许的键值对取决于共识插件。对于 etcd/raft,
# 我们使用以下选项:
# WALDir 指定存储 etcd/raft 的Write Ahead Logs的位置。每个channel都有自己的以channelID命名的子目录
WALDir: /var/hyperledger/production/orderer/etcdraft/wal
# SnapDir 指定存储 etcd/raft 快照的位置。每个channel都有自己的以channelID命名的子目录
SnapDir: /var/hyperledger/production/orderer/etcdraft/snapshot
搭建网络核心crypto-config.yaml 配置
crypto-config.yaml 文件
# ---------------------------------------------------------------------------
# "OrdererOrgs"
# ---------------------------------------------------------------------------
OrdererOrgs: ## 定义Orderer组织
- Name: Orderer ## 名称
Domain: example.com ## 组织的命名域
# ---------------------------------------------------------------------------
# "Specs" - 有关完整说明,请参阅下面的PeerOrgs
# ---------------------------------------------------------------------------
Specs:
- Hostname: orderer
# ---------------------------------------------------------------------------
# "PeerOrgs"
# ---------------------------------------------------------------------------
PeerOrgs:
- Name: Org1 ## 名称
Domain: org1.example.com ## 组织的命名域
EnableNodeOUs: true ## 如果设置了EnableNodeOUs,就在msp下生成config.yaml文件
Template: ## 允许定义从模板顺序创建的1个或多个主机。 默认情况下,这看起来像是从0到Count-1的“peer”。 您可以覆盖节点数(Count),起始索引(Start)或用于构造名称的模板(Hostname)。
Count: 1 ## 表示生成几个Peer
# Start: 5
# Hostname: {{.Prefix}}{{.Index}} # default
Users:
Count: 1 ## 表示生成普通User数量
- Name: Org2
Domain: org2.example.com
EnableNodeOUs: true
Template:
Count: 1
Users:
Count: 1
通道及锚节点的配置 configtx.yaml 配置剖析
configtx.yaml 文件
################################################################################
#
# Organizations部分
# 【注意】:本文件中 &KEY 均为 *KEY 所引用; xx:&KEY 均为 <<: *KEY 所引用
################################################################################
Organizations:
## 定义Orderer组织
- &OrdererOrg
Name: OrdererOrg ## Orderer的组织的名称
ID: OrdererMSP ## Orderer 组织的ID (ID是引用组织的关键)
MSPDir: crypto-config/ordererOrganizations/example.com/msp ## Orderer的 MSP 证书目录路径
AdminPrincipal: Role.ADMIN ## 【可选项】 组织管理员所需要的身份,可选项: Role.ADMIN 和 Role.MEMBER
## 定义Peer组织1
- &Org1
Name: Org1MSP ## 组织名称
ID: Org1MSP ## 组织ID
MSPDir: crypto-config/peerOrganizations/org1.example.com/msp ## Peer的MSP 证书目录路径
AnchorPeers: ## 定义组织锚节点 用于跨组织 Gossip 通信
- Host: peer0.org1.example.com ## 锚节点的主机名
Port: 7051 ## 锚节点的端口号
## 定义Peer组织 2
- &Org2
Name: Org2MSP
ID: Org2MSP
MSPDir: crypto-config/peerOrganizations/org2.example.com/msp
AnchorPeers:
- Host: peer0.org2.example.com
Port: 7051
################################################################################
# 本节定义了 fabric 网络的功能.
################################################################################
Capabilities:
## 通道功能适用于orderers and the peers,并且必须得到两者的支持。 将功能的值设置为true.
Global: &ChannelCapabilities
## V1.1 的 Global是一个行为标记,已被确定为运行v1.0.x的所有orderers和peers的行为,但其修改会导致不兼容。 用户应将此标志设置为true.
V1_1: true
## Orderer功能仅适用于orderers,可以安全地操纵,而无需担心升级peers。 将功能的值设置为true
Orderer: &OrdererCapabilities
## Orderer 的V1.1是行为的一个标记,已经确定为运行v1.0.x的所有orderers 都需要,但其修改会导致不兼容。 用户应将此标志设置为true
V1_1: true
## 应用程序功能仅适用于Peer 网络,可以安全地操作,而无需担心升级或更新orderers。 将功能的值设置为true
Application: &ApplicationCapabilities
## V1.2 for Application是一个行为标记,已被确定为运行v1.0.x的所有peers所需的行为,但其修改会导致不兼容。 用户应将此标志设置为true
V1_2: true
################################################################################
#
# 应用通道相关配置,主要包括 参与应用网络的可用组织信息
#
################################################################################
Application: &ApplicationDefaults ## 自定义被引用的地址
Organizations: ## 加入通道的组织信息
################################################################################
#
# Orderer 系统通道相关配置,包括 Orderer 服务配置和参与Orderer 服务的可用组织
# Orderer 默认是 solo 的 且不包含任何组织 【主要被 Profiles 部分引用】
################################################################################
Orderer: &OrdererDefaults ## 自定义被引用的地址
OrdererType: solo ## Orderer 类型,包含 solo 和 kafka 集群
Addresses: ## 服务地址
- orderer.example.com:7050
BatchTimeout: 2s ## 区块打包的最大超时时间 (到了该时间就打包区块)
BatchSize: ## 区块打包的最大包含交易数
MaxMessageCount: 10 ## 一个区块里最大的交易数
AbsoluteMaxBytes: 98 MB ## 一个区块的最大字节数, 任何时候都不能超过
PreferredMaxBytes: 512 KB ## 一个区块的建议字节数,如果一个交易消息的大小超过了这个值, 就会被放入另外一个更大的区块中
MaxChannels: 0 ## 【可选项】 表示Orderer 允许的最大通道数, 默认 0 表示没有最大通道数
Kafka:
Brokers: ## kafka的 brokens 服务地址 允许有多个
- 127.0.0.1:9092
Organizations: ## 参与维护 Orderer 的组织,默认为空
################################################################################
#
# Profile
#
# - 一系列通道配置模板,包括Orderer 系统通道模板 和 应用通道类型模板
#
################################################################################
Profiles:
## Orderer的 系统通道模板 必须包括 Orderer、 Consortiums 两部分
TwoOrgsOrdererGenesis: ## Orderer 系统的通道及创世块配置。通道为默认配置,添加一个OrdererOrg 组织, 联盟为默认的 SampleConsortium 联盟,添加了两个组织 【该名称可以自定义 ??】
Capabilities:
<<: *ChannelCapabilities
Orderer: ## 指定Orderer系统通道自身的配置信息
<<: *OrdererDefaults ## 引用 Orderer 部分的配置 &OrdererDefaults
Organizations:
- *OrdererOrg ## 属于Orderer 的通道组织 该处引用了 【 &OrdererOrg 】位置内容
Capabilities:
<<: *OrdererCapabilities
Consortiums: ## Orderer 所服务的联盟列表
SampleConsortium: ## 创建更多应用通道时的联盟 引用 TwoOrgsChannel 所示
Organizations:
- *Org1
- *Org2
## 应用通道模板 必须包括 Application、 Consortium 两部分
TwoOrgsChannel: ## 应用通道配置。默认配置的应用通道,添加了两个组织。联盟为SampleConsortium
Consortium: SampleConsortium ## 通道所关联的联盟名称
Application: ## 指定属于某应用通道的信息,主要包括 属于通道的组织信息
<<: *ApplicationDefaults
Organizations: ## 初始 加入应用通道的组织
- *Org1
- *Org2
Capabilities:
<<: *ApplicationCapabilities
转载自:https://gitee.com/jonluo/blockchain/tree/master/hyperledger-fabric
Hyperledger Fabric 称为联盟链,是分布式账本技术(DLT),采用模块化架构来提供高度机密性,伸缩性,灵活性和可扩展性。 它旨在支持不同组件的可插拔实现,并适应整个经济生态系统中存在的复杂性和复杂性。
前提安装条件
克隆 hyperledger/fabric-samples
切换到fabric-samples文件夹下
将指定版本的Hyperledger Fabric平台特定二进制文件和配置文件分别安装到fabric-samples存储库的根目录中bin文件夹和config文件夹,和下载指定版本的Hyperledger Fabric docker镜像
构建第一个网络
cd first-network
生成网络工件: ./byfn.sh generate
启动网络: ./byfn.sh up
终止容器,删除加密材料和四个工件,并从Docker Registry中删除链上代码镜像: ./byfn.sh down (这一步一般在重新启动新的联盟链使用)
到此,第一个联盟链搭建成功,因为是自动化脚本构建的,接下来分析细节,手动构建细节:
./byfn.sh generate 执行后的日志如图:
1
,以获取生成将用于crypto-config.yaml文件中定义的网络配置的证书,对应手工配置: ../bin/cryptogen generate --config=./crypto-config.yaml
对应输出日志:
org1.example.com
org2.example.com
证书和密钥(即MSP材料)将输出到 first-network 目录中的 crypto-config 文件夹
2
,告诉 configtxgen 工具在哪里查找配置文件 configtx.yaml 并调用 configtxgen 工具来创建 orderer 创世区块,对应手工配置:export FABRIC_CFG_PATH=$PWD && ../bin/configtxgen -profile TwoOrgsOrdererGenesis -outputBlock ./channel-artifacts/genesis.block
对应输出类似日志:
2018-08-23 10:36:13.825 CST [common/tools/configtxgen] main -> WARN 001 Omitting the channel ID for configtxgen is deprecated. Explicitly passing the channel ID will be required in the future, defaulting to 'testchainid'.
2018-08-23 10:36:13.825 CST [common/tools/configtxgen] main -> INFO 002 Loading configuration
2018-08-23 10:36:13.831 CST [common/tools/configtxgen/encoder] NewChannelGroup -> WARN 003 Default policy emission is deprecated, please include policy specificiations for the channel group in configtx.yaml
2018-08-23 10:36:13.832 CST [common/tools/configtxgen/encoder] NewOrdererGroup -> WARN 004 Default policy emission is deprecated, please include policy specificiations for the orderer group in configtx.yaml
2018-08-23 10:36:13.832 CST [common/tools/configtxgen/encoder] NewOrdererOrgGroup -> WARN 005 Default policy emission is deprecated, please include policy specificiations for the orderer org group OrdererOrg in configtx.yaml
2018-08-23 10:36:13.832 CST [msp] getMspConfig -> INFO 006 Loading NodeOUs
2018-08-23 10:36:13.832 CST [common/tools/configtxgen/encoder] NewOrdererOrgGroup -> WARN 007 Default policy emission is deprecated, please include policy specificiations for the orderer org group Org1MSP in configtx.yaml
2018-08-23 10:36:13.832 CST [msp] getMspConfig -> INFO 008 Loading NodeOUs
2018-08-23 10:36:13.832 CST [common/tools/configtxgen/encoder] NewOrdererOrgGroup -> WARN 009 Default policy emission is deprecated, please include policy specificiations for the orderer org group Org2MSP in configtx.yaml
2018-08-23 10:36:13.832 CST [common/tools/configtxgen] doOutputBlock -> INFO 00a Generating genesis block
2018-08-23 10:36:13.833 CST [common/tools/configtxgen] doOutputBlock -> INFO 00b Writing genesis block
创世区块 genesis.block 将输出到 first-network 目录中的 channel-artifacts 文件夹
3
,创建通道配置文件,对应手工配置:export CHANNEL_NAME=mychannel && ../bin/configtxgen -profile TwoOrgsChannel -outputCreateChannelTx ./channel-artifacts/channel.tx -channelID $CHANNEL_NAME
对应输出类似日志:
2018-08-23 10:55:33.393 CST [common/tools/configtxgen] main -> INFO 001 Loading configuration
2018-08-23 10:55:33.399 CST [common/tools/configtxgen] doOutputChannelCreateTx -> INFO 002 Generating new channel configtx
2018-08-23 10:55:33.399 CST [common/tools/configtxgen/encoder] NewApplicationGroup -> WARN 003 Default policy emission is deprecated, please include policy specificiations for the application group in configtx.yaml
2018-08-23 10:55:33.399 CST [msp] getMspConfig -> INFO 004 Loading NodeOUs
2018-08-23 10:55:33.399 CST [common/tools/configtxgen/encoder] NewApplicationOrgGroup -> WARN 005 Default policy emission is deprecated, please include policy specificiations for the application org group Org1MSP in configtx.yaml
2018-08-23 10:55:33.400 CST [msp] getMspConfig -> INFO 006 Loading NodeOUs
2018-08-23 10:55:33.400 CST [common/tools/configtxgen/encoder] NewApplicationOrgGroup -> WARN 007 Default policy emission is deprecated, please include policy specificiations for the application org group Org2MSP in configtx.yaml
2018-08-23 10:55:33.401 CST [common/tools/configtxgen] doOutputChannelCreateTx -> INFO 008 Writing new channel tx
通道配置文件 channel.tx 将输出到 first-network 目录中的 channel-artifacts 文件夹
4
,构建的通道上为Org1组织锚节点配置文件,对应手工配置:../bin/configtxgen -profile TwoOrgsChannel -outputAnchorPeersUpdate ./channel-artifacts/Org1MSPanchors.tx -channelID $CHANNEL_NAME -asOrg Org1MSP
对应输出类似日志:
2018-08-23 11:07:49.817 CST [common/tools/configtxgen] main -> INFO 001 Loading configuration
2018-08-23 11:07:49.823 CST [common/tools/configtxgen] doOutputAnchorPeersUpdate -> INFO 002 Generating anchor peer update
2018-08-23 11:07:49.823 CST [common/tools/configtxgen] doOutputAnchorPeersUpdate -> INFO 003 Writing anchor peer update
通道上为Org1定义锚对等节点配置文件 Org1MSPanchors.tx 将输出到 first-network 目录中的 channel-artifacts 文件夹
5
,构建的通道上为Org2组织锚节点配置文件,对应手工配置:../bin/configtxgen -profile TwoOrgsChannel -outputAnchorPeersUpdate ./channel-artifacts/Org2MSPanchors.tx -channelID $CHANNEL_NAME -asOrg Org2MSP
对应输出类似日志:
2018-08-23 11:10:02.486 CST [common/tools/configtxgen] main -> INFO 001 Loading configuration
2018-08-23 11:10:02.493 CST [common/tools/configtxgen] doOutputAnchorPeersUpdate -> INFO 002 Generating anchor peer update
2018-08-23 11:10:02.493 CST [common/tools/configtxgen] doOutputAnchorPeersUpdate -> INFO 003 Writing anchor peer upda
通道上为Org2定义锚对等节点配置文件 Org2MSPanchors.tx 将输出到 first-network 目录中的 channel-artifacts 文件夹
./byfn.sh up 执行后的日志可以分为两部分:
第一部分
Creating network "net_byfn" with the default driver
Creating volume "net_orderer.example.com" with default driver
Creating volume "net_peer0.org1.example.com" with default driver
Creating volume "net_peer1.org1.example.com" with default driver
Creating volume "net_peer0.org2.example.com" with default driver
Creating volume "net_peer1.org2.example.com" with default driver
Creating peer0.org2.example.com ... done
Creating orderer.example.com ... done
Creating peer1.org1.example.com ... done
Creating peer1.org2.example.com ... done
Creating peer0.org1.example.com ... done
Creating cli ... done
这部分其实是利用 docker-compose 启动容器编排,具体命令为:
docker-compose -f docker-compose-cli.yaml up -d
第二部分
____ _____ _ ____ _____
/ ___| |_ _| / \ | _ \ |_ _|
\___ \ | | / _ \ | |_) | | |
___) | | | / ___ \ | _ < | |
|____/ |_| /_/ \_\ |_| \_\ |_|
Build your first network (BYFN) end-to-end test
Channel name : mychannel
Creating channel...
+ peer channel create -o orderer.example.com:7050 -c mychannel -f ./channel-artifacts/channel.tx --tls true --cafile /opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-cert.pem
+ res=0
+ set +x
2018-08-23 04:18:50.971 UTC [channelCmd] InitCmdFactory -> INFO 001 Endorser and orderer connections initialized
2018-08-23 04:18:50.985 UTC [cli/common] readBlock -> INFO 002 Got status: &{NOT_FOUND}
2018-08-23 04:18:50.987 UTC [channelCmd] InitCmdFactory -> INFO 003 Endorser and orderer connections initialized
2018-08-23 04:18:51.193 UTC [cli/common] readBlock -> INFO 004 Received block: 0
===================== Channel 'mychannel' created =====================
Having all peers join the channel...
+ peer channel join -b mychannel.block
+ res=0
+ set +x
2018-08-23 04:18:51.282 UTC [channelCmd] InitCmdFactory -> INFO 001 Endorser and orderer connections initialized
2018-08-23 04:18:51.386 UTC [channelCmd] executeJoin -> INFO 002 Successfully submitted proposal to join channel
===================== peer0.org1 joined channel 'mychannel' =====================
+ peer channel join -b mychannel.block
+ res=0
+ set +x
2018-08-23 04:18:54.468 UTC [channelCmd] InitCmdFactory -> INFO 001 Endorser and orderer connections initialized
2018-08-23 04:18:54.577 UTC [channelCmd] executeJoin -> INFO 002 Successfully submitted proposal to join channel
===================== peer1.org1 joined channel 'mychannel' =====================
+ peer channel join -b mychannel.block
+ res=0
+ set +x
2018-08-23 04:18:57.680 UTC [channelCmd] InitCmdFactory -> INFO 001 Endorser and orderer connections initialized
2018-08-23 04:18:57.790 UTC [channelCmd] executeJoin -> INFO 002 Successfully submitted proposal to join channel
===================== peer0.org2 joined channel 'mychannel' =====================
+ peer channel join -b mychannel.block
+ res=0
+ set +x
2018-08-23 04:19:00.881 UTC [channelCmd] InitCmdFactory -> INFO 001 Endorser and orderer connections initialized
2018-08-23 04:19:00.991 UTC [channelCmd] executeJoin -> INFO 002 Successfully submitted proposal to join channel
===================== peer1.org2 joined channel 'mychannel' =====================
Updating anchor peers for org1...
+ peer channel update -o orderer.example.com:7050 -c mychannel -f ./channel-artifacts/Org1MSPanchors.tx --tls true --cafile /opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-cert.pem
+ res=0
+ set +x
2018-08-23 04:19:04.082 UTC [channelCmd] InitCmdFactory -> INFO 001 Endorser and orderer connections initialized
2018-08-23 04:19:04.089 UTC [channelCmd] update -> INFO 002 Successfully submitted channel update
===================== Anchor peers updated for org 'Org1MSP' on channel 'mychannel' =====================
Updating anchor peers for org2...
+ peer channel update -o orderer.example.com:7050 -c mychannel -f ./channel-artifacts/Org2MSPanchors.tx --tls true --cafile /opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-cert.pem
+ res=0
+ set +x
2018-08-23 04:19:07.175 UTC [channelCmd] InitCmdFactory -> INFO 001 Endorser and orderer connections initialized
2018-08-23 04:19:07.183 UTC [channelCmd] update -> INFO 002 Successfully submitted channel update
===================== Anchor peers updated for org 'Org2MSP' on channel 'mychannel' =====================
Installing chaincode on peer0.org1...
+ peer chaincode install -n mycc -v 1.0 -l golang -p github.com/chaincode/chaincode_example02/go/
+ res=0
+ set +x
2018-08-23 04:19:10.273 UTC [chaincodeCmd] checkChaincodeCmdParams -> INFO 001 Using default escc
2018-08-23 04:19:10.273 UTC [chaincodeCmd] checkChaincodeCmdParams -> INFO 002 Using default vscc
2018-08-23 04:19:10.401 UTC [chaincodeCmd] install -> INFO 003 Installed remotely response:<status:200 payload:"OK" >
===================== Chaincode is installed on peer0.org1 =====================
Install chaincode on peer0.org2...
+ peer chaincode install -n mycc -v 1.0 -l golang -p github.com/chaincode/chaincode_example02/go/
+ res=0
+ set +x
2018-08-23 04:19:10.461 UTC [chaincodeCmd] checkChaincodeCmdParams -> INFO 001 Using default escc
2018-08-23 04:19:10.461 UTC [chaincodeCmd] checkChaincodeCmdParams -> INFO 002 Using default vscc
2018-08-23 04:19:10.573 UTC [chaincodeCmd] install -> INFO 003 Installed remotely response:<status:200 payload:"OK" >
===================== Chaincode is installed on peer0.org2 =====================
Instantiating chaincode on peer0.org2...
+ peer chaincode instantiate -o orderer.example.com:7050 --tls true --cafile /opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-cert.pem -C mychannel -n mycc -l golang -v 1.0 -c '{"Args":["init","a","100","b","200"]}' -P 'AND ('\''Org1MSP.peer'\'','\''Org2MSP.peer'\'')'
+ res=0
+ set +x
2018-08-23 04:19:10.634 UTC [chaincodeCmd] checkChaincodeCmdParams -> INFO 001 Using default escc
2018-08-23 04:19:10.634 UTC [chaincodeCmd] checkChaincodeCmdParams -> INFO 002 Using default vscc
===================== Chaincode is instantiated on peer0.org2 on channel 'mychannel' =====================
Querying chaincode on peer0.org1...
===================== Querying on peer0.org1 on channel 'mychannel'... =====================
Attempting to Query peer0.org1 ...3 secs
+ peer chaincode query -C mychannel -n mycc -c '{"Args":["query","a"]}'
+ res=0
+ set +x
100
===================== Query successful on peer0.org1 on channel 'mychannel' =====================
Sending invoke transaction on peer0.org1 peer0.org2...
+ peer chaincode invoke -o orderer.example.com:7050 --tls true --cafile /opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-cert.pem -C mychannel -n mycc --peerAddresses peer0.org1.example.com:7051 --tlsRootCertFiles /opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/tls/ca.crt --peerAddresses peer0.org2.example.com:7051 --tlsRootCertFiles /opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org2.example.com/peers/peer0.org2.example.com/tls/ca.crt -c '{"Args":["invoke","a","b","10"]}'
+ res=0
+ set +x
2018-08-23 04:19:31.656 UTC [chaincodeCmd] chaincodeInvokeOrQuery -> INFO 001 Chaincode invoke successful. result: status:200
===================== Invoke transaction successful on peer0.org1 peer0.org2 on channel 'mychannel' =====================
Installing chaincode on peer1.org2...
+ peer chaincode install -n mycc -v 1.0 -l golang -p github.com/chaincode/chaincode_example02/go/
+ res=0
+ set +x
2018-08-23 04:19:31.708 UTC [chaincodeCmd] checkChaincodeCmdParams -> INFO 001 Using default escc
2018-08-23 04:19:31.708 UTC [chaincodeCmd] checkChaincodeCmdParams -> INFO 002 Using default vscc
2018-08-23 04:19:31.815 UTC [chaincodeCmd] install -> INFO 003 Installed remotely response:<status:200 payload:"OK" >
===================== Chaincode is installed on peer1.org2 =====================
Querying chaincode on peer1.org2...
===================== Querying on peer1.org2 on channel 'mychannel'... =====================
+ peer chaincode query -C mychannel -n mycc -c '{"Args":["query","a"]}'
Attempting to Query peer1.org2 ...3 secs
+ res=0
+ set +x
90
===================== Query successful on peer1.org2 on channel 'mychannel' =====================
========= All GOOD, BYFN execution completed ===========
_____ _ _ ____
| ____| | \ | | | _ \
| _| | \| | | | | |
| |___ | |\ | | |_| |
|_____| |_| \_| |____/
这部分其实是利用 docker exec 命令 进入 cli 容器中执行 scripts/script.sh 脚本,其参数为 mychannel 3 golang 10 false,具体命令为:
docker exec cli scripts/script.sh mychannel 3 golang 10 false
接下来,继续细分 docker exec cli scripts/script.sh mychannel 3 golang 10 false 这个命令等同于以下操作:
首先进入 cli 容器:
docker exec -it cli bash
接下来在容器里操作,配置环境变量:
export CORE_PEER_MSPCONFIGPATH=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org1.example.com/users/Admin@org1.example.com/msp
export CORE_PEER_ADDRESS=peer0.org1.example.com:7051
export CORE_PEER_LOCALMSPID="Org1MSP"
export CORE_PEER_TLS_ROOTCERT_FILE=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/tls/ca.crt
创建 mychannel 通道(相当于通过创世区块创建区块链,每个通道相当于每条独立的区块链):
export CHANNEL_NAME=mychannel
peer channel create -o orderer.example.com:7050 -c $CHANNEL_NAME -f ./channel-artifacts/channel.tx --tls --cafile /opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-cert.pem
输出日志:
2018-08-23 06:56:14.257 UTC [channelCmd] InitCmdFactory -> INFO 001 Endorser and orderer connections initialized
2018-08-23 06:56:14.273 UTC [cli/common] readBlock -> INFO 002 Got status: &{NOT_FOUND}
2018-08-23 06:56:14.274 UTC [channelCmd] InitCmdFactory -> INFO 003 Endorser and orderer connections initialized
2018-08-23 06:56:14.480 UTC [cli/common] readBlock -> INFO 004 Received block: 0
节点加入 mychannel 通道(相当于节点加入区块链网络):
加入通道需要用到环境变量的值,默认为 peer0.org1 节点加入通道
peer channel join -b mychannel.block
输出日志:
2018-08-23 07:10:09.620 UTC [channelCmd] InitCmdFactory -> INFO 001 Endorser and orderer connections initialized
2018-08-23 07:10:09.729 UTC [channelCmd] executeJoin -> INFO 002 Successfully submitted proposal to join channel
要其他节点也加入 mychannel 通道,需要修改环境变量的值,也很简单,举个例子,如果 peer1.org2 节点加入通道,只要把所有环境变量值出现 org1 替换成 org2 ,并把 CORE_PEER_ADDRESS值中的 peer0 替换成 peer1 ,如下:
CORE_PEER_MSPCONFIGPATH=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org2.example.com/users/Admin@org2.example.com/msp
CORE_PEER_ADDRESS=peer1.org2.example.com:7051
CORE_PEER_LOCALMSPID="Org2MSP"
CORE_PEER_TLS_ROOTCERT_FILE=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org2.example.com/peers/peer0.org2.example.com/tls/ca.crt
修改后继续执行:peer channel join -b mychannel.block,同理完成 peer0.org2,peer1.org1,peer1.org2 加入 mychannel 通道
更新通道的锚节点,实质上是在通道的创世块之上添加了额外的配置信息(所谓锚节点就是某联盟在通道中公开链接的一个或多个节点)
更新通道中 Org1 组织的锚节点为 peer0.org1.example.com:
首先确保环境变量是 peer0.org1 的信息:
CORE_PEER_MSPCONFIGPATH=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org1.example.com/users/Admin@org1.example.com/msp
CORE_PEER_ADDRESS=peer0.org1.example.com:7051
CORE_PEER_LOCALMSPID="Org1MSP"
CORE_PEER_TLS_ROOTCERT_FILE=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/tls/ca.crt
然后更新
peer channel update -o orderer.example.com:7050 -c $CHANNEL_NAME -f ./channel-artifacts/Org1MSPanchors.tx --tls --cafile /opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-cert.pem
更新通道中 Org2 组织的锚节点为 peer0.org2.example.com:
首先确保环境变量是 peer0.org2 的信息:
CORE_PEER_MSPCONFIGPATH=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org2.example.com/users/Admin@org2.example.com/msp
CORE_PEER_ADDRESS=peer0.org2.example.com:7051
CORE_PEER_LOCALMSPID="Org2MSP"
CORE_PEER_TLS_ROOTCERT_FILE=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org2.example.com/peers/peer0.org2.example.com/tls/ca.crt
然后更新
peer channel update -o orderer.example.com:7050 -c $CHANNEL_NAME -f ./channel-artifacts/Org2MSPanchors.tx --tls --cafile /opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-cert.pem
安装和实例化Chaincode
安装 golang版 Chaincode ,安装到的节点为环境变量的配置节点:
peer chaincode install -n mycc -v 1.0 -p github.com/chaincode/chaincode_example02/go/
日志输出:
2018-08-23 11:25:20.439 UTC [chaincodeCmd] checkChaincodeCmdParams -> INFO 001 Using default escc
2018-08-23 11:25:20.439 UTC [chaincodeCmd] checkChaincodeCmdParams -> INFO 002 Using default vscc
2018-08-23 11:25:20.831 UTC [chaincodeCmd] install -> INFO 003 Installed remotely response:<status:200 payload:"OK" >
接下来,在通道上实例化链码。这将初始化通道上的链代码,设置链代码的认可策略,并为目标节点启动链代码容器:
peer chaincode instantiate -o orderer.example.com:7050 --tls --cafile /opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-cert.pem -C $CHANNEL_NAME -n mycc -v 1.0 -c '{"Args":["init","a", "100", "b","200"]}' -P "AND ('Org1MSP.peer','Org2MSP.peer')"
日志输出:
2018-08-23 11:31:33.050 UTC [chaincodeCmd] checkChaincodeCmdParams -> INFO 001 Using default escc
2018-08-23 11:31:33.050 UTC [chaincodeCmd] checkChaincodeCmdParams -> INFO 002 Using default vscc
查询以确保链代码已正确实例化并填充状态数据库
peer chaincode query -C $CHANNEL_NAME -n mycc -c '{"Args":["query","a"]}'
日志输出:
100
调用,a取10给b
peer chaincode invoke -o orderer.example.com:7050 --tls true --cafile /opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-cert.pem -C $CHANNEL_NAME -n mycc --peerAddresses peer0.org1.example.com:7051 --tlsRootCertFiles /opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/tls/ca.crt --peerAddresses peer0.org2.example.com:7051 --tlsRootCertFiles /opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org2.example.com/peers/peer0.org2.example.com/tls/ca.crt -c '{"Args":["invoke","a","b","10"]}'
输出
INFO 001 Chaincode invoke successful. result: status:200
查询结果得到: a:90,b:210,成功结束
联盟链新增组织 Org3 :./eyfn.sh up
../../bin/cryptogen generate --config=./org3-crypto.yaml
export FABRIC_CFG_PATH=$PWD && ../../bin/configtxgen -printOrg Org3MSP > ../channel-artifacts/org3.json
cd ../ && cp -r crypto-config/ordererOrganizations org3-artifacts/crypto-config/
docker exec -it cli bash
export ORDERER_CA=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-cert.pem && export CHANNEL_NAME=mychannel
peer channel fetch config config_block.pb -o orderer.example.com:7050 -c $CHANNEL_NAME --tls --cafile $ORDERER_CA
configtxlator proto_decode --input config_block.pb --type common.Block | jq .data.data[0].payload.data.config > config.json
花一点时间在选择的文本编辑器(或浏览器)中打开此文件。值得研究,因为它揭示了底层配置结构和可以进行的其他类型的通道更新
jq -s '.[0] * {"channel_group":{"groups":{"Application":{"groups": {"Org3MSP":.[1]}}}}}' config.json ./channel-artifacts/org3.json > modified_config.json
configtxlator proto_encode --input config.json --type common.Config --output config.pb
configtxlator proto_encode --input modified_config.json --type common.Config --output modified_config.pb
configtxlator compute_update --channel_id $CHANNEL_NAME --original config.pb --updated modified_config.pb --output org3_update.pb
configtxlator proto_decode --input org3_update.pb --type common.ConfigUpdate | jq . > org3_update.json
echo '{"payload":{"header":{"channel_header":{"channel_id":"mychannel", "type":2}},"data":{"config_update":'$(cat org3_update.json)'}}}' | jq . > org3_update_in_envelope.json
configtxlator proto_encode --input org3_update_in_envelope.json --type common.Envelope --output org3_update_in_envelope.pb
peer channel signconfigtx -f org3_update_in_envelope.pb
export CORE_PEER_LOCALMSPID="Org2MSP"
export CORE_PEER_TLS_ROOTCERT_FILE=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org2.example.com/peers/peer0.org2.example.com/tls/ca.crt
export CORE_PEER_MSPCONFIGPATH=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org2.example.com/users/Admin@org2.example.com/msp
export CORE_PEER_ADDRESS=peer0.org2.example.com:7051
peer channel update -f org3_update_in_envelope.pb -c $CHANNEL_NAME -o orderer.example.com:7050 --tls --cafile $ORDERER_CA
CORE_PEER_GOSSIP_USELEADERELECTION=true
CORE_PEER_GOSSIP_ORGLEADER=false
docker-compose -f docker-compose-org3.yaml up -d
docker exec -it Org3cli bash
export ORDERER_CA=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-cert.pem && export CHANNEL_NAME=mychannel
peer channel join -b mychannel.block
peer chaincode install -n mycc -v 2.0 -p github.com/chaincode/chaincode_example02/go/
peer chaincode install -n mycc -v 2.0 -p github.com/chaincode/chaincode_example02/go/
升级
peer chaincode upgrade -o orderer.example.com:7050 --tls $CORE_PEER_TLS_ENABLED --cafile $ORDERER_CA -C $CHANNEL_NAME -n mycc -v 2.0 -c '{"Args":["init","a","90","b","210"]}' -P "OR ('Org1MSP.peer','Org2MSP.peer','Org3MSP.peer')"
peer chaincode query -C $CHANNEL_NAME -n mycc -c '{"Args":["query","a"]}'
如果使用过该 eyfn.sh 脚本,则需要关闭网络。这可以通过:./eyfn.sh down
利用 fabric-samples/fabric-ca 进行搭建
cd fabric-ca
首先下载镜像: ./bootstrap.sh
运行:./start.sh
完成搭建
接下来分析细节,仔细分析start.sh脚本文件
#!/bin/bash
set -e
SDIR=$(dirname "$0")
# 引入环境变量
source ${SDIR}/scripts/env.sh
cd ${SDIR}
# 删除docker容器
dockerContainers=$(docker ps -a | awk '$2~/hyperledger/ {print $1}')
if [ "$dockerContainers" != "" ]; then
log "Deleting existing docker containers ..."
docker rm -f $dockerContainers > /dev/null
fi
# 删除链码docker镜像
chaincodeImages=`docker images | grep "^dev-peer" | awk '{print $3}'`
if [ "$chaincodeImages" != "" ]; then
log "Removing chaincode docker images ..."
docker rmi -f $chaincodeImages > /dev/null
fi
# 准备一个空文件夹
DDIR=${SDIR}/${DATA}
if [ -d ${DDIR} ]; then
log "Cleaning up the data directory from previous run at $DDIR"
rm -rf ${SDIR}/data
fi
mkdir -p ${DDIR}/logs
# 创建docker-compose.yml文件
${SDIR}/makeDocker.sh
# 根据生成的docker-compose.yml文件启动docker容器编排
log "Creating docker containers ..."
docker-compose up -d
# 等待名为 setup 容器完成
dowait "the 'setup' container to finish registering identities, creating the genesis block and other artifacts" 90 $SDIR/$SETUP_LOGFILE $SDIR/$SETUP_SUCCESS_FILE
# 等待名为 run 容器启动,然后打印它的结束日志
dowait "the docker 'run' container to start" 60 ${SDIR}/${SETUP_LOGFILE} ${SDIR}/${RUN_SUMFILE}
tail -f ${SDIR}/${RUN_SUMFILE}&
TAIL_PID=$!
# 等待名为 run 容器完成,然后结束
while true; do
if [ -f ${SDIR}/${RUN_SUCCESS_FILE} ]; then
kill -9 $TAIL_PID
exit 0
elif [ -f ${SDIR}/${RUN_FAIL_FILE} ]; then
kill -9 $TAIL_PID
exit 1
else
sleep 1
fi
done
转载自:https://gitee.com/jonluo/blockchain/blob/master/hyperledger-fabric/README.md