Skip to content

Commit

Permalink
add discover to bdk chaincode commit
Browse files Browse the repository at this point in the history
  • Loading branch information
kth-tw committed Jan 17, 2022
1 parent ff4738b commit 0b45d31
Show file tree
Hide file tree
Showing 5 changed files with 161 additions and 47 deletions.
2 changes: 1 addition & 1 deletion cicd/test_script/steps/chaincode.sh
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ bdk chaincode approve -C ${CHANNEL_NAME} -l ${CHAINCODE_LABEL} -I # discover
export_env 'peer' ${PEER_ORG_NAME_ORG2} ${PEER_ORG_DOMAIN_ORG2} 'peer0'
bdk chaincode install -l ${CHAINCODE_LABEL}
bdk chaincode approve -C ${CHANNEL_NAME} -l ${CHAINCODE_LABEL} -I # discover
bdk chaincode commit -C ${CHANNEL_NAME} -l ${CHAINCODE_LABEL} -I --orderer ${ORDERER_ORG_URL_ORG0_ORDERER0} --peer-addresses ${PEER_ORG_URL_ORG0_PEER0} --peer-addresses ${PEER_ORG_URL_ORG1_PEER0} --peer-addresses ${PEER_ORG_URL_ORG2_PEER0}
bdk chaincode commit -C ${CHANNEL_NAME} -l ${CHAINCODE_LABEL} -I # discover

# invoke init
export_env 'peer' ${PEER_ORG_NAME_ORG0} ${PEER_ORG_DOMAIN_ORG0} 'peer0'
Expand Down
20 changes: 10 additions & 10 deletions docs/COMMANDS.md
Original file line number Diff line number Diff line change
Expand Up @@ -111,16 +111,16 @@ Description: 代表環境變數中 BDK_ORG_NAME 的 Peer org 同意 Chaincode

Description: 代表環境變數中 BDK_ORG_NAME 的 Peer org 發布 Chaincode

| Options | Type | Description | Required | Default |
| --------------------- | :-----: | -------------------------------------- | :------: | ------- |
| --help | boolean | Show help | |
| --version | boolean | Show version number | |
| -i, --interactive | boolean | 是否使用 Cathay BDK 互動式問答 | |
| -C, --channel-id | string | 選擇欲發布 Chaincode 在的 Channel 名稱 | |
| -l, --chaincode-label | string | Chaincode package 的標籤名稱 | |
| -I, --init-required | boolean | Chaincode 是否需要初始化 | |
| --orderer | string | 選擇 Orderer 同意 Chaincode | |
| --peer-addresses | array | 需要簽名的 Peer address | |
| Options | Type | Description | Required | Default |
| --------------------- | :-----: | ---------------------------------------------------- | :------: | ------- |
| --help | boolean | Show help | | |
| --version | boolean | Show version number | | |
| -i, --interactive | boolean | 是否使用 Cathay BDK 互動式問答 | | |
| -C, --channel-id | string | 選擇欲發布 Chaincode 在的 Channel 名稱 | | |
| -l, --chaincode-label | string | Chaincode package 的標籤名稱 | | |
| -I, --init-required | boolean | Chaincode 是否需要初始化 | | |
| --orderer | string | 選擇 Orderer 同意 Chaincode (若未輸入則使用discover) | | |
| --peer-addresses | array | 需要簽名的 Peer address (若未輸入則使用discover) | | |

### `bdk chaincode install`

