{"id":30972825,"url":"https://github.com/wulusai2333/linuxstudy","last_synced_at":"2026-05-18T15:02:29.657Z","repository":{"id":105413255,"uuid":"242284925","full_name":"wulusai2333/linuxstudy","owner":"wulusai2333","description":"linux相关语法 fabric练习","archived":false,"fork":false,"pushed_at":"2020-11-02T01:04:04.000Z","size":202,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"master","last_synced_at":"2025-09-12T04:03:12.654Z","etag":null,"topics":["fabric","linux-shell"],"latest_commit_sha":null,"homepage":"","language":"Go","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/wulusai2333.png","metadata":{"files":{"readme":"Readme.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2020-02-22T05:23:22.000Z","updated_at":"2021-02-20T07:45:00.000Z","dependencies_parsed_at":"2023-03-13T14:44:55.490Z","dependency_job_id":null,"html_url":"https://github.com/wulusai2333/linuxstudy","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/wulusai2333/linuxstudy","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/wulusai2333%2Flinuxstudy","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/wulusai2333%2Flinuxstudy/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/wulusai2333%2Flinuxstudy/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/wulusai2333%2Flinuxstudy/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/wulusai2333","download_url":"https://codeload.github.com/wulusai2333/linuxstudy/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/wulusai2333%2Flinuxstudy/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":33181755,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-18T09:27:30.708Z","status":"ssl_error","status_checked_at":"2026-05-18T09:27:28.300Z","response_time":71,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.5:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["fabric","linux-shell"],"created_at":"2025-09-12T03:22:44.383Z","updated_at":"2026-05-18T15:02:29.619Z","avatar_url":"https://github.com/wulusai2333.png","language":"Go","funding_links":[],"categories":[],"sub_categories":[],"readme":"\n\n### fabric环境搭建(基于ubuntu)\n\n#### 准备工作\n\n```\n官方帮助文档\n安装curl\n安装docker\n安装docker-compose\n安装go\n安装node.js\n安装python 2.7版本以上\ngit\ngit clone -b release-1.4 https://github.com/hyperledger/fabric.git\nGO111MODULE=on go mod init bhxy\nGO111MODULE=on go build\n```\n\n\n\n#### 1.安装和更新基础软件\n\n```shell\nsudo apt-get update\nsudo apt-get install apt-transport-https ca-certificates curl git software-properties-common lrzsz -y\n#添加阿里的docker镜像仓库\napt-get install docker-ce -y\n#用非root用户操作是可能权限不足 当前用户加入docker组中\nsudo gpasswd -a ${USER} docker\nsystemctl restart docker\nnewgrp - docker #当前用户切换docker群组\nsudo docker version\n#装docker-compose\nsudo apt-get install python-pip -y\nsudo pip install docker-compose\nsudo docker-compose version\n#安装go\nwget go安装包\ntar zxvf go安装包 -C /use/local\nmkdir $HOME/go\nvim ~/.bashrc\n\texport GOROOT=/user/local/go\n\texport GOPATH=$HOME/go\n\texport PATH=$PATH:$GOROOT/bin:$GOPATH/bin\n#使环境变量生效\nsource ~/.bashrc\n. ~/.bashrc #对当前用户生效\ngo version\n安装mode.js\nwget 安装包\n#解压 /opt\nsudo tar -xvf 安装包 -C /opt\nsudo vim /etc/profile\n\texport NODEJS_HOME=/opt/node\n\texport PATH=$PATH:$NODEJS_HOME/bin\n. /etc/profile #对操作系统生效\nnode -v\n\n```\n\n#### 2.安装fabric-sample\n\n```shell\n#需要注意fabric项目安装位置在GOPATH的src目录下github.com/hyperledger/\n#可以使用git clone拉取项目\n#或者参考fabric官方文档使用curl 下载 bootstrap.sh\n#下载过程中 hyperledger-fabric-ca-amd64-1.4.4.tar.gz hyperledger-fabric-ca-amd64-1.4.4.tar.gz 这两个包下载极慢,可以直接将此包放到fabric-sample中减少下载时间\n#拉取镜像\nfabric-peer #peer模块镜像\nfabric-orderer #order节点\nfabric-ccenv #chaincode运行环境库\nfabric-tools #工具镜像包含cryptogen,configtxgen\nfabric-ca #ca模块\nfabric-couchdb #couchdb数据库\nfabric-kafka \nfabric-zookeeper\n#镜像位置\n/var/lib/docker/image\n#fabric-sample 的bin目录加载到环境变量中,参考node.js\n./bysh.sh generate #生成证书文件\n./bysh.sh up #启动\n./bysh.sh down#关闭\n```\n\n3.一些概念\n\ntls -\u003e ssl  https 都是加密的,节点间需要证书\n\n#### 逻辑架构\n\n```shell\n#程序员需要做的\n身份管理inentity\t-\u003e成员服务membership\t-\u003e注册登录enroliment 属性证书attributes\t\t\n\n账本管理ledger\t\t-\u003e|\n\t\t\t\t\t共识服务consensus -\u003e 分布式账本 排序服务\tP2P协议 背书验证\n交易管理transcations-\u003e| \t\t\n\n智能合约smart contract\t-\u003e链码服务chaincode -\u003e安全容器环境 安全镜像仓库\n#程序员需要做的是最前面的一层 智能合约是最简单的\n```\n\n##### 成员管理\n\n```\n会员注册\n\t注册成功的一个账户得到的不是用户名密码 是一个证书\n\t使用证书做身份认证\n身份保护\n\n交易审计\n\n内容保密\n\t可以多条区块链,通过通道区分\n\n```\n\n##### 账本管理\n\n```\n区块链\n\t保存所有交易了记录\n世界状态\n\t数据最新状态\n\t数据存储在当前节点的数据库中 默认levelDB\n\n```\n\n##### 交易管理\n\n```\n部署交易\n\t部署的是链码,就是给节点安装链码\n调用交易\n\tinvoke\n```\n\n#### 基础概念\n\n##### 组织\n\n``` \n-\u003e社会实体\n组织中:\n有用户\n进行数据处理的节点\nput 写入数据到区块链中\nget 数据查询\n```\n\n##### 节点\n\n```\nclient \n\t进行交易管理(cli node sdk,java sdk)\n\tcli -\u003e通过linux命令行进行操作,使用的是shell命令对数据进行提交和查询\n\tnode.js -\u003eapi实现客户端 提供服务,浏览器查询\n\tjava-\u003e 同上\n\tgo-\u003e 同上\npeer\n\t存储和同步账本数据\n\t用户通过客户端工具对数据进行put操作,数据写入到一个节点中\n\t数据同步是fabric框架实现的\norderer\n\t排序和分发交易\n\t交易数据线打包再写入到区块中\n```\n\n##### 通道\n\n``` \n-\u003eQQ群 只有在同一个群中才能看到一个群的消息\nconsensus server:orderer节点\npeer节点加入一个通道就要创一个区块链\n```\n\n交易流程\n\n```\n1.Application/SDK 充当客户端\n2.客户端发起一个提案,给peer节点\n3.peer节点预演,得到一个结果\n4.peer节点将交易结果发送给客户端\n\t如果模拟交易失败,流程终止\n\t成功继续\n5.客户端将交易提交给排序节点\n6.排序节点对交易打包\n7.orderer节点将打包数据发送给peer,peer节点将数据写入搭配区块中\n\t打包数据的发送,不是实时的\n\t有设定条件,在配置文件中\n背书策略:\n\t完成一笔交易的过程就是背书\n```\n\n思考:\n\n站在普通人的角度看Application/SDK 实际是后台服务器\n\n交易通过 手机APP/浏览器(终端) --发送-\u003e  Application/SDK(后台服务器)处理请求 --\u003epee背书节点--\u003e后台应用服务器(确认验证成功)  --\u003e orderer节点排序打包区块 --\u003e peer主节点存储分发区块\n\n#### fabric核心模块\n\n```\npeer 主节点模块,负责存储区块链数据,运行维护链码\norderer 交易打包,排序模块\ncrytogen 组织和证书生成模块\nconfigtxgen 区块和交易生成模块\nconfigtxlator 区块和交易解析模块 -\u003e解析成json格式\n```\n\n#### cryptogen命令生成证书文件\n\n```shell\ncrptogen showtemplate \u003e crypto-config.yaml #生成模板配置文件\n#修改配置文件内容\ncryptogen generate --config=crypto-config.yaml #根据指定配置文件生成证书\n```\n\nmsp 是什么?\n\n账号\n\n​\t谁有msp\n\n​\t\t每个节点都有一个msp账号\n\n​\t\t每个用户都有msp账号\n\n#### 创世块文件和通道文件生成\n\n```shell\n#需要从fabric-sample/first-network下复制configtx.yaml并修改\n#已知Capabilities规则修改会导致创建通道失败\nconfigtxgen --help\n\t-outputBlock string #输出创世区块文件的路径和名字\n\t-channelID string #指定channel名字,没有用默认\n\t-outputCreateChannelTx string #输出通道文件的路径和名字\n\t-profile string #指定配置文件中的节点\n\t-outputAnchorPeersUpdate string #更新channel配置信息\n\t-asOrg string #指定所属的组织名称\n#执行这个命令需要configtx.yaml 可以复制fabric-sample/first-network下的\n#引用配置文件的参数生成创世区块 后面是生成文件的路径\nconfigtxgen -profile TwoOrgsOrdererGenesis -outputBlock ./channel-artifacts/genesis.block -channelID wulusaichannel\n#创建目录放区块文件\nmkdir channel-artifacts\n#生成通道文件\nconfigtxgen -profile TwoOrgsChannel -outputCreateChannelTx ./channel-artifacts/channel.tx -channelID wulusaichannel\n#锚节点更新文件 这个操作可选 这个操作主要用来想更换锚节点时使用\nconfigtxgen -profile TwoOrgsChannel -outputAnchorPeersUpdate ./channel-artifacts/Org1MSPanchors.tx -channelID wulusaichannel -asOrg Org1MSP\n#---asOrg:锚节点的组织名\nconfigtxgen -profile TwoOrgsChannel -outputAnchorPeersUpdate ./channel-artifacts/Org2MSPanchors.tx -channelID wulusaichannel -asOrg Org2MSP\n```\n\n\n\npeer中四种节点的角色和作用\n\n```\nanchor 锚节点 组织与其他组织通信的节点\nleader 领导节点 组织与orderer通信的节点\ncommit 提交节点 把数据写入到区块链中\n背书节点 模拟交易\n```\n\n修改 各节点容器的docker-compose 配置文件\n\ndocker-compose\n\n```shell\n#启动 守护进程\ndocker-compose -f docker-compose-cli.yaml up -d \n#所有容器 up状态为up 且有端口映射才算成功\nset IMAGE_TAG=latest  \nset COMPOSE_PROJECT_NAME=wulusai #设置为空 则 容器网络等于 _byfn\n#创建的网络则是当前目录名 + _byfn\ndocker-compose up -d \ndocker-compose -f docker-compose-cli.yaml ps #查看启动状态\n#如果容器状态正常就可以进入cli操作了\n#删除容器\ndocker rm `docker ps -aq` -f\n```\n\n#### cli容器操作节点\n\n```shell\n步骤总结:\n\t先用orderer的证书创建通道\n\t设置环境变量peer0.org1 加入通道\n\t设置环境变量peer0.org2 加入通道\n\t对应环境下更新锚节点(如果锚节点不变这步可以不要)\n\t对应环境install链码\n\t初始化链码 使用orderer证书\n\tinvoke调用 orderer证书使用两个锚节点证书,指定通道\n\tquery查询\n示例:\n\t#创建通道\npeer channel create -o orderer地址:7050 -c 通道名 -f 通道文件 --tls true --cafile orderer节点pem证书文件绝对路径\n\t#加入通道\npeer channel join -b wulusaichannel.block\t\n\t#更新锚节点\npeer channel update -o orderer节点地址:端口 -c 通道名 -f 锚节点更新文件 --tls true --cafile orderer节点pem格式证书文件\n\t#安装链码\npeer chaincode install -n 链码名字 -v 链码版本 -l 链码语言 -p 链码位置\n\t#初始化\npeer chaincode instantiate -o orderer节点地址:端口 -tls true -cafile orderer节点pem格式证书文件 -C 通道名称 -n 链码名称 -l 链码语言 -v 链码版本 -c 链码init函数调用 -P 背书策略\n\t#invoke调用\npeer chaincode invoke  -n 链码名字 -c '{\"Args\":[\"userRegister\", \"2\", \"user1\"]}' -o orderer节点地址:端口 --tls true --cafile orderer节点pem格式证书文件 -C wulusaichannel --peerAddresses org1背书节点:端口 --tlsRootCertFiles org1根ca.crt --peerAddresses org2背书节点:端口 --tlsRootCertFiles org2根ca.crt\n\t#query查询\npeer chaincode query -C wulusaichannel -n bhxycc -c '{\"Args\":[\"queryUser\", \"2\"]}'\n```\n\n##### 环境配置\n\n```shell\n环境配置都放在scripts/changepath.sh中了,可以指定不同节点的环境变量执行peer channel join\n查看当前节点是否加入通道: peer channel list\n```\n\n\n\n##### 创建通道\n\n```shell\n#创建通道\npeer channel create -o orderer地址:7050 -c 通道名 -f 通道文件 --tls true --cafile orderer节点pem证书文件绝对路径\n#crypto-config/ordererOrganizations/wulusai.net/tlsca/tlsca.wulusai.net-cert.pem这是宿主机的文件,在cli中应该找客户端的文件绝对路径\npeer channel create -o orderer.wulusai.net:7050 -c wulusaichannel -f ./channel-artifacts/channel.tx --tls true --cafile /opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/ordererOrganizations/wulusai.net/tlsca/tlsca.wulusai.net-cert.pem\n#此处遇到bug 修改configtx.yaml的Capabilities为fabric-sample的默认值解决,以下为错误信息\n#Error: got unexpected status: BAD_REQUEST -- error validating channel creation transaction for new channel 'wulusaichannel', could not succesfully apply update to template configuration: error authorizing update: error validating DeltaSet: policy for [Value]  /Channel/Capabilities not satisfied: implicit policy evaluation failed - 0 sub-policies were satisfied, but this policy requires 2 of the 'Admins' sub-policies to be satisfied\n#生成了 通道名.block 文件\n```\n\n##### 当前节点加入通道\n\n```shell\n#当前节点加入通道 这里用org1的管理员添加一次 再用org2的管理员添加一次\npeer channel join -b wulusaichannel.block\n```\n\n##### 更新锚节点\n\n```shell\n#更新锚节点 在configtx.yaml中已经指定了默认锚节点 如果不需要更换锚节点这一步可以不做\npeer channel update -o orderer节点地址:端口 -c 通道名 -f 锚节点更新文件 --tls true --cafile orderer节点pem格式证书文件\n#更新锚节点 org1\npeer channel update -o orderer.wulusai.net:7050 -c wulusaichannel -f ./channel-artifacts/Org1MSPanchors.tx --tls true --cafile /opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/ordererOrganizations/wulusai.net/orderers/orderer.wulusai.net/msp/tlscacerts/tlsca.wulusai.net-cert.pem\n#更新锚节点 org2\npeer channel update -o orderer.wulusai.net:7050 -c wulusaichannel -f ./channel-artifacts/Org2MSPanchors.tx --tls true --cafile /opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/ordererOrganizations/wulusai.net/orderers/orderer.wulusai.net/msp/tlscacerts/tlsca.wulusai.net-cert.pem\n```\n\n##### 安装链码\n\n```shell\n#想要在哪个节点上安装链码就需要在哪个节点配置下install\n# -l 默认为go\npeer chaincode install -n 链码名字 -v 链码版本 -l 链码语言 -p 链码位置\n#安装链码 -p 必须是链码安装的目录而不是链码,起始为$GOPATH下路径 /opt/gopath\npeer chaincode install -n bhxycc -v 1.0 -p github.com/chaincode/bhxy\n```\n\n##### 链码初始化\n\n```shell\n#init初始化 只需要任意节点初始化一次,数据会自动同步\n#链码的初始化 \npeer chaincode instantiate -o orderer节点地址:端口 -tls true -cafile orderer节点pem格式证书文件 -C 通道名称 -n 链码名称 -l 链码语言 -v 链码版本 -c 链码init函数调用 -P 背书策略\n#初始化\npeer chaincode instantiate -o orderer.wulusai.net:7050 --tls true --cafile /opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/ordererOrganizations/wulusai.net/orderers/orderer.wulusai.net/msp/tlscacerts/tlsca.wulusai.net-cert.pem -C wulusaichannel -n bhxycc -v 1.0 -c '{\"Args\":[\"init\"]}' -P \"AND ('Org1MSP.peer','Org2MSP.peer')\"\n#Error: error endorsing chaincode: rpc error: code = Unknown desc = access denied: channel [wulusaichannel] creator org [Org2MSP]\n# 背书策略改为member了\npeer chaincode instantiate -o orderer.wulusai.net:7050 --tls true --cafile /opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/ordererOrganizations/wulusai.net/orderers/orderer.wulusai.net/msp/tlscacerts/tlsca.wulusai.net-cert.pem -C wulusaichannel -n bhxycc -v 1.0 -c '{\"Args\":[\"init\"]}' -P \"AND ('Org1MSP.member','Org2MSP.member')\"\n#可能是未加入通道 peer channel list查看情况\n```\n\n##### invoke调用\n\n```shell\n#调用需要向orderer节点发送请求,然后由背书规则背书,结果发送给orderer打包\npeer chaincode invoke  -n 链码名字 -c '{\"Args\":[\"userRegister\", \"2\", \"user1\"]}' -o orderer节点地址:端口 --tls true --cafile orderer节点pem格式证书文件 -C wulusaichannel --peerAddresses org1背书节点:端口 --tlsRootCertFiles org1根ca.crt --peerAddresses org2背书节点:端口 --tlsRootCertFiles org2根ca.crt\n#invoke调用  需要根据制定背书策略选择背书节点证书 orderer证书\npeer chaincode invoke  -n bhxycc -c '{\"Args\":[\"userRegister\", \"2\", \"user1\"]}' -o orderer.wulusai.net:7050 --tls true --cafile /opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/ordererOrganizations/wulusai.net/orderers/orderer.wulusai.net/msp/tlscacerts/tlsca.wulusai.net-cert.pem -C wulusaichannel --peerAddresses peer0.org1.wulusai.net:7051 --tlsRootCertFiles /opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org1.wulusai.net/peers/peer0.org1.wulusai.net/tls/ca.crt --peerAddresses peer0.org2.wulusai.net:9051 --tlsRootCertFiles /opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org2.wulusai.net/peers/peer0.org2.wulusai.net/tls/ca.crt\n\n#Error: endorsement failure during invoke. response: status:500 message:\"cannot retrieve package for chaincode bhxycc/1.0, error open /var/hyperledger/production/chaincodes/bhxycc.1.0: no such file or directory\" \n#在 install命令都执行后出现 多节点部署问题,解决办法:先打包再按照\n\n#按顺序执行 创建通道,加入通道 更新锚节点 安装链码 初始化 query成功 invoke调用失败\n#可能原因1,没有在所有对等节点上安装链码\n#可能原因2,当前环境变量设置问题,没有在通道内链码调用invoke\n#可以使用 peer channel list 检查当前peer的通道\n#可以使用 echo $CORE_PEER_ADDRESS 检查当前peer的服务地址\n#Error: could not assemble transaction: ProposalResponsePayloads do not match - proposal response: version:1 response:\u003cstatus:200 \u003e payload:\"...\n\n```\n\n##### 查询\n\n```shell\n#查询 可以查询 查询不需要经过orderer,只需要向通道内节点请求就行\npeer chaincode query -C wulusaichannel -n bhxycc -c '{\"Args\":[\"queryUser\", \"2\"]}'\n#升级链码 这个代码无用\npeer chaincode Upgrade -o orderer.wulusai.net:7050 -C wulusaichannel -n bhxycc -v 1.1 -c '{\"Args\":[\"init\"]}'\n```\n\nhttps://godoc.org/github.com/hyperledger/fabric/core/chaincode/shim\n\n配置环境的文件的意义\n\n```shell\n# core peer msp config path 当前peer节点的admin的msp证书\n#peerOrg下的组织org2 的 users 下的 admin用户的msp\nexport CORE_PEER_MSPCONFIGPATH=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org2.wulusai.net/users/Admin@org2.wulusai.net/msp\n#core peer address \nexport CORE_PEER_ADDRESS=peer0.org2.wulusai.net:9051\n#core peer local msp id 操作的peer节点名字\nexport CORE_PEER_LOCALMSPID=\"Org2MSP\"\n#core peer tls cert file peer节点的证书\n#peerOrg下的组织org2 的 peers 的peer0 的tls下的 server.crt\nexport CORE_PEER_TLS_CERT_FILE=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org2.wulusai.net/peers/peer0.org2.wulusai.net/tls/server.crt\n#core peer tls key file peer节点的秘钥文件\n#peerOrg下的组织org2 的 peers 的peer0 的tls下的 server.key\nexport CORE_PEER_TLS_KEY_FILE=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org2.wulusai.net/peers/peer0.org2.wulusai.net/tls/server.key\n#core peer tls rootcert file peer节点的根文件 根证书\n#peerOrg下的组织org2 的 peers 的peer0 的tls下的ca.crt\nexport CORE_PEER_TLS_ROOTCERT_FILE=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org2.wulusai.net/peers/peer0.org2.wulusai.net/tls/ca.crt\n #orderer节点的ca证书\n #在ordererOrg目录下的 域名/orderers 的 对应orderer节点 \n #的msp的tls cacerts tlsca.wulusai.net-cert.pem\n --cafile /opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/ordererOrganizations/wulusai.net/orderers/orderer.wulusai.net/msp/tlscacerts/tlsca.wulusai.net-cert.pem\n```\n\n#### fabric账号\n\n\u003e 根据PKI规范生成的一组证书和秘钥文件\n\u003e\n\u003e 作用:\n\u003e\n\u003e ​\t保证记录在区块链中的数据具有不可逆,不可篡改\n\u003e\n\u003e ​\tfabric中每条交易都会加上发起者的标签(签名证书) 同时用发起人的私钥加密\n\u003e\n\u003e ​\t如果交易需要其他组织的节点提供背书功能,name背书节点也会在交易中加入自己的签名\n\u003e\n\u003e 创建channel\n\n如何寻找对应的账号目录\n\n```shell\n#Orderer 启动路径\ncrypto-config/ordererOrganizations/wulusai.net/orderers/orderer.wulusai.net/msp\n#Peer 启动的账号路径\ncrypto-config/peerOrganizations/org1.wulusai.net/peers/peer0.org1.wulusai.net/msp\n#创建 channel的账号路径 crypto是cli容器内目录\ncrypto/peerOrganizations/org2.wulusai.net/users/Admin@org2.wulusai.net/msp\n```\n\n\n\n```shell\n\n```\n\ncrypto的tree\n\n```\n\n```\n\n#### fabric-ca\n\n\n\n```shell\nnode.js 的api 编程去组织上生成账号\n官方建议,一个组织对应一个ca\n#fabric-ca的配置 模板文件fabric-sample/base-network/docker-compose.yaml\ndocker rm `docker ps -aq` -f #删除容器\n#如果没有按照npm\nyum install npm\n#新建一个目录初始化 遇到选项全回车就行最终生成一个 package.json\nnpm init\nnpm install -g node-gyp\nnpm install -g node-pre-gyp \nnpm install -g cnpm --registry=https://registry.npm.taobao.org\nnpm install --save grpc --unsafe-perm #安装成功\n#使用nodejs 依赖包\nnpm install --save fabric-ca-client --unsafe-perm #安装成功\n#这两个安装包安装失败\nyum -y update gcc\nyum -y install gcc+ gcc-c++\nnpm install --save fabric-client --unsafe-perm\n#如果没能解决可以尝试更新nodejs如下\n#更新yum源\nmv /etc/yum.repos.d/CentOS-Base.repo /etc/yum.repos.d/CentOS-Base.repo.backup\ncurl -o /etc/yum.repos.d/CentOS-Base.repo http://mirrors.aliyun.com/repo/Centos-7.repo\nyum makecache\nyum -y update\n#如果没有更新则直接下载最新版 添加到/etc/profile\nwget https://nodejs.org/dist/v12.16.1/node-v12.16.1-linux-x64.tar.xz\nxz -d node-v12.16.1-linux-x64.tar.xz\ntar -xf node-v12.16.1-linux-x64.tar\n#创建软连接\nln -s ~/node-v12.16.1-linux-x64/bin/node /usr/bin/node\nln -s ~/node-v12.16.1-linux-x64/bin/npm /usr/bin/npm\n#删除软连接 \nrm -rf /usr/bin/node\n#install报错了试试下面的\nnpm cache verify\nnpm cache clean\nnpm cache clean --force\nnpm i -g npm\ngrep -ir \"sha1-xxxxxxxxxxxxxxxx\" ~/.npm\n#执行命令\nnode enrollAdmin.js #创建管理员用户 \u003e hfc-key-store\n\n\n#hf-key-store\nhfc-key-store/\n├── 709630d415d64255d1c9cac3483bf3bd044a3ac8c7c942eeae34795e0f4e0f1d-priv\n├── 709630d415d64255d1c9cac3483bf3bd044a3ac8c7c942eeae34795e0f4e0f1d-pub\n└── admin\n#执行创建普通用户\nnode enrollUser.js #创建普通用户\nhfc-key-store/\n├── 1f98230937ffcb5057794d89569e1697fd49a23fd182577ca66d37a3cd8149fc-priv\n├── 1f98230937ffcb5057794d89569e1697fd49a23fd182577ca66d37a3cd8149fc-pub\n├── 709630d415d64255d1c9cac3483bf3bd044a3ac8c7c942eeae34795e0f4e0f1d-priv\n├── 709630d415d64255d1c9cac3483bf3bd044a3ac8c7c942eeae34795e0f4e0f1d-pub\n├── admin\n└── user3\nnode query.js\n```\n\n#### solo多机多节点部署\n\n```shell\nn台主机需要创建一个名字相同的工作目录\n#主机1:192.168.100.10\nmdir ~/wulusai\n#主机2:192.168.100.20\nmdir ~/wulusai\n#主机3:192.168.100.30\nmdir ~/wulusai\n#疑问?这是在内网多机部署,如果多组织和多节点跨公网和内网该怎么办?\n```\n\n#####orderer节点主机的配置\n\n```yaml\n#需要注意的是networks的配置\nversion: '2'\n\nservices:\n  orderer.wulusai.net: #为了方便看 服务名跟域名相同\n    image: hyperledger/fabric-orderer:latest\n    container_name: ca.wulusai.net\n    environment:\n      - FABRIC_LOGGING_SPEC=INFO\n      - ORDERER_GENERAL_LISTENADDRESS=0.0.0.0 #orderer节点的监听地址\n    volumes:\n        - ../crypto-config/...:/var/hyperledger/orderer/msp\n        - ../crypto-config/.../tls/:/var/hyperledger/orderer/tls\n        - orderer.wulusai.net:/var/hyperledger/production/orderer\n    working_dir: /opt/gopath/src/github.com/hyperledger/fabric\n    command: orderer\n    ports:\n      - 7050:7050\n    networks:\n      default:\n      \taliases:\n      \t\t- wulusai #此名字是当前配置文件所在的目录的名字\n```\n\n##### peer节点主机的配置\n\n```yaml\n#需要注意的是节点的networks和extra_hosts的配置\nversion: '2'\n\nservices:\n\n    peer0.org1.wulusai.net:\n      container_name: peer0.org1.wulusai.net\n      image: hyperledger/fabric-peer:latest\n      environment:\n        - CORE_PEER_LOCALMSPID=Org1MSP\n        - CORE_PEER_ID=peer0.org1.wulusai.net\n        - CORE_PEER_ADDRESS=peer0.org1.wulusai.net:7051\n        - ...\n      volumes:\n        - /var/run/:/host/var/run/\n        - ...\n      working_dir: /opt/gopath/src/github.com/hyperledger/fabric/peer\n      command: peer node start\n      networks:\n        default:\n          aliases:\n            - testwork\n      ports:\n        - 7051:7051\n      extra_hosts:  # 声明域名和IP的对应关系 把域名解析为对应IP\n        - \"orderer.wulusai.net:192.168.100.10\"\n        #- \"peer0.org1.wulusai.net:192.168.100.20\"\n        \n#需要注意的是cli的networks和extra_hosts的配置        \n    cli:\n      container_name: cli\n      image: hyperledger/fabric-tools:latest\n      tty: true\n      stdin_open: true\n      environment:\n        - CORE_PEER_ID=cli\n        - CORE_PEER_ADDRESS=peer0.org1.wulusai.net:7051\n        - CORE_PEER_LOCALMSPID=Org1MSP\n        - CORE_PEER_TLS_ENABLED=true\n        - ...\n      working_dir: /opt/gopath/src/github.com/hyperledger/fabric/peer\n      command: /bin/bash\n      volumes:\n          - /var/run/:/host/var/run/\n         \n      depends_on:   # 启动顺序 有用吗?\n        - peer0.org1.wulusai.net     \n      networks:\n          default:\n            aliases:\n              - wulusai #这里需要注意 order ,peer 都要在同名目录下 这个也要相同,否则找不到\n      extra_hosts: #同网络下其他主机地址,这是个 1 orderer 2 peer 的网络 \n        - \"orderer.wulusai.net:192.168.100.10\"\n        - \"peer0.org1.wulusai.net:192.168.100.20\"\n        #- \"peer0.org2.wulusai.net:192.168.100.30\"\n```\n\n部署节点\n\n```shell\n#准备好事先生成的channel-artifacts crypto-config的文件\n#切换到对应主机上 如 pee0.org1的主机 192.168.100.20\n#进入主机文件夹 ~/wulusai\n#拷问文件 channel-artifacts crypto-config 到目录中\n#编写docker-compose.yaml\n理解起来很容易 拷贝的文件是工具生成的,里面包含了docker容器启动需要的文件\n#容器的启动,cli的操作与之前几乎一样,无非就是容器配置文件被拆分了\n容器启动后可执行的操作\n#orderer容器: 假设证书文件\n\t先启动,不做任何操作\n#peer0.org1节点: \n\tdocker-compose up -d 启动后 \n\tcli:\n\t\t执行create channel \n    \tpeer join\n    \tpeer install操作\n    \tdocker cp cli:/..../peer/channel.block #拷贝通道文件到宿主机中 发给其他主机\n    \t#还有一种操作方法,将文件放到容器的挂载目录中\n#peer0.org2节点:\n\t\n```\n\n#### fabric网络搭建过程\n\n```shell\n#1.编写组织信息的配置文件,文件中声明多少个组织,每个组织多少个节点多少用户\ncrypto-config.yaml\n#2.生成创世块文件和通道文件,文件中声明配置组织信息,共识机制,区块生成策略,组织关系的概述\nconfigtx.yaml\n```\n\n\n\n#### fabric网络组织结构\n\n```\n客户端\n\t链接peer需要用户身份账号信息,就可以连到同组织的peer节点\n\t客户端发起一笔交易\n\t\t会发送到所有参与交易的背书节点上\n\t\t参加背书的节点进行模拟交易\n\t\t背书节点将处理结果发送给客户端你\n\t\t如果提案的结果没问题,客户端将交易提交给orderer节点\n\t\torderer节点将交易打包\n\t\tleader节点将打包数据同步到当前组织\n\t\t当前组织的提交节点将打包数据写入到区块中\nfabric-ca-sever\n\t可以通过他动态创建用户\n\t可有可无,因为fabirc是个封闭网络,只是提供了些许灵活性\n组织\n排序节点\n\t对交易进行排序\n\t\t解决双花问题\n\t对交易打包\npeer节点\n\t背书节点\n\t\t进行模拟交易,将结果返回给客户端\n\t\t客户端选择的,指定谁去模拟交易\n\t提交节点\n\t\t将orderer节点打包的数据加入到区块链中\n\t\t只要是peer节点,就有提交数据的能力\n\t主节点\n\t\t和orderer排序节点直接通信的节点\n\t\t\t从orderer节点处获取到打包数据\n\t\t\t将数据同步到当前组织的各个节点中\n\t\t只能有一个\n\t\t\t可以自己指定\n\t\t\t也可通过fabric框架自主选举\n\t锚节点\n\t\t代表当前组织和其他组织通信的节点\n\t\t只能有一个\n```\n\n\n\nSCP远程拷贝\n\n```shell\nscp 要拷贝的文件路径 远程主机用户名@远程主机ip:远程主机目录\nscp -r 要拷贝的目录 远程主机用户名@远程主机ip:远程主机目录\nscp -r /root/wulusai root@192.168.1.2:/root\n\n#安装同一个链码文件时有可能出现指纹不匹配的问题,可以用如下方式安装\n#安装链码 在一个节点上安装完链码,打包然后远程拷贝到其他节点主机上\n#将链码打包\npeer chaincode package -n bhxycc -v 1.0 -p github.com/chaincode bhxycc.1.0.out\n#将链码从容器中拷贝到主机上\ndocker cp cli:/opt/gopath/src/github.com/hyperledger/fabric/peer/bhxycc.1.0.out ./\n#scp发送到远程主机\nscp ./bhxycc.1.0.out root@192.168.1.2:/root/wulusai/channel-artifacts\n\n#进入另一个主机的cli容器中\ndocker exec -it cli bash\n#安装链码\npeer chaincode install ./channel-artifacts/bhxycc.1.0.out\n```\n\n#### kafka多级多节点配置\n\n```shell\n#为保证集群的可用性,3台主机\n#zookeeper主机1:192.168.100.101\n#zookeeper主机2:192.168.100.102\n#zookeeper主机3:192.168.100.103\n#kafka集群至少4个主机才行\n#kafka主机1:192.168.100.201 \n#kafka主机2:192.168.100.202\n#kafka主机3:192.168.100.203\n#kafka主机4:192.168.100.204\n# 同样最低3台\n#orderer主机3:192.168.100.20\n#orderer主机3:192.168.100.21\n#orderer主机3:192.168.100.22\n# 两个组织一个组织一个peer节点\n#peer主机3:192.168.100.30\n#peer主机3:192.168.100.40\n```\n\nzookeeper配置\n\n```yaml\nversion: '2'\n\nservices:\n\n  zookeeper1:\n    container_name: zookeeper1\n    hostname: zookeeper1\n    image: hyperledger/fabric-zookeeper:latest\n    restart: always\n    environment:\n      # ID在集合中必须是唯一的并且应该有一个值，在1和255之间。\n      - ZOO_MY_ID=1\n      # server.x=[hostname]:nnnnn[:nnnnn]\n      - ZOO_SERVERS=server.1=zookeeper1:2888:3888 server.2=zookeeper2:2888:3888 server.3=zookeeper3:2888:3888\n    ports:\n      - 2181:2181\n      - 2888:2888\n      - 3888:3888\n    extra_hosts:\n      - zookeeper1:192.168.100.101\n      - zookeeper2:192.168.100.102\n      - zookeeper3:192.168.100.103\n      - kafka1:192.168.100.201\n      - kafka2:192.168.100.202\n      - kafka3:192.168.100.203\n      - kafka4:192.168.100.204\n```\n\nkafka配置\n\n```yaml\n\nversion: '2'\n\nservices:\n\n  kafka1:\n    container_name: kafka1\n    hostname: kafka1\n    image: hyperledger/fabric-kafka\n    restart: always\n    environment:\n      # broker.id\n      - KAFKA_BROKER_ID=1 \n      - KAFKA_MIN_INSYNC_REPLICAS=2 #最小备份数\n      - KAFKA_DEFAULT_REPLICATION_FACTOR=3 #默认备份数\n      - KAFKA_ZOOKEEPER_CONNECT=zookeeper1:2181,zookeeper2:2181,zookeeper3:2181\n      # 100 * 1024 * 1024 B\n      - KAFKA_MESSAGE_MAX_BYTES=104857600  #最大信息个头 根据orderer节点打包区块大小设置,orderer默认99M 这里信息包括消息头 所以给100M\n      - KAFKA_REPLICA_FETCH_MAX_BYTES=104857600 #配置同上\n      - KAFKA_UNCLEAN_LEADER_ELECTION_ENABLE=false\n      - KAFKA_LOG_RETENTION_MS=-1 #记录日志的时间间隔 -1表示不记录\n      - KAFKA_HEAP_OPTS=-Xmx512M -Xms256M #堆内存 默认1G\n    ports:\n      - 9092:9092\n    extra_hosts:\n      - zookeeper1:192.168.100.101\n      - zookeeper2:192.168.100.102\n      - zookeeper3:192.168.100.103\n      - kafka1:192.168.100.201\n      - kafka2:192.168.100.202\n      - kafka3:192.168.100.203\n      - kafka4:192.168.100.204\n```\n\norderer配置\n\n```yaml\nversion: '2'\n\nservices:\n\n  orderer0.wulusai.net:\n    container_name: orderer0.wulusai.net\n    image: hyperledger/fabric-orderer:latest\n    environment:\n      - CORE_VM_DOCKER_HOSTCONFIG_NETWORKMODE=kafka_default #注意这里的网络设置\n      - ORDERER_GENERAL_LOGLEVEL=debug\n      - ORDERER_GENERAL_LISTENADDRESS=0.0.0.0\n      - ORDERER_GENERAL_LISTENPORT=7050\n      - ORDERER_GENERAL_GENESISMETHOD=file\n      - ORDERER_GENERAL_GENESISFILE=/var/hyperledger/orderer/orderer.genesis.block\n      - ORDERER_GENERAL_LOCALMSPID=OrdererMSP\n      - ORDERER_GENERAL_LOCALMSPDIR=/var/hyperledger/orderer/msp\n      # enabled TLS\n      - ORDERER_GENERAL_TLS_ENABLED=false\n      - ORDERER_GENERAL_TLS_PRIVATEKEY=/var/hyperledger/orderer/tls/server.key\n      - ORDERER_GENERAL_TLS_CERTIFICATE=/var/hyperledger/orderer/tls/server.crt\n      - ORDERER_GENERAL_TLS_ROOTCAS=[/var/hyperledger/orderer/tls/ca.crt]\n\n      - ORDERER_KAFKA_RETRY_LONGINTERVAL=10s\n      - ORDERER_KAFKA_RETRY_LONGTOTAL=100s\n      - ORDERER_KAFKA_RETRY_SHORTINTERVAL=1s\n      - ORDERER_KAFKA_RETRY_SHORTTOTAL=30s\n      - ORDERER_KAFKA_VERBOSE=true\n      - ORDERER_KAFKA_BROKERS=[192.168.100.201:9092,192.168.100.202:9092,192.168.100.203:9092,192.168.100.204:9092] #kafka主机的地址\n    working_dir: /opt/gopath/src/github.com/hyperledger/fabric\n    command: orderer\n    volumes:\n      - ./channel-artifacts/genesis.block:/var/hyperledger/orderer/orderer.genesis.block\n      - ./crypto-config/ordererOrganizations/test.com/orderers/orderer0.wulusai.net/msp:/var/hyperledger/orderer/msp\n      - ./crypto-config/ordererOrganizations/test.com/orderers/orderer0.wulusai.net/tls/:/var/hyperledger/orderer/tls\n    networks:\n      default:\n        aliases:\n         - kafka\n    ports:\n      - 7050:7050\n    extra_hosts:\n      - kafka1:192.168.100.201\n      - kafka2:192.168.100.202\n      - kafka3:192.168.100.203\n      - kafka4:192.168.100.204\n```\n\n##### 启用kafka集群\n\n```shell\ncd kafka\n#按顺序启动容器 此处假设已经完成了目录的创建,并且通过cryptogen生成的文件和configtxgen生成的区块等文件已经放到了对应的主机上\ndocker-compose up -d -f zookeeper.yaml\ndocker-compose up -d -f kafka.yaml\ndocker-compose up -d -f orderer.yaml\ndocker-compose up -d -f peer.yaml\n```\n\n#### 实例演示\n\n```go\n/*\n假设有如下场景:\n\t养牛场 dairy farm 牛奶加工厂 milk processing factory 销售商 seller\n他们之间需要建立一个fabric网络,保证每一瓶出产的牛奶商品都可以溯源\n那么他们需要怎么建立 \nOrganization: dairy  process sell\nchaincode: dairy.go process.go seller.go\n假设每个组织有三个成员\ncrypto-config.yaml 中配置组织和成员的秘钥材料生成规则\nconfigtx.yaml 配置各组织交互规则权限\n\n溯源流程:\n每袋牛奶上有个ID,唯一标识\n通过标识查出牛奶是谁卖出去的 -\u003e狗东\n根据狗东的标识查询 -\u003e 狗东的供应商\n根据供应商(加工厂) -\u003e 来自哪个牛奶厂\n通过奶牛场 -\u003e 查到牛情况\n```\n\n##### 链码编写分析\n\n```go\n/*\nInit函数调用时机: instantiate时/upgrade时\nInvoke调用: peer invoke\n\n调用函数\nGetState\nPutState\nGetHistoryForKey\n\n消费者 invoke调用,参数:牛奶盒上的ID\n values:= stub.GetHistoryForKey(ID)\n values是个json字符串 里面包含了经销商信息,经销商从哪个地方进货的信息\n \n 链码调用:\n stub.InvokeChaincode(\"process\",args,\"channel\")\n \n```\n\n使用fabric与传统程序有何优势?\n\n第一,由于从客户端到排序服务都是多节点验证,保证了程序难以被破坏和篡改\n\n第二,fabric生成链的形式,保证了每一个操作记录都能被找到且历史不可篡改\n\nfabric数据以区块的形式保存,而且想要访问区块数据,必须要用fabric的链码访问,而想要调用链码,则必须是网络的用户,使用正确的用户的证书才能在网络中调用链码\n\n并且链码在多个节点中都有备份,想通过攻击某一节点对网络进行篡改或者破坏都比传统系统难上不少","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fwulusai2333%2Flinuxstudy","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fwulusai2333%2Flinuxstudy","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fwulusai2333%2Flinuxstudy/lists"}