本文關於新的peer節點加入網絡的相關操作是基於java版本的sdk進行的。
假設你原本是基於Template創建的節點
修改crypto-config.yaml配置
OrdererOrgs:
# orderer的配置在這里就省略了
- ...
PeerOrgs:
- Name: Org1
Domain: org1.example.com
CA:
Hostname: ca
# 這里原本是2,現在我們新增一個節點,將這里修改為3
Template:
Count: 3
Users:
Count: 1
生成peer節點證書
# 執行命令生成的時候沒有打印,要確認是否生成ok,可以使用tree命令查看一下目錄結構
# 使用cryptogen工具的extend指令
./bin/cryptogen extend --config=./crypto-config.yaml
環境變量文件
#default env. vars settings
#TLS: etcdraft 模式下必須開啟tls(因為有指定各orderer節點的TLS證書)
TLS=true
CLIENT_AUTH_REQUIRED=false
#docker-compose config for setting project name
COMPOSE_PROJECT_NAME=tld
#Image tags - Fabric versions.
#V 1.4.1
IMAGE_TAG_FABRIC=1.4.1
IMAGE_TAG_FABRIC_CA=1.4.1
#log
LOG_LEVEL=INFO
#DNS server address,如果在/etc/hosts中添加了節點映射,這里可以忽略(私有域名服務器地址)
DNS_ADDR_01=192.168.1.111
#other
V11_IDENTITIES_ALLOWREMOVE=--cfg.identities.allowremove
V11_AFFILIATIONS_ALLOWREMOVE=--cfg.affiliations.allowremove
編寫peer節點的啟動配置
docker-compose-tld-peer3org1.yaml
# 版本
version: '3'
# 網絡
networks:
basic:
driver: bridge
# 服務
services:
peer3.org1.example.com:
container_name: peer3.org1.example.com
hostname: peer3.org1.example.com
image: hyperledger/fabric-peer:${IMAGE_TAG_FABRIC}
restart: always
environment:
- CORE_PEER_ID=peer3.org1.example.com
# 雲服務器環境下需要加這個配置
- GODEBUG=netdns=go
- CORE_PEER_ADDRESS=peer3.org1.example.com:7051
- CORE_PEER_EVENTS_ADDRESS=0.0.0.0:7053
- CORE_PEER_CHAINCODELISTENADDRESS=peer3.org1.example.com:7052
- CORE_PEER_GOSSIP_EXTERNALENDPOINT=peer3.org1.example.com:7051
- CORE_PEER_GOSSIP_BOOTSTRAP=peer0.org1.example.com:7051
- CORE_PEER_LOCALMSPID=Org1MSP
- CORE_PEER_TLS_ROOTCERT_FILE=/etc/hyperledger/fabric/peer/msp/cacerts/ca.org1.example.com-cert.pem
- CORE_PEER_TLS_CLIENTROOTCAS_FILES=/etc/hyperledger/fabric/peer/msp/tlscacerts/tlsca.org1.example.com-cert.pem
# ---
- CORE_VM_ENDPOINT=unix:///host/var/run/docker.sock
- CORE_VM_DOCKER_HOSTCONFIG_NETWORKMODE=${COMPOSE_PROJECT_NAME}_basic
- FABRIC_LOGGING_SPEC=${LOG_LEVEL}
- CORE_PEER_ENDORSER_ENABLED=true
- CORE_PEER_CHANNELSERVICE_ENABLED=true
- CORE_CHAINCODE_STARTUPTIMEOUT=10m
- CORE_PEER_MSPCONFIGPATH=/etc/hyperledger/fabric/peer/msp
- CORE_PEER_GOSSIP_USELEADERELECTION=true
- CORE_PEER_GOSSIP_ORGLEADER=false
- CORE_PEER_PROFILE_ENABLED=false
- CORE_PEER_TLS_ENABLED=${TLS}
- CORE_PEER_TLS_CERT_FILE=/etc/hyperledger/fabric/peer/tls/server.crt
- CORE_PEER_TLS_KEY_FILE=/etc/hyperledger/fabric/peer/tls/server.key
- CORE_PEER_TLS_ROOTCERT_FILE=/etc/hyperledger/fabric/peer/tls/ca.crt
working_dir: /opt/gopath/src/github.com/hyperledger/fabric/peer
command: peer node start
volumes:
# 注意同步時間,這里只是同步了時間,還需要注意同步時區
- /etc/localtime:/etc/localtime
- /var/run/:/host/var/run/
- ./crypto-config/peerOrganizations/org1.example.com/peers/peer3.org1.example.com:/etc/hyperledger/fabric/peer:ro
- ./fabric-data/peer3.org1.example.com:/var/hyperledger/production
ports:
- 7051:7051
- 7052:7052
- 7053:7053
networks:
- basic
啟動節點
docker-compose -f ./docker-compose-tld-peer3org1.yaml up -d
新節點加入通道
這里需要注意下,hfClient客戶端程序中指定的用戶是PeerAdmin以及其相關的證書。
這里牽扯的代碼比較多,在這里只放一些關鍵的代碼。
@Test
public void newPeerJoinChannel() throws Exception {
Map<String, String> peerLocations = new HashMap<>();
peerLocations.put("peer3.org1.example.com", FabricManager.grpcUrl(true, "x.x.x.x", "7051"));
org1.setPeerLocations(peerLocations);
channelManager.newOrgPeerJoinChannel(org1, admin);
}
public void newOrgPeerJoinChannel(IntermediateOrg org, IntermediateUser user) throws Exception {
// 這里的參數為true的話是特別指定了使用的用戶證書是peeradmin的
HFClient client = this.getClient(org, user, true);
// 從store中獲取通道,類似cli操作中的channel.block
Channel channel = FabricStore.getChannel(client, channelName);
for (String peerName : org.getPeerNames()) {
String peerLocation = org.getPeerLocation(peerName);
Properties peerProperties = FABRIC_CONFIGURATION.getPeerProperties(peerName);
if (peerProperties == null) {
peerProperties = new Properties();
}
// set specific options on grpc's NettyChannelBuilder
peerProperties.put("grpc.NettyChannelBuilderOption.maxInboundMessageSize", FabricConstant.PEER_PROPERTIES_MAX_INBOUND_MESSAGE_SIZE);
Peer peer = client.newPeer(peerName, peerLocation, peerProperties);
channel.joinPeer(peer, createPeerOptions().setPeerRoles(EnumSet.of(Peer.PeerRole.ENDORSING_PEER,
Peer.PeerRole.LEDGER_QUERY, Peer.PeerRole.CHAINCODE_QUERY, Peer.PeerRole.EVENT_SOURCE)));
logger.debug(format(" Peer %s joined channel %s", peerName, channelName));
}
FabricStore.saveChannel(channel);
}
節點安裝鏈碼並升級鏈碼
我們不用人為的選擇節點,因為前面的操作依據將新節點包含在channel中了。
如果不想每個節點都去升級,那么也可以單獨的對這個節點做安裝和實例化操作。
// 安裝鏈碼
@Test
public void install() throws Exception {
Map res = chainCodeManager.install();
System.out.println("安裝結果:" + res);
}
// 升級鏈碼
@Test
public void upgrade() throws Exception {
String[] args = {"test_007", "100"};
String endorsementFilePath = "src/main/java/fabric/edu/fixture/chaincode/javacc/chaincodeendorsementpolicy.yaml";
Map res = chainCodeManager.upgrade(args, endorsementFilePath);
System.out.println("升級結果:" + res);
}
// 轉賬
@Test
public void invoke() throws Exception {
String[] args = {"a", "b","100","sign"};
Map res = chainCodeManager.invoke(admin, "move", args);
System.out.println("調用結果:" + res);
}
// 查詢鏈碼
@Test
public void query() throws Exception {
String[] args = {"test_007"};
Map res = chainCodeManager.query(admin, "queryAccount", args);
System.out.println("查詢結果:" + res);
}