Expand Down
107 changes: 77 additions & 30 deletions src/command/chaincode/commit.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { Arguments, Argv } from 'yargs'
import prompts from 'prompts'
import { logger, onCancel } from '../../util'
import { ChaincodeCommitType } from '../../model/type/chaincode.type'
import { ChaincodeCommitType, ChaincodeCommitWithoutDiscoverType } from '../../model/type/chaincode.type'
import Chaincode from '../../service/chaincode'
import Channel from '../../service/channel'
import config from '../../config'
Expand All @@ -24,13 +24,14 @@ const chaincodeList = getChaincodeList(config)
export const builder = (yargs: Argv<OptType>) => {
return yargs
.example('bdk chaincode commit --interactive', 'Cathay BDK 互動式問答')
.example('bdk chaincode commit --channel-id fabcar --chaincode-label test_1 --init-required --orderer orderer0.example.com:7050 --peer-addresses peer0.org1.example.com --peer-addresses peer0.org2.example.com', '使用 orderer0.example.com:7050 同意名稱為 test 中標籤為 test_1 的 Chaincode,此 Chaincode 需要初始化並且 Org1 和 Org2 的 Peer org 簽名')
.example('bdk chaincode commit --channel-id test --chaincode-label fabcar_1 --init-required', '使用 discover 自動選擇 peer 與 orderer 同意名稱為 test 的 channel 中標籤為 fabcar_1 的 Chaincode,此 Chaincode 需要初始化並且 Org1 和 Org2 的 Peer org 簽名')
.example('bdk chaincode commit --channel-id test --chaincode-label fabcar_1 --init-required --orderer orderer0.example.com:7050 --peer-addresses peer0.org1.example.com --peer-addresses peer0.org2.example.com', '使用 orderer0.example.com:7050 同意名稱為 test 的 channel 中標籤為 fabcar_1 的 Chaincode,此 Chaincode 需要初始化並且 Org1 和 Org2 的 Peer org 簽名')
.option('interactive', { type: 'boolean', description: '是否使用 Cathay BDK 互動式問答', alias: 'i' })
.option('channel-id', { type: 'string', description: '選擇欲發布 Chaincode 在的 Channel 名稱', alias: 'C' })
.option('chaincode-label', { type: 'string', description: 'Chaincode package 的標籤名稱', alias: 'l', choices: chaincodeList.map(x => `${x.name}_${x.version}`) })
.option('init-required', { type: 'boolean', description: 'Chaincode 是否需要初始化', alias: 'I' })
.option('orderer', { type: 'string', description: '選擇 Orderer 同意 Chaincode' })
.option('peer-addresses', { type: 'array', description: '需要簽名的 Peer address' })
.option('orderer', { type: 'string', description: '選擇 Orderer 同意 Chaincode (若未輸入則使用discover)' })
.option('peer-addresses', { type: 'array', description: '需要簽名的 Peer address (若未輸入則使用discover)' })
}

