import { logger , ParamsError } from '../util' ; import { NetworkCryptoConfigOrdererOrgType , NetworkCreateOrdererOrgType , NetworkOrdererPortType } from '../model/type/network.type' ; import CryptoConfigYaml from '../model/yaml/network/cryptoConfigYaml' ; import OrdererDockerComposeYaml from '../model/yaml/docker-compose/ordererDockerComposeYaml' ; import OrdererInstance from '../instance/orderer' ; import ConfigtxYaml from '../model/yaml/network/configtx' ; import FabricTools from '../instance/fabricTools' ; import Channel from './channel' ; import { ChannelCreateChannelConfigComputeType , ChannelCreateChannelConfigUpdateType } from '../model/type/channel.type' ; import { OrdererAddType , ConsenterType , OrdererUpType , OrdererAddOrgToChannelType , OrdererAddConsenterToChannelType } from '../model/type/orderer.type' ; import { InfraRunnerResultType } from '../instance/infra/InfraRunner.interface' ; import { OrgOrdererCreateType } from '../model/type/org.type' ; import { AbstractService } from './Service.abstract' ; import Org from './org' ; export default class Orderer extends AbstractService { description public async up ( dto ) { logger . debug ( `Orderer up: ${ dto . ordererHostname }` ) ; return await new OrdererInstance ( dto . ordererHostname , this . config , this . infra ) . up ( ) ; } description public async down ( dto ) { logger . debug ( `Orderer down: ${ dto . ordererHostname }` ) ; return await new OrdererInstance ( dto . ordererHostname , this . config , this . infra ) . down ( ) ; } description returns public async cryptogen ( dto ) { const { ordererOrgs } = dto ; logger . debug ( 'Orderer create cryptogen' ) ; const cryptoConfigYaml = new CryptoConfigYaml ( ) ; const ordererOrgCryptoConfigYaml = this . createCryptoConfigYaml ( ordererOrgs ) ; if ( ordererOrgCryptoConfigYaml && ordererOrgCryptoConfigYaml . value . OrdererOrgs ) { cryptoConfigYaml . setOrdererOrgs ( ordererOrgCryptoConfigYaml . value . OrdererOrgs ) ; } this . bdkFile . createCryptoConfigYaml ( cryptoConfigYaml ) ; await ( new FabricTools ( this . config , this . infra ) ) . cryptogenGenerateCryptoConfig ( ) ; } public ordererConsenter ( ordererOrg ) { const ordererOrgConsenter = [ ] ; const ports = ordererOrg . ports ?. map ( port => port . port ) ; ordererOrg . hostname . forEach ( ( hostname , index ) => { const serverCertBase64 = this . bdkFile . getOrdererServerCertToBase64 ( hostname , ordererOrg . domain ) ; ordererOrgConsenter . push ( { clientTlsCert : serverCertBase64 , host : `${ hostname }.${ ordererOrg . domain }` , port : ports ? ports [ index ] : + `7${ index }50` , serverTlsCert : serverCertBase64 , } ) ; } ) ; return ordererOrgConsenter ; } description returns public async createOrdererOrgConfigtxJSON ( dto ) { const { ordererOrgs } = dto ; for ( const ordererOrg of ordererOrgs ) { logger . debug ( `Orderer create configtx: ${ ordererOrg . name }` ) ; const configtxYaml = new ConfigtxYaml ( ) ; const ports = ordererOrg . ports ?. map ( port => port . port ) ; const newOrg = configtxYaml . addOrdererOrg ( { name : ordererOrg . name , mspDir : `${ this . config . infraConfig . dockerPath }/ordererOrganizations/${ ordererOrg . domain }/msp` , domain : ordererOrg . domain , hostname : ordererOrg . hostname , ports , } ) ; this . bdkFile . createConfigtxOrdererOrg ( newOrg ) ; await ( new Org ( this . config , this . infra ) ) . createOrgDefinitionJson ( ordererOrg . name , configtxYaml ) ; this . bdkFile . createOrdererOrgConsenterJson ( ordererOrg . name , JSON . stringify ( this . ordererConsenter ( ordererOrg ) ) ) ; } } description returns public copyTLSCa ( dto ) { const { ordererOrgs } = dto ; ordererOrgs . forEach ( ( ordererOrg ) => { logger . debug ( `Orderer create copyTLSCa: ${ ordererOrg . name }` ) ; for ( const ordererHostname of ordererOrg . hostname ) { this . bdkFile . copyOrdererOrgTLSCa ( ordererHostname , ordererOrg . domain ) ; } } ) ; } description returns public add ( dto ) { logger . debug ( 'Orderer add' ) ; this . createOrdererOrgDockerComposeYaml ( dto . orgName || this . config . orgName , dto . orgDomain || this . config . orgDomainName , dto . ordererHostnames , dto . genesisFileName , dto . ports ) ; } description returns public createDockerCompose ( dto ) { const { ordererOrgs , genesisFileName } = dto ; if ( ! genesisFileName ) { throw new ParamsError ( 'genesisFileName is required' ) ; } ordererOrgs . forEach ( ( ordererOrg ) => { logger . debug ( `Orderer create docker-compose: ${ ordererOrg . name }` ) ; this . createOrdererOrgDockerComposeYaml ( ordererOrg . name , ordererOrg . domain , ordererOrg . hostname , genesisFileName , ordererOrg . ports ) ; } ) ; } description param ordererName param ordererDomain param ordererHostnames param genesisFileName param ports returns public createOrdererOrgDockerComposeYaml ( ordererName , ordererDomain , ordererHostnames , genesisFileName , ports ? ) { ordererHostnames . forEach ( ( hostname , i ) => { const ordererDockerComposeYaml = new OrdererDockerComposeYaml ( ) ; ordererDockerComposeYaml . addNetwork ( this . config . networkName , { name : this . config . networkName , external : true } ) ; ordererDockerComposeYaml . addOrderer ( this . config , ordererName , ordererDomain , hostname , genesisFileName , ports ?. [ i ] . port , ports ?. [ i ] . operationPort , ports ?. [ i ] . isPublishPort , ports ?. [ i ] . isPublishOperationPort ) ; this . bdkFile . createDockerComposeYaml ( `${ hostname }.${ ordererDomain }` , ordererDockerComposeYaml ) ; ordererHostnames . forEach ( hostname => { this . bdkFile . createOrgConfigEnv ( `orderer-${ hostname }.${ ordererDomain }` , ordererDockerComposeYaml . getOrdererOrgEnv ( this . config , ordererName , hostname , ordererDomain , ports ?. [ 0 ] ?. port ) ) ; } ) ; } ) ; } description returns public createCryptoConfigYaml ( cryptoConfigOrdererOrg ) { const cryptConfigYaml = new CryptoConfigYaml ( ) ; cryptoConfigOrdererOrg . forEach ( x => cryptConfigYaml . addOrdererOrg ( { Name : x . name , Domain : x . domain , EnableNodeOUs : x . enableNodeOUs , Specs : x . hostname . map ( y => ( { Hostname : y } ) ) , } ) ) ; return cryptoConfigOrdererOrg . length === 0 ? null : cryptConfigYaml ; } description public async addOrgToChannel ( dto ) { logger . debug ( `Org Orderer Add Org: add ${ dto . orgName } in ${ dto . channelName }` ) ; await this . addOrgToChannelSteps ( ) . fetchChannelConfig ( dto ) ; await this . addOrgToChannelSteps ( ) . orgConfigComputeUpdateConfigTx ( dto ) ; } ignore public addOrgToChannelSteps ( ) { return { fetchChannelConfig : async ( dto ) : Promise < InfraRunnerResultType > => { logger . debug ( 'add org to channel step1 (fetchChannelConfig)' ) ; return await ( new Channel ( this . config , this . infra ) ) . fetchChannelConfig ( dto . channelName , this . config . orgType , dto . orderer ) ; } , orgConfigComputeUpdateConfigTx : async ( dto ) => { logger . debug ( 'add org to 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 . Orderer . groups = { ... configBlock . channel_group . groups . Orderer . groups , [ orgName ] : newOrg , } ; this . bdkFile . createChannelConfigJson ( channelName , Channel . channelConfigFileName ( channelName ) . modifiedFileName , JSON . stringify ( configBlock ) ) ; const channelCreateChannelConfigUpdate = { channelName , } ; return await ( new Channel ( this . config , this . infra ) ) . createChannelConfigSteps ( ) . computeUpdateConfigTx ( channelCreateChannelConfigUpdate ) ; } , } ; } description public async addConsenterToChannel ( dto ) { logger . debug ( `Org Orderer Add Consenter: add ${ dto . hostname } of ${ dto . orgName } in ${ dto . channelName }` ) ; await this . addConsenterToChannelSteps ( ) . fetchChannelConfig ( dto ) ; await this . addConsenterToChannelSteps ( ) . hostnameComputeUpdateConfigTx ( dto ) ; } ignore public addConsenterToChannelSteps ( ) { return { fetchChannelConfig : async ( dto ) : Promise < InfraRunnerResultType > => { logger . debug ( 'add consenter to channel step1 (fetchChannelConfig)' ) ; return await ( new Channel ( this . config , this . infra ) ) . fetchChannelConfig ( dto . channelName , this . config . orgType , dto . orderer ) ; } , hostnameComputeUpdateConfigTx : async ( dto ) => { logger . debug ( 'add consenter to channel step2 (hostnameComputeUpdateAndSignConfigTx)' ) ; const { orderer , channelName } = dto ; const consenters = JSON . parse ( this . bdkFile . getOrdererOrgConsenter ( dto . orgName ) ) ; const index = consenters . findIndex ( ( x ) => x . host . split ( '.' ) [ 0 ] === dto . hostname ) ; const consenter = consenters [ index ] ; 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 ( { clientTlsCert : consenter . clientTlsCert , host : consenter . host , port : consenter . port , serverTlsCert : consenter . serverTlsCert , } ) ; this . bdkFile . createChannelConfigJson ( channelName , Channel . channelConfigFileName ( channelName ) . modifiedFileName , JSON . stringify ( configBlock ) ) ; const channelCreateChannelConfigUpdate = { orderer , channelName , } ; return await ( new Channel ( this . config , this . infra ) ) . createChannelConfigSteps ( ) . computeUpdateConfigTx ( channelCreateChannelConfigUpdate ) ; } , } ; } }