diff --git a/cicd/test_script/crypto-gen.sh b/cicd/test_script/crypto-gen.sh index 9a1e238d..81eee5fa 100755 --- a/cicd/test_script/crypto-gen.sh +++ b/cicd/test_script/crypto-gen.sh @@ -219,6 +219,35 @@ bdk chaincode query -C ryan -n ${CHAINCODE_NAME} -f QueryCar -a CAR_EUGENE_PEER0 # ================================================================== +# [BenOrderer] Eric org add in system-channel +export_env 'orderer' 'BenOrderer' ${ORDERER_ORG_DOMAIN_BEN} 'orderer0' +bdk org peer add-system-channel -o orderer0.${ORDERER_ORG_DOMAIN_BEN}:7050 -n Eric +sleep 2 +bdk org orderer approve -c ${SYSTEM_CHANNEL_NAME} +sleep 2 + +# [GraceOrderer] Orderer org approve in system-channel +export_env 'orderer' 'GraceOrderer' ${ORDERER_ORG_DOMAIN_GRACE} 'orderer0' +bdk org orderer approve -c ${SYSTEM_CHANNEL_NAME} +sleep 2 + +# [BenOrderer] Orderer org update in system-channel +export_env 'orderer' 'BenOrderer' ${ORDERER_ORG_DOMAIN_BEN} 'orderer0' +bdk org orderer update -o orderer0.${ORDERER_ORG_DOMAIN_BEN}:7050 -c ${SYSTEM_CHANNEL_NAME} +sleep 2 + +# [Eric] Create channel +export_env 'peer' 'Eric' ${PEER_ORG_DOMAIN_ERIC} 'peer0' +bdk channel create -n ryan87 --orderer orderer0.${ORDERER_ORG_DOMAIN_BEN}:7050 -o Ben -o Grace -o Eugene -o Eric --channelAdminPolicyStyle "Any-Member-in-Channel" +sleep 2 + +bdk channel join -n ryan87 --orderer orderer1.${ORDERER_ORG_DOMAIN_BEN}:7150 +bdk channel update-anchorpeer -n ryan87 --orderer orderer1.${ORDERER_ORG_DOMAIN_BEN}:7150 -p 7051 + +# ================================================================== + + + # [EricOrderer] Orderer org create bdk org orderer create -f cicd/test_script/org-orderer-create.json --genesis-file-name newest_genesis --create-full diff --git a/docs/EXAMPLE-EN.md b/docs/EXAMPLE-EN.md index d304deee..0a9a17b6 100644 --- a/docs/EXAMPLE-EN.md +++ b/docs/EXAMPLE-EN.md @@ -295,11 +295,6 @@ bdk chaincode invoke -C test -n fabcar -f CreateCar -a CAR_ORG2_PEER0 -a BMW -a # Query data bdk chaincode query -C test -n fabcar -f QueryCar -a CAR_ORG2_PEER0 ``` - ## Add New Channel @@ -347,7 +342,6 @@ bdk channel join -n test --orderer orderer0.example.com:7050 Update settings for Org1 and Org2 on the application channel named *test*. Note that when updating the settings in *~/.bdk/.env*, *BDK_ORG_NAME* and *BDK_ORG_DOMAIN* have to be editted as well. - ```bash # export BDK_ORG_NAME='Org1' # export BDK_ORG_DOMAIN='org1.example.com' @@ -368,7 +362,6 @@ bdk channel update-anchorpeer -n test --orderer orderer0.example.com:7050 First, we need to prepare a file named *org-peer-create.json*, with the required variables. We then use `cryptogen` to generate the certificates and keys required for the peer organization. Next, we add the Org3(the new peer org) to the settings file for the application channel. Last, we start the peers in Org3 and add it to the `test` channel. Test transactions and queries should be successful at this point. - ### Prepare settings files *org-peer-create.json* contains parameters required for generating *configtx.yaml*, *crypto-config.yaml*, and *docker-compose.yaml*. Place the file in the current working directory. @@ -457,7 +450,42 @@ Start Org3 peer containers bdk peer up -n peer0.org3.example.com -n peer1.org3.example.com ``` -### Step 4:Add Org3 to channel +### Step 4: Add Org3 to system-channel +Add Org3 to system channel with Org1Orderer + +```bash +# export BDK_ORG_TYPE='orderer' +# export BDK_ORG_NAME='Org1Orderer' +# export BDK_ORG_DOMAIN='org1.example.com' +# export BDK_HOSTNAME='orderer0' + +bdk org peer add-system-channel -o orderer0.org1.example.com:7050 -n Eric +bdk org orderer approve -c system-channel +``` + +Approve system-channel change with Org1Orderer +```bash +# export BDK_ORG_TYPE='orderer' +# export BDK_ORG_NAME='Org2Orderer' +# export BDK_ORG_DOMAIN='org2.example.com' +# export BDK_HOSTNAME='orderer0' + +bdk org peer add-system-channel -o orderer0.org1.example.com:7050 -n Eric +bdk org orderer approve -c system-channel +``` + +update system-channel with Org1Orderer + +```bash +# export BDK_ORG_TYPE='orderer' +# export BDK_ORG_NAME='Org1Orderer' +# export BDK_ORG_DOMAIN='org1.example.com' +# export BDK_HOSTNAME='orderer0' + +bdk org orderer update -o orderer0.org1.example.com:7050 -c system-channel +``` + +### Step 5:Add Org3 to channel Add Org3 to the application channel named *test*. Since each peer is added individually to the application channel, changes to variables *BDK_ORG_NAME*, *BDK_ORG_DOMAIN*, and *BDK_HOSTNAME* in *~/.bdk/.env* are required every time. @@ -475,7 +503,7 @@ bdk channel join -n test --orderer orderer0.example.com:7050 bdk channel join -n test --orderer orderer0.example.com:7050 ``` -### Step 5:Deploy chaincode on Org3 +### Step 6:Deploy chaincode on Org3 Install and approve the chaincode named fabcar_1. Since we are using the blockchain network from before, we only need to do `peer chaincode lifecycle approveformyorg` up to this step. We can use the `-a` parameter to restrict the deployment of the chaincode lifecycle, and require the chaincode to be initialized with parameter ``-I`. We then install the chaincode named fabcar_1 on peer1 of Org3. @@ -495,7 +523,7 @@ bdk chaincode deploy -C test -l fabcar_1 -I -a --orderer orderer0.example.com:70 bdk chaincode install -l fabcar_1 ``` -### Step 6:Initiate and query a transaction on Org3 +### Step 7:Initiate and query a transaction on Org3 Initiate a chaincode transaction on fabcar_1 with `bdk chaincode invoke`. We use the `-f` parameter to select the function used to initialize the chaincode, and `-a` parameter to pass in the variables for the chaincode function. We can then query the chaincode with `bdk chaincode query`. diff --git a/docs/EXAMPLE.md b/docs/EXAMPLE.md index 784ace5f..e3fe322e 100644 --- a/docs/EXAMPLE.md +++ b/docs/EXAMPLE.md @@ -450,7 +450,42 @@ bdk org peer add -o orderer0.org1.example.com:7050 -c test -n Eric bdk peer up -n peer0.org3.example.com -n peer1.org3.example.com ``` -### Step 4:Org3 加入 Channel +### Step 4:Org3 加入 system-channel +由 Org1Orderer 組織身份將 Org3 加入 System Channel 並同意 + +```bash +# export BDK_ORG_TYPE='orderer' +# export BDK_ORG_NAME='Org1Orderer' +# export BDK_ORG_DOMAIN='org1.example.com' +# export BDK_HOSTNAME='orderer0' + +bdk org peer add-system-channel -o orderer0.org1.example.com:7050 -n Eric +bdk org orderer approve -c system-channel +``` + +由 Org2Orderer 組織身份同意 system-channel 的更新 +```bash +# export BDK_ORG_TYPE='orderer' +# export BDK_ORG_NAME='Org2Orderer' +# export BDK_ORG_DOMAIN='org2.example.com' +# export BDK_HOSTNAME='orderer0' + +bdk org peer add-system-channel -o orderer0.org1.example.com:7050 -n Eric +bdk org orderer approve -c system-channel +``` + +由 Org1Orderer 組織身份更新 system-channel + +```bash +# export BDK_ORG_TYPE='orderer' +# export BDK_ORG_NAME='Org1Orderer' +# export BDK_ORG_DOMAIN='org1.example.com' +# export BDK_HOSTNAME='orderer0' + +bdk org orderer update -o orderer0.org1.example.com:7050 -c system-channel +``` + +### Step 5:Org3 加入 Channel Org1 加入名稱為 *test* 的 Application Channel,由於加入 Application Chanel 是以 Peer 單位加入,所以每次加入都要記得更改在 *~/.bdk/.env* 的 *BDK_ORG_NAME 、 BDK_ORG_DOMAIN* 、 *BDK_HOSTNAME* 的設定 @@ -468,7 +503,7 @@ bdk channel join -n test --orderer orderer0.example.com:7050 bdk channel join -n test --orderer orderer0.example.com:7050 ``` -### Step 5:Org3 部署 Chaincode +### Step 6:Org3 部署 Chaincode 安裝並且同意標籤名稱為 fabcar_1 的 Chaincode,由於使用前面的 Blockchain network,所以此次只做到 `peer chaincode lifecycle approveformyorg`,使用 `-a` 來限制 Lifecycle chaincode 的部署 Chaincode 步驟只做到 `peer chaincode lifecycle approveformyorg` ,使用 `-I` 來標示此次 Chaincode 需要初始化才能使用,之後在 Org3 的 peer1 安裝名稱為 fabcar_1 的 Chaincode @@ -488,7 +523,7 @@ bdk chaincode deploy -C test -l fabcar_1 -I -a --orderer orderer0.example.com:70 bdk chaincode install -l fabcar_1 ``` -### Step 6:Org3 發起交易且查詢 +### Step 7:Org3 發起交易且查詢 使用 `bdk chaincode invoke` 和名稱為 fabcar_1 的 Chaincode 發起交易,使用 `-f` 選擇 Chaincode 上初始化的 function,使用 `-a` 輸入 Chainocde function 所需要的參數,之後可以使用 `bdk chaincode query` 和 Chaincode 查詢資訊 diff --git a/src/command/org/peer/add-system-channel.ts b/src/command/org/peer/add-system-channel.ts new file mode 100644 index 00000000..2eeee4c3 --- /dev/null +++ b/src/command/org/peer/add-system-channel.ts @@ -0,0 +1,71 @@ +import config from '../../../config' +import prompts from 'prompts' +import { Arguments, Argv } from 'yargs' +import { onCancel, ParamsError } from '../../../util' +import Peer from '../../../service/peer' +import { getOrdererList } from '../../../model/prompts/util' + +export const command = 'add-system-channel' + +export const desc = '加入新 Peer org 在 System Channel 中' + +interface OptType { + interactive: boolean + orderer: string + channelName: string + peerOrgName: string +} + +const ordererList = getOrdererList(config) + +export const builder = (yargs: Argv) => { + return yargs + .example('bdk org peer add-system-channel --interactive', 'Cathay BDK 互動式問答') + .example('bdk org peer add-system-channel --orderer orderer0.example.com:7050 --peer-org-name Org1', '使用 orderer0.example.com:7050 將 Org1 加入 System channel') + .option('interactive', { type: 'boolean', description: '是否使用 Cathay BDK 互動式問答', alias: 'i' }) + .option('peer-org-name', { type: 'string', description: '欲加入 Channel 中 Peer Org 的名稱', alias: 'n' }) + .option('orderer', { type: 'string', choices: ordererList, description: '選擇使用的 Orderer', alias: 'o' }) +} + +export const handler = async (argv: Arguments) => { + const peer = new Peer(config) + + const peerOrgName: string = await (async () => { + if (argv.interactive) { + return (await prompts([ + { + type: 'text', + name: 'name', + message: 'What is peer org name?', + initial: 'Test', + }, + ], { onCancel })).name + } else if (argv.peerOrgName) { + return argv.peerOrgName + } else { + throw new ParamsError('Invalid params: Required parameter missing') + } + })() + + const orderer: string = await (async () => { + if (argv.interactive) { + return (await prompts([ + { + type: 'select', + name: 'orderer', + message: 'Ordering service endpoint', + choices: ordererList.map(x => ({ + title: x, + value: x, + })), + }, + ], { onCancel })).orderer + } else if (argv.orderer) { + return argv.orderer + } else { + throw new ParamsError('Invalid params: Required parameter missing') + } + })() + + await peer.addOrgToSystemChannel({ channelName: 'system-channel', orgName: peerOrgName, orderer }) +} diff --git a/src/command/org/peer/update.ts b/src/command/org/peer/update.ts index 0e564fc2..1e28704b 100644 --- a/src/command/org/peer/update.ts +++ b/src/command/org/peer/update.ts @@ -21,7 +21,7 @@ const ordererList = getOrdererList(config) export const builder = (yargs: Argv) => { return yargs .example('bdk org peer update --interactive', 'Cathay BDK 互動式問答') - .example('bdk org peer update --peer peer0.example.com:7050 --channel-name test', '使用 peer0.example.com:7050 在名稱 test 的 channel 更新') + .example('bdk org peer update --orderer orderer0.example.com:7050 --channel-name test', '使用 orderer0.example.com:7050 在名稱 test 的 channel 更新') .option('interactive', { type: 'boolean', description: '是否使用 Cathay BDK 互動式問答', alias: 'i' }) .option('orderer', { type: 'string', choices: ordererList, description: '選擇使用的 Orderer', alias: 'o' }) .option('channel-name', { type: 'string', choices: channelList, description: 'Channel 的名稱', alias: 'c' }) diff --git a/src/instance/fabricInstance.ts b/src/instance/fabricInstance.ts index fc8e97f8..522f1597 100644 --- a/src/instance/fabricInstance.ts +++ b/src/instance/fabricInstance.ts @@ -104,35 +104,6 @@ export default class FabricInstance extends AbstractInstance { options) } - // * get AnchorPeers and Orderer of a channel - public async fetchChannelConfig ( - channelName: string, - outputFileName: string, - outputExtension: 'pb' | 'block', - orderer: string | undefined, - signType: OrgTypeEnum, - options?: OptionsType, - ): Promise { - return await this.infraRunCommand( - [ - 'peer', 'channel', 'fetch', 'config', - `${this.dockerPath}/channel-artifacts/${channelName}/${outputFileName}.${outputExtension}`, - '--channelID', channelName, - ].concat( - orderer - ? [ - '--orderer', orderer, - '--ordererTLSHostnameOverride', orderer.split(':')[0], - '--tls', '--cafile', `${this.dockerPath}/tlsca/${orderer.split(':')[0]}/ca.crt`, - ] - : [], - ), - signType, - undefined, - undefined, - options) - } - public async signConfigTx ( signType: OrgTypeEnum, channelName: string, @@ -335,21 +306,57 @@ export default class FabricInstance extends AbstractInstance { options) } + // * get AnchorPeers and Orderer of a channel + public async fetchChannelConfig ( + channelName: string, + outputFileName: string, + outputExtension: 'pb' | 'block' = 'block', + orderer: string | undefined, + signType: OrgTypeEnum, + options?: OptionsType, + ): Promise { + return await this.infraRunCommand( + [ + 'peer', 'channel', 'fetch', 'config', + `${this.dockerPath}/channel-artifacts/${channelName}/${outputFileName}.${outputExtension}`, + '--channelID', channelName, + ].concat( + orderer + ? [ + '--orderer', orderer, + '--ordererTLSHostnameOverride', orderer.split(':')[0], + '--tls', '--cafile', `${this.dockerPath}/tlsca/${orderer.split(':')[0]}/ca.crt`, + ] + : [], + ), + signType, + undefined, + undefined, + options) + } + // * get channel block 0 - public async fetchChannelBlock0 (orderer: string, + public async fetchChannelBlock0 ( channelName: string, fileName: string, + outputExtension: 'pb' | 'block' = 'block', + orderer: string | undefined, signType: OrgTypeEnum, options?: OptionsType): Promise { return await this.infraRunCommand( [ 'peer', 'channel', 'fetch', '0', - `${this.dockerPath}/channel-artifacts/${channelName}/${fileName}.block`, + `${this.dockerPath}/channel-artifacts/${channelName}/${fileName}.${outputExtension}`, '--channelID', channelName, - '--orderer', orderer, - '--ordererTLSHostnameOverride', orderer.split(':')[0], - '--tls', '--cafile', `${this.dockerPath}/tlsca/${orderer.split(':')[0]}/ca.crt`, - ], + ].concat( + orderer + ? [ + '--orderer', orderer, + '--ordererTLSHostnameOverride', orderer.split(':')[0], + '--tls', '--cafile', `${this.dockerPath}/tlsca/${orderer.split(':')[0]}/ca.crt`, + ] + : [], + ), signType, undefined, undefined, @@ -357,20 +364,27 @@ export default class FabricInstance extends AbstractInstance { } // * fetch channel newest block - public async fetchChannelNewestBlock (orderer: string, + public async fetchChannelNewestBlock ( channelName: string, - outputFileName: string, + fileName: string, + outputExtension: 'pb' | 'block' = 'block', + orderer: string | undefined, signType: OrgTypeEnum, options?: OptionsType): Promise { return await this.infraRunCommand( [ 'peer', 'channel', 'fetch', 'newest', - `${this.dockerPath}/channel-artifacts/${channelName}/${outputFileName}.block`, + `${this.dockerPath}/channel-artifacts/${channelName}/${fileName}.${outputExtension}`, '--channelID', channelName, - '--orderer', orderer, - '--ordererTLSHostnameOverride', orderer.split(':')[0], - '--tls', '--cafile', `${this.dockerPath}/tlsca/${orderer.split(':')[0]}/ca.crt`, - ], + ].concat( + orderer + ? [ + '--orderer', orderer, + '--ordererTLSHostnameOverride', orderer.split(':')[0], + '--tls', '--cafile', `${this.dockerPath}/tlsca/${orderer.split(':')[0]}/ca.crt`, + ] + : [], + ), signType, undefined, undefined, diff --git a/src/model/type/channel.type.ts b/src/model/type/channel.type.ts index ab5b083c..93b40859 100644 --- a/src/model/type/channel.type.ts +++ b/src/model/type/channel.type.ts @@ -108,10 +108,3 @@ export interface ChannelCreateChannelConfigSignType extends ChannelCreateChannel export interface ChannelCreateChannelConfigUpdateType extends ChannelCreateChannelConfigSignType { orderer: string } - -// TODO remove it -export interface FetchChannelConfigType { - orderer: string - channelName: string - orgType: OrgTypeEnum -} diff --git a/src/model/type/peer.type.ts b/src/model/type/peer.type.ts index 19df6a39..962b72da 100644 --- a/src/model/type/peer.type.ts +++ b/src/model/type/peer.type.ts @@ -28,7 +28,6 @@ export interface PeerAddType { } /** - * @requires orderer - [string] 使用 orderer 的 address 和 port * @requires channelName - [string] channel 的名稱 * @requires orgNames - [string array] peer org 的名稱 */ @@ -37,6 +36,13 @@ export interface PeerAddOrgToChannelType { orgName: string } +/** + * @requires orderer - [string] 使用 orderer 的 address 和 port + */ +export interface PeerAddOrgToSystemChannelType extends PeerAddOrgToChannelType { + orderer: string +} + export interface OrgSignEnvelopeType{ channelName: string } diff --git a/src/service/channel.ts b/src/service/channel.ts index b4429a45..4b6dd70e 100644 --- a/src/service/channel.ts +++ b/src/service/channel.ts @@ -97,9 +97,7 @@ export default class Channel extends AbstractService { logger.info(`[*] Channel Update Anchor Peer: add ${host} anchor peer config in ${channelName} - compute update`) - await this.decodeChannelConfig(channelName, Channel.channelConfigFileName(channelName).originalFileName, 'temp') - - const configBlock = JSON.parse(this.bdkFile.getChannelConfigString(channelName, 'temp')).data.data[0].payload.data.config + const configBlock = await this.getConfigBlock(channelName) this.bdkFile.createChannelConfigJson(channelName, Channel.channelConfigFileName(channelName).originalFileName, JSON.stringify(configBlock)) @@ -180,19 +178,19 @@ export default class Channel extends AbstractService { const { orderer, outputFileName, orgType, channelName } = data this.bdkFile.createChannelArtifact(channelName) - return await (new FabricInstance(this.config, this.infra)).fetchChannelNewestBlock(orderer, channelName, outputFileName, orgType || this.config.orgType) + return await (new FabricInstance(this.config, this.infra)).fetchChannelNewestBlock(channelName, outputFileName, 'block', orderer, orgType || this.config.orgType) }, fetchChannelGenesisBlock: async (data: ChannelFetchBlockType): Promise => { const { orderer, outputFileName, channelName, orgType } = data this.bdkFile.createChannelArtifact(channelName) - return await (new FabricInstance(this.config, this.infra)).fetchChannelBlock0(orderer, channelName, outputFileName, orgType || this.config.orgType) + return await (new FabricInstance(this.config, this.infra)).fetchChannelBlock0(channelName, outputFileName, 'block', orderer, orgType || this.config.orgType) }, fetchChannelConfig: async (data: ChannelFetchBlockType): Promise => { - const { channelName, outputFileName, orgType } = data + const { orderer, channelName, outputFileName, orgType } = data this.bdkFile.createChannelArtifact(channelName) - return await (new FabricInstance(this.config, this.infra)).fetchChannelConfig(channelName, outputFileName, 'block', undefined, orgType || this.config.orgType) + return await (new FabricInstance(this.config, this.infra)).fetchChannelConfig(channelName, outputFileName, 'block', orderer, orgType || this.config.orgType) }, } } @@ -277,16 +275,23 @@ export default class Channel extends AbstractService { */ public async fetchChannelConfig (channelName: string, signType: OrgTypeEnum, orderer?: string): Promise { this.bdkFile.createChannelFolder(channelName) - return await (new FabricInstance(this.config, this.infra)).fetchChannelConfig(channelName, Channel.channelConfigFileName(channelName).originalFileName, 'pb', orderer, signType) + return await (new FabricInstance(this.config, this.infra)).fetchChannelConfig(channelName, Channel.channelConfigFileName(channelName).fetchFileName, 'pb', orderer, signType) } /** @ignore */ - public async decodeChannelConfig (channelName: string, input: string, output: string) { + private async decodeChannelConfig (channelName: string, input: string, output: string) { await (new FabricTools(this.config, this.infra)).decodeProto(ConfigtxlatorEnum.BLOCK, channelName, input, output) } + /** @ignore */ + public async getConfigBlock (channelName: string) { + await this.decodeChannelConfig(channelName, Channel.channelConfigFileName(channelName).fetchFileName, 'temp') + return JSON.parse(this.bdkFile.getChannelConfigString(channelName, 'temp')).data.data[0].payload.data.config + } + public static channelConfigFileName (channelName: string) { return { + fetchFileName: `${channelName}_fetch`, originalFileName: `${channelName}_config_block`, modifiedFileName: `${channelName}_modified_config_block`, compareUpdatedConfigFileName: `${channelName}_config_update`, diff --git a/src/service/orderer.ts b/src/service/orderer.ts index ed7d5e11..06350a4e 100644 --- a/src/service/orderer.ts +++ b/src/service/orderer.ts @@ -6,7 +6,7 @@ import OrdererInstance from '../instance/orderer' import ConfigtxYaml from '../model/yaml/network/configtx' import FabricTools from '../instance/fabricTools' import Channel from './channel' -import { ChannelCreateChannelConfigComputeType, ChannelCreateChannelConfigSignType, ChannelCreateChannelConfigUpdateType, FetchChannelConfigType } from '../model/type/channel.type' +import { ChannelCreateChannelConfigComputeType, ChannelCreateChannelConfigSignType, ChannelCreateChannelConfigUpdateType } from '../model/type/channel.type' import { OrdererAddType, ConsenterType, OrdererUpType, OrdererAddOrgToChannelType, OrdererAddConsenterToChannelType, OrdererApproveType, OrdererUpdateType } from '../model/type/orderer.type' import { InfraRunnerResultType } from '../instance/infra/InfraRunner.interface' import { OrgOrdererCreateType } from '../model/type/org.type' @@ -187,14 +187,13 @@ export default class Orderer extends AbstractService { return { fetchChannelConfig: async (dto: OrdererAddOrgToChannelType): Promise => { logger.info('[*] add org to channel step1 (fetchChannelConfig)') - return await this.fetchChannelConfig({ orderer: dto.orderer, channelName: dto.channelName, orgType: this.config.orgType }) + return await (new Channel(this.config, this.infra)).fetchChannelConfig(dto.channelName, this.config.orgType, dto.orderer) }, orgConfigComputeUpdateConfigTx: async (dto: OrdererAddOrgToChannelType) => { logger.info('[*] add org to channel step2 (orgConfigComputeUpdateAndSignConfigTx)') const { channelName, orgName } = dto - await (new Channel(this.config, this.infra)).decodeChannelConfig(channelName, Channel.channelConfigFileName(channelName).originalFileName, 'temp') - const configBlock = JSON.parse(this.bdkFile.getChannelConfigString(channelName, 'temp')).data.data[0].payload.data.config + const configBlock = await (new Channel(this.config, this.infra)).getConfigBlock(channelName) this.bdkFile.createChannelConfigJson(channelName, Channel.channelConfigFileName(channelName).originalFileName, JSON.stringify(configBlock)) const newOrg = JSON.parse(this.bdkFile.getOrgConfigJson(orgName)) @@ -230,7 +229,7 @@ export default class Orderer extends AbstractService { return { fetchChannelConfig: async (dto: OrdererAddConsenterToChannelType): Promise => { logger.info('[*] add consenter to channel step1 (fetchChannelConfig)') - return await this.fetchChannelConfig({ orderer: dto.orderer, channelName: dto.channelName, orgType: this.config.orgType }) + return await (new Channel(this.config, this.infra)).fetchChannelConfig(dto.channelName, this.config.orgType, dto.orderer) }, hostnameComputeUpdateConfigTx: async (dto: OrdererAddConsenterToChannelType) => { logger.info('[*] add consenter to channel step2 (hostnameComputeUpdateAndSignConfigTx)') @@ -241,8 +240,7 @@ export default class Orderer extends AbstractService { const index = consenters.findIndex((x: ConsenterType) => x.host.split('.')[0] === dto.hostname) const consenter = consenters[index] - await (new Channel(this.config, this.infra)).decodeChannelConfig(channelName, Channel.channelConfigFileName(channelName).originalFileName, 'temp') - const configBlock = JSON.parse(this.bdkFile.getChannelConfigString(channelName, 'temp')).data.data[0].payload.data.config + const configBlock = await (new Channel(this.config, this.infra)).getConfigBlock(channelName) this.bdkFile.createChannelConfigJson(channelName, Channel.channelConfigFileName(channelName).originalFileName, JSON.stringify(configBlock)) configBlock.channel_group.groups.Orderer.values.ConsensusType.value.metadata.consenters.push({ @@ -287,9 +285,4 @@ export default class Orderer extends AbstractService { } return await (new Channel(this.config, this.infra)).createChannelConfigSteps().updateChannelConfig(channelCreateChannelConfigUpdate) } - - private fetchChannelConfig = async (dto: FetchChannelConfigType): Promise => { - const { orderer, channelName, orgType } = dto - return await (new Channel(this.config, this.infra)).fetchChannelConfig(channelName, orgType, orderer) - } } diff --git a/src/service/peer.ts b/src/service/peer.ts index 8b20901a..d06f0e36 100644 --- a/src/service/peer.ts +++ b/src/service/peer.ts @@ -10,7 +10,7 @@ import ConfigtxYaml from '../model/yaml/network/configtx' import FabricTools from '../instance/fabricTools' import Channel from './channel' import { ChannelCreateChannelConfigComputeType, ChannelCreateChannelConfigSignType, ChannelCreateChannelConfigUpdateType } from '../model/type/channel.type' -import { PeerUpType, PeerDownType, PeerAddType, PeerAddOrgToChannelType, PeerApproveType, PeerUpdateType } from '../model/type/peer.type' +import { PeerUpType, PeerDownType, PeerAddType, PeerAddOrgToChannelType, PeerApproveType, PeerUpdateType, PeerAddOrgToSystemChannelType } from '../model/type/peer.type' import { InfraRunnerResultType } from '../instance/infra/InfraRunner.interface' import { OrgPeerCreateType } from '../model/type/org.type' import { AbstractService } from './Service.abstract' @@ -189,7 +189,7 @@ export default class Peer extends AbstractService { } /** - * @description 在 channel 中加入 peer org(第一步) + * @description 在 channel 中加入 peer org */ public async addOrgToChannel (dto: PeerAddOrgToChannelType): Promise { await this.addOrgToChannelSteps().fetchChannelConfig(dto) @@ -202,17 +202,14 @@ export default class Peer extends AbstractService { public addOrgToChannelSteps () { return { fetchChannelConfig: async (dto: PeerAddOrgToChannelType): Promise => { - const { channelName, orgName } = dto - logger.info(`[*] Org Peer Add: add ${orgName} in ${channelName} step 1`) - return await (new Channel(this.config, this.infra)).fetchChannelConfig(channelName, this.config.orgType) + logger.info('[*] add org to channel step1 (fetchChannelConfig)') + return await (new Channel(this.config, this.infra)).fetchChannelConfig(dto.channelName, this.config.orgType) }, computeUpdateConfigTx: async (dto: PeerAddOrgToChannelType) => { + logger.info('[*] add org to channel step2 (orgConfigComputeUpdateAndSignConfigTx)') const { channelName, orgName } = dto - logger.info(`[*] Org Peer Add: add ${orgName} in ${channelName} step 2`) - - await (new Channel(this.config, this.infra)).decodeChannelConfig(channelName, Channel.channelConfigFileName(channelName).originalFileName, 'temp') - const configBlock = JSON.parse(this.bdkFile.getChannelConfigString(channelName, 'temp')).data.data[0].payload.data.config + const configBlock = await (new Channel(this.config, this.infra)).getConfigBlock(channelName) this.bdkFile.createChannelConfigJson(channelName, Channel.channelConfigFileName(channelName).originalFileName, JSON.stringify(configBlock)) const newOrg = JSON.parse(this.bdkFile.getOrgConfigJson(orgName)) @@ -231,6 +228,46 @@ export default class Peer extends AbstractService { } } + /** + * @description 在 system-channel 中加入 peer org + */ + public async addOrgToSystemChannel (dto: PeerAddOrgToSystemChannelType): Promise { + await this.addOrgToSystemChannelSteps().fetchChannelConfig(dto) + await this.addOrgToSystemChannelSteps().computeUpdateConfigTx(dto) + } + + /** + * @ignore + */ + public addOrgToSystemChannelSteps () { + return { + fetchChannelConfig: async (dto: PeerAddOrgToSystemChannelType): Promise => { + logger.info('[*] add org to system channel step1 (fetchChannelConfig)') + return await (new Channel(this.config, this.infra)).fetchChannelConfig(dto.channelName, this.config.orgType, dto.orderer) + }, + computeUpdateConfigTx: async (dto: PeerAddOrgToSystemChannelType) => { + logger.info('[*] add org to system channel step2 (orgConfigComputeUpdateAndSignConfigTx)') + const { channelName, orgName } = dto + + const configBlock = await (new Channel(this.config, this.infra)).getConfigBlock(channelName) + this.bdkFile.createChannelConfigJson(channelName, Channel.channelConfigFileName(channelName).originalFileName, JSON.stringify(configBlock)) + + const newOrg = JSON.parse(this.bdkFile.getOrgConfigJson(orgName)) + + configBlock.channel_group.groups.Consortiums.groups.AllOrganizationsConsortium.groups = { + ...configBlock.channel_group.groups.Consortiums.groups.AllOrganizationsConsortium.groups, + [orgName]: newOrg, + } + + this.bdkFile.createChannelConfigJson(channelName, Channel.channelConfigFileName(channelName).modifiedFileName, JSON.stringify(configBlock)) + const channelCreateChannelConfigUpdate: ChannelCreateChannelConfigComputeType = { + channelName, + } + return await (new Channel(this.config, this.infra)).createChannelConfigSteps().computeUpdateConfigTx(channelCreateChannelConfigUpdate) + }, + } + } + public async approve (dto: PeerApproveType): Promise { logger.info(`[*] Org Peer Approve: ${this.config.orgName} sign ${dto.channelName} config update`) const { channelName } = dto