export const handler = async (argv: Arguments<OptType>) => {
Expand All @@ -39,7 +40,7 @@ export const handler = async (argv: Arguments<OptType>) => {
const chaincode = new Chaincode(config)
const channel = new Channel(config)

let commitChannelInput: ChaincodeCommitType
let commitChannelInput: ChaincodeCommitType | ChaincodeCommitWithoutDiscoverType
const chaincodeVersionMap: Map<string, number[]> = new Map()
chaincodeList.forEach(chaincode => {
chaincodeVersionMap.set(chaincode.name, [...(chaincodeVersionMap.get(chaincode.name) || []), chaincode.version])
Expand Down Expand Up @@ -89,45 +90,91 @@ export const handler = async (argv: Arguments<OptType>) => {

},
], { onCancel })
const channelGroup = await channel.getChannelGroup(channelId)

const { orderer, peerAddresses } = await prompts([
commitChannelInput = {
channelId,
chaincodeName,
chaincodeVersion,
initRequired,
}

const discoverOrderer = await prompts([
{
type: 'select',
name: 'orderer',
message: 'Ordering service endpoint',
choices: channelGroup.orderer.map(x => ({
title: x,
value: x,
})),
name: 'discoverOrderer',
message: 'Set orderer with discover?',
choices: [
{
title: 'Yes',
value: true,
},
{
title: 'No',
value: false,
},
],
},
], { onCancel })
if (discoverOrderer) {
const channelGroup = await channel.getChannelGroup(channelId)
const { orderer } = await prompts([
{
type: 'select',
name: 'orderer',
message: 'Ordering service endpoint',
choices: channelGroup.orderer.map(x => ({
title: x,
value: x,
})),
},
], { onCancel })
commitChannelInput = { ...commitChannelInput, orderer }
}

const discoverPeer = await prompts([
{
type: 'multiselect',
name: 'peerAddresses',
message: 'The addresses of the peers to connect to',
choices: channelGroup.anchorPeer.map(x => ({
title: x,
value: x,
})),
type: 'select',
name: 'discoverPeer',
message: 'Set peers with discover?',
choices: [
{
title: 'Yes',
value: true,
},
{
title: 'No',
value: false,
},
],
},
], { onCancel })

commitChannelInput = {
channelId,
chaincodeName,
chaincodeVersion,
initRequired,
orderer,
peerAddresses,
if (discoverPeer) {
const channelGroup = await channel.getChannelGroup(channelId)
const { peerAddresses } = await prompts([
{
type: 'multiselect',
name: 'peerAddresses',
message: 'The addresses of the peers to connect to',
choices: channelGroup.anchorPeer.map(x => ({
title: x,
value: x,
})),
},
], { onCancel })
commitChannelInput = { ...commitChannelInput, peerAddresses }
}
} else {
commitChannelInput = {
channelId: argv.channelId,
chaincodeName: argv.chaincodeLabel.split('_')[0],
chaincodeVersion: parseInt(argv.chaincodeLabel.split('_')[1]),
initRequired: argv.initRequired,
orderer: argv.orderer,
peerAddresses: argv.peerAddresses,
}
if (argv.orderer) {
commitChannelInput = { ...commitChannelInput, orderer: argv.orderer }
}
if (argv.peerAddresses) {
commitChannelInput = { ...commitChannelInput, peerAddresses: argv.peerAddresses }
}
}

Expand Down
11 changes: 9 additions & 2 deletions src/model/type/chaincode.type.ts
Original file line number Diff line number Diff line change
Expand Up @@ -50,14 +50,21 @@ export interface ChaincodeInstallStepSavePackageIdType extends ChaincodeInstallT
* @requires chaincodeName - [string] chaincode 的名稱
* @requires chaincodeVersion - [number] chaincode 的版本號碼
* @requires initRequired - [boolean] 使否需要初始化
* @requires orderer - [string] orderer 的 address 和 port
* @requires peerAddresses - [string array] peer address 和 port 的 array
*/
export interface ChaincodeCommitType {
channelId: string
chaincodeName: string
chaincodeVersion: number
initRequired: boolean
}

export type ChaincodeCommitWithoutDiscoverType = ChaincodeApproveType & ({ orderer: string } | { peerAddresses: string[] })

/**
* @requires orderer - [string] orderer 的 address 和 port
* @requires peerAddresses - [string array] peer address 和 port 的 array
*/
export interface ChaincodeCommitStepCommitOnInstanceType extends ChaincodeApproveType {
orderer: string
peerAddresses: string[]
}
Expand Down
68 changes: 64 additions & 4 deletions src/service/chaincode.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import path from 'path'
import FabricTools from '../instance/fabricTools'
import FabricInstance from '../instance/fabricInstance'
import { ChaincodeApproveStepApproveOnInstanceType, ChaincodeApproveType, ChaincodeApproveWithoutDiscoverType, ChaincodeCommitType, ChaincodeInstallStepSavePackageIdType, ChaincodeInstallType, ChaincodeInvokeType, ChaincodePackageType, ChaincodeQueryType } from '../model/type/chaincode.type'
import { ChaincodeApproveStepApproveOnInstanceType, ChaincodeApproveType, ChaincodeCommitStepCommitOnInstanceType, ChaincodeApproveWithoutDiscoverType, ChaincodeCommitType, ChaincodeInstallStepSavePackageIdType, ChaincodeInstallType, ChaincodeInvokeType, ChaincodePackageType, ChaincodeQueryType, ChaincodeCommitWithoutDiscoverType } from '../model/type/chaincode.type'
import { ParserType, AbstractService } from './Service.abstract'
import { logger } from '../util/logger'
import { DockerResultType, InfraRunnerResultType } from '../instance/infra/InfraRunner.interface'
Expand All @@ -14,6 +14,8 @@ interface ChaincodeParser extends ParserType {
getChaincodePackageId: (result: DockerResultType, options: {chaincodeLabel: string}) => string
getCommittedChaincode: (result: DockerResultType) => string[]
approveStepDiscover: (result: DockerResultType) => string
commitStepDiscoverChannelConfig: (result: DockerResultType) => string
commitStepDiscoverPeers: (result: DockerResultType) => string[]
}

export default class Chaincode extends AbstractService {
Expand All @@ -24,6 +26,20 @@ export default class Chaincode extends AbstractService {
getChaincodePackageId: (result, options: {chaincodeLabel: string}) => result.stdout.match(RegExp(`(?<=Package ID: )${options.chaincodeLabel}:.*(?=, Label: ${options.chaincodeLabel})`))?.[0] || '',
getCommittedChaincode: (result) => result.stdout.match(/(?<=Name: ).*(?=, Version)/g) || [],
approveStepDiscover: (result) => Discover.chooseOneRandomOrderer(Discover.parser.channelConfig(result)),
commitStepDiscoverChannelConfig: (result) => Discover.chooseOneRandomOrderer(Discover.parser.channelConfig(result)),
commitStepDiscoverPeers: (result) => {
const peerDiscoverResult = Discover.parser.peers(result)
const peerList: Map<string, string[]> = new Map()
peerDiscoverResult.forEach(peer => {
peerList.has(peer.MSPID) ? peerList.get(peer.MSPID)?.push(peer.Endpoint) : peerList.set(peer.MSPID, [peer.Endpoint])
})
const peers: string[] = []
Array.from(peerList.keys()).forEach(org => {
const peersOfOrg = peerList.get(org) || []
peers.push(randomFromArray(peersOfOrg))
})
return peers
},
}

/**
Expand Down Expand Up @@ -132,9 +148,53 @@ export default class Chaincode extends AbstractService {
/**
* @description 發布 chaincode
*/
public async commit (payload: ChaincodeCommitType): Promise<InfraRunnerResultType> {
logger.debug('Commit chaincode definition')
return await (new FabricInstance(this.config, this.infra)).commitChaincode(payload.channelId, payload.chaincodeName.replace('_', '-'), payload.chaincodeVersion, payload.initRequired, payload.orderer, payload.peerAddresses)
public async commit (payload: ChaincodeCommitType | ChaincodeCommitWithoutDiscoverType): Promise<InfraRunnerResultType> {
let orderer: string
let peerAddresses: string[]

if ('orderer' in payload) {
orderer = payload.orderer
} else {
const discoverChannelConfigResult = await this.commitSteps().discoverChannelConfig(payload)
if (!('stdout' in discoverChannelConfigResult)) {
logger.error('this service only for docker infra')
throw new Error('this service for docker infra')
}
orderer = Chaincode.parser.commitStepDiscoverChannelConfig(discoverChannelConfigResult)
}

if ('peerAddresses' in payload) {
peerAddresses = payload.peerAddresses
} else {
const discoverPeersResult = await this.commitSteps().discoverPeers(payload)
if (!('stdout' in discoverPeersResult)) {
logger.error('this service only for docker infra')
throw new Error('this service for docker infra')
}
peerAddresses = Chaincode.parser.commitStepDiscoverPeers(discoverPeersResult)
}

return await this.commitSteps().commitOnInstance({ ...payload, orderer, peerAddresses })
}

/**
* @ignore
*/
public commitSteps () {
return {
discoverPeers: async (payload: ChaincodeCommitType): Promise<InfraRunnerResultType> => {
logger.debug('commit chaincode step 1 (discover peers)')
return await (new Discover(this.config)).peers({ channel: payload.channelId })
},
discoverChannelConfig: async (payload: ChaincodeCommitType): Promise<InfraRunnerResultType> => {
logger.debug('commit chaincode step 2 (discover channel config)')
return await (new Discover(this.config)).channelConfig({ channel: payload.channelId })
},
commitOnInstance: async (payload: ChaincodeCommitStepCommitOnInstanceType): Promise<InfraRunnerResultType> => {
logger.debug('commit chaincode step 3 (commit)')
return await (new FabricInstance(this.config, this.infra)).commitChaincode(payload.channelId, payload.chaincodeName.replace('_', '-'), payload.chaincodeVersion, payload.initRequired, payload.orderer, payload.peerAddresses)
},
}
}

/**
Expand Down

0 comments on commit 0b45d31

Please sign in to comment.