From 355ebd800e90df7aeb6f12093ff8f9c0e6f39acf Mon Sep 17 00:00:00 2001 From: IITI-tushar <019saxenatushar@gmail.com> Date: Wed, 16 Apr 2025 16:24:45 +0530 Subject: [PATCH 01/10] updated code to new branch Signed-off-by: IITI-tushar <019saxenatushar@gmail.com> --- e2e/fabloCommands.test.ts | 11 +++++++++++ src/extend-config/extendChaincodesConfig.ts | 11 +++++++++++ src/extend-config/extendConfig.ts | 2 ++ 3 files changed, 24 insertions(+) diff --git a/e2e/fabloCommands.test.ts b/e2e/fabloCommands.test.ts index 65a893d79..a5d69a650 100644 --- a/e2e/fabloCommands.test.ts +++ b/e2e/fabloCommands.test.ts @@ -137,6 +137,17 @@ describe("validate", () => { expect(commandResult.output).toContain(" instance.orgs[0].organization.mspName : does not match pattern"); expect(commands.getFiles()).toEqual([]); }); + it("should throw an error for duplicate chaincode names across different channels", () => { + // Given + const fabloConfig = `${commands.relativeRoot}/samples/fablo-config-hlf2-2orgs-2chaincodes-private-data-duplicate.yaml`; + + // When + const commandResult = commands.fabloExec(`validate ${fabloConfig}`); + + // Then + expect(commandResult).toEqual(TestCommands.failure()); + expect(commandResult.output).toContain("Duplicate chaincode name found"); + }); }); describe("extend config", () => { diff --git a/src/extend-config/extendChaincodesConfig.ts b/src/extend-config/extendChaincodesConfig.ts index da7982046..17559cacb 100644 --- a/src/extend-config/extendChaincodesConfig.ts +++ b/src/extend-config/extendChaincodesConfig.ts @@ -37,11 +37,22 @@ const createPrivateCollectionConfig = ( }; }; +const checkUniqueChaincodeNames = (chaincodes: ChaincodeJson[]): void => { + const chaincodeNames = new Set(); + chaincodes.forEach((chaincode) => { + if (chaincodeNames.has(chaincode.name)) { + throw new Error(`Duplicate chaincode name found: '${chaincode.name}'`); + } + chaincodeNames.add(chaincode.name); + }); +}; + const extendChaincodesConfig = ( chaincodes: ChaincodeJson[], transformedChannels: ChannelConfig[], network: Global, ): ChaincodeConfig[] => { + checkUniqueChaincodeNames(chaincodes); return chaincodes.map((chaincode) => { const channel = transformedChannels.find((c) => c.name === chaincode.channel); if (!channel) throw new Error(`No matching channel with name '${chaincode.channel}'`); diff --git a/src/extend-config/extendConfig.ts b/src/extend-config/extendConfig.ts index 620d2797b..5254a5ac2 100644 --- a/src/extend-config/extendConfig.ts +++ b/src/extend-config/extendConfig.ts @@ -4,6 +4,7 @@ import { extendOrgsConfig } from "./extendOrgsConfig"; import extendGlobal from "./extendGlobal"; import extendChannelsConfig from "./extendChannelsConfig"; import extendChaincodesConfig from "./extendChaincodesConfig"; +import checkUniqueChaincodeNames from "./extendChaincodesConfig"; import extendHooksConfig from "./extendHooksConfig"; import { distinctOrdererHeads, mergeOrdererGroups } from "./mergeOrdererGroups"; @@ -22,6 +23,7 @@ const extendConfig = (json: FabloConfigJson): FabloConfigExtended => { const orderedHeadsDistinct = distinctOrdererHeads(ordererGroups); const channels = extendChannelsConfig(channelsJson, orgs, ordererGroups); + checkUniqueChaincodeNames(chaincodesJson, channels, global); const chaincodes = extendChaincodesConfig(chaincodesJson, channels, global); const hooks = extendHooksConfig(hooksJson); From 4ac26cf46dab0241f2228f2a62d11af3621e4b97 Mon Sep 17 00:00:00 2001 From: Tushar Saxena <019saxenatushar@gmail.com> Date: Fri, 16 May 2025 15:40:18 +0530 Subject: [PATCH 02/10] updated Signed-off-by: Tushar Saxena <019saxenatushar@gmail.com> --- ...2chaincodes-private-data.yaml.test.ts.snap | 1296 +++++++++++++++++ e2e/fabloCommands.test.ts | 18 +- ...gs-2chaincodes-private-data-duplicate.yaml | 59 + ...g-hlf2-2orgs-2chaincodes-private-data.yaml | 2 +- src/extend-config/extendChaincodesConfig.ts | 2 +- 5 files changed, 1373 insertions(+), 4 deletions(-) create mode 100644 samples/fablo-config-hlf2-2orgs-2chaincodes-private-data-duplicate.yaml diff --git a/e2e/__snapshots__/fablo-config-hlf2-2orgs-2chaincodes-private-data.yaml.test.ts.snap b/e2e/__snapshots__/fablo-config-hlf2-2orgs-2chaincodes-private-data.yaml.test.ts.snap index 1b41b84e0..3faf9999b 100644 --- a/e2e/__snapshots__/fablo-config-hlf2-2orgs-2chaincodes-private-data.yaml.test.ts.snap +++ b/e2e/__snapshots__/fablo-config-hlf2-2orgs-2chaincodes-private-data.yaml.test.ts.snap @@ -317,6 +317,272 @@ certificateAuthorities: " `; +exports[`samples/fablo-config-hlf2-2orgs-2chaincodes-private-data.yaml should create proper e2e/__tmp__/samples/fablo-config-hlf2-2orgs-2chaincodes-private-data.yaml.tmpdir/fablo-target/fabric-config/connection-profiles/connection-profile-orderer1.json from samples/fablo-config-hlf2-2orgs-2chaincodes-private-data.yaml 1`] = ` +"{ + "name": "fablo-test-network-orderer1", + "description": "Connection profile for Orderer1 in Fablo network", + "version": "1.0.0", + "client": { + "organization": "Orderer1" + }, + "organizations": { + "Orderer1": { + "mspid": "Orderer1MSP", + "peers": [ + "peer0.org1.example.com", + "peer1.org1.example.com", + "peer0.org2.example.com", + "peer1.org2.example.com" + ], + "certificateAuthorities": [ + "ca.orderer1.com" + ] + } + }, + "peers": { + "peer0.org1.example.com": { + "url": "grpcs://localhost:7061", + "tlsCACerts": { + "path": "/samples/fablo-target/fabric-config/crypto-config/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/tls/ca.crt" + }, + "grpcOptions": { + "ssl-target-name-override": "peer0.org1.example.com" + } + }, + "peer1.org1.example.com": { + "url": "grpcs://localhost:7062", + "tlsCACerts": { + "path": "/samples/fablo-target/fabric-config/crypto-config/peerOrganizations/org1.example.com/peers/peer1.org1.example.com/tls/ca.crt" + }, + "grpcOptions": { + "ssl-target-name-override": "peer1.org1.example.com" + } + }, + "peer0.org2.example.com": { + "url": "grpcs://localhost:7081", + "tlsCACerts": { + "path": "/samples/fablo-target/fabric-config/crypto-config/peerOrganizations/org2.example.com/peers/peer0.org2.example.com/tls/ca.crt" + }, + "grpcOptions": { + "ssl-target-name-override": "peer0.org2.example.com" + } + }, + "peer1.org2.example.com": { + "url": "grpcs://localhost:7082", + "tlsCACerts": { + "path": "/samples/fablo-target/fabric-config/crypto-config/peerOrganizations/org2.example.com/peers/peer1.org2.example.com/tls/ca.crt" + }, + "grpcOptions": { + "ssl-target-name-override": "peer1.org2.example.com" + } + } + }, + "certificateAuthorities": { + "ca.orderer1.com": { + "url": "https://localhost:7020", + "caName": "ca.orderer1.com", + "tlsCACerts": { + "path": "/samples/fablo-target/fabric-config/crypto-config/peerOrganizations/orderer1.com/ca/ca.orderer1.com-cert.pem" + }, + "httpOptions": { + "verify": false + } + } + } +} +" +`; + +exports[`samples/fablo-config-hlf2-2orgs-2chaincodes-private-data.yaml should create proper e2e/__tmp__/samples/fablo-config-hlf2-2orgs-2chaincodes-private-data.yaml.tmpdir/fablo-target/fabric-config/connection-profiles/connection-profile-orderer1.yaml from samples/fablo-config-hlf2-2orgs-2chaincodes-private-data.yaml 1`] = ` +"name: fablo-test-network-orderer1 +description: Connection profile for Orderer1 in Fablo network +version: 1.0.0 +client: + organization: Orderer1 +organizations: + Orderer1: + mspid: Orderer1MSP + peers: + - peer0.org1.example.com + - peer1.org1.example.com + - peer0.org2.example.com + - peer1.org2.example.com + certificateAuthorities: + - ca.orderer1.com +peers: + peer0.org1.example.com: + url: grpcs://localhost:7061 + tlsCACerts: + path: >- + /samples/fablo-target/fabric-config/crypto-config/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/tls/ca.crt + grpcOptions: + ssl-target-name-override: peer0.org1.example.com + peer1.org1.example.com: + url: grpcs://localhost:7062 + tlsCACerts: + path: >- + /samples/fablo-target/fabric-config/crypto-config/peerOrganizations/org1.example.com/peers/peer1.org1.example.com/tls/ca.crt + grpcOptions: + ssl-target-name-override: peer1.org1.example.com + peer0.org2.example.com: + url: grpcs://localhost:7081 + tlsCACerts: + path: >- + /samples/fablo-target/fabric-config/crypto-config/peerOrganizations/org2.example.com/peers/peer0.org2.example.com/tls/ca.crt + grpcOptions: + ssl-target-name-override: peer0.org2.example.com + peer1.org2.example.com: + url: grpcs://localhost:7082 + tlsCACerts: + path: >- + /samples/fablo-target/fabric-config/crypto-config/peerOrganizations/org2.example.com/peers/peer1.org2.example.com/tls/ca.crt + grpcOptions: + ssl-target-name-override: peer1.org2.example.com +certificateAuthorities: + ca.orderer1.com: + url: https://localhost:7020 + caName: ca.orderer1.com + tlsCACerts: + path: >- + /samples/fablo-target/fabric-config/crypto-config/peerOrganizations/orderer1.com/ca/ca.orderer1.com-cert.pem + httpOptions: + verify: false +" +`; + +exports[`samples/fablo-config-hlf2-2orgs-2chaincodes-private-data.yaml should create proper e2e/__tmp__/samples/fablo-config-hlf2-2orgs-2chaincodes-private-data.yaml.tmpdir/fablo-target/fabric-config/connection-profiles/connection-profile-orderer2.json from samples/fablo-config-hlf2-2orgs-2chaincodes-private-data.yaml 1`] = ` +"{ + "name": "fablo-test-network-orderer2", + "description": "Connection profile for Orderer2 in Fablo network", + "version": "1.0.0", + "client": { + "organization": "Orderer2" + }, + "organizations": { + "Orderer2": { + "mspid": "Orderer2MSP", + "peers": [ + "peer0.org1.example.com", + "peer1.org1.example.com", + "peer0.org2.example.com", + "peer1.org2.example.com" + ], + "certificateAuthorities": [ + "ca.orderer2.com" + ] + } + }, + "peers": { + "peer0.org1.example.com": { + "url": "grpcs://localhost:7061", + "tlsCACerts": { + "path": "/samples/fablo-target/fabric-config/crypto-config/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/tls/ca.crt" + }, + "grpcOptions": { + "ssl-target-name-override": "peer0.org1.example.com" + } + }, + "peer1.org1.example.com": { + "url": "grpcs://localhost:7062", + "tlsCACerts": { + "path": "/samples/fablo-target/fabric-config/crypto-config/peerOrganizations/org1.example.com/peers/peer1.org1.example.com/tls/ca.crt" + }, + "grpcOptions": { + "ssl-target-name-override": "peer1.org1.example.com" + } + }, + "peer0.org2.example.com": { + "url": "grpcs://localhost:7081", + "tlsCACerts": { + "path": "/samples/fablo-target/fabric-config/crypto-config/peerOrganizations/org2.example.com/peers/peer0.org2.example.com/tls/ca.crt" + }, + "grpcOptions": { + "ssl-target-name-override": "peer0.org2.example.com" + } + }, + "peer1.org2.example.com": { + "url": "grpcs://localhost:7082", + "tlsCACerts": { + "path": "/samples/fablo-target/fabric-config/crypto-config/peerOrganizations/org2.example.com/peers/peer1.org2.example.com/tls/ca.crt" + }, + "grpcOptions": { + "ssl-target-name-override": "peer1.org2.example.com" + } + } + }, + "certificateAuthorities": { + "ca.orderer2.com": { + "url": "https://localhost:7040", + "caName": "ca.orderer2.com", + "tlsCACerts": { + "path": "/samples/fablo-target/fabric-config/crypto-config/peerOrganizations/orderer2.com/ca/ca.orderer2.com-cert.pem" + }, + "httpOptions": { + "verify": false + } + } + } +} +" +`; + +exports[`samples/fablo-config-hlf2-2orgs-2chaincodes-private-data.yaml should create proper e2e/__tmp__/samples/fablo-config-hlf2-2orgs-2chaincodes-private-data.yaml.tmpdir/fablo-target/fabric-config/connection-profiles/connection-profile-orderer2.yaml from samples/fablo-config-hlf2-2orgs-2chaincodes-private-data.yaml 1`] = ` +"name: fablo-test-network-orderer2 +description: Connection profile for Orderer2 in Fablo network +version: 1.0.0 +client: + organization: Orderer2 +organizations: + Orderer2: + mspid: Orderer2MSP + peers: + - peer0.org1.example.com + - peer1.org1.example.com + - peer0.org2.example.com + - peer1.org2.example.com + certificateAuthorities: + - ca.orderer2.com +peers: + peer0.org1.example.com: + url: grpcs://localhost:7061 + tlsCACerts: + path: >- + /samples/fablo-target/fabric-config/crypto-config/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/tls/ca.crt + grpcOptions: + ssl-target-name-override: peer0.org1.example.com + peer1.org1.example.com: + url: grpcs://localhost:7062 + tlsCACerts: + path: >- + /samples/fablo-target/fabric-config/crypto-config/peerOrganizations/org1.example.com/peers/peer1.org1.example.com/tls/ca.crt + grpcOptions: + ssl-target-name-override: peer1.org1.example.com + peer0.org2.example.com: + url: grpcs://localhost:7081 + tlsCACerts: + path: >- + /samples/fablo-target/fabric-config/crypto-config/peerOrganizations/org2.example.com/peers/peer0.org2.example.com/tls/ca.crt + grpcOptions: + ssl-target-name-override: peer0.org2.example.com + peer1.org2.example.com: + url: grpcs://localhost:7082 + tlsCACerts: + path: >- + /samples/fablo-target/fabric-config/crypto-config/peerOrganizations/org2.example.com/peers/peer1.org2.example.com/tls/ca.crt + grpcOptions: + ssl-target-name-override: peer1.org2.example.com +certificateAuthorities: + ca.orderer2.com: + url: https://localhost:7040 + caName: ca.orderer2.com + tlsCACerts: + path: >- + /samples/fablo-target/fabric-config/crypto-config/peerOrganizations/orderer2.com/ca/ca.orderer2.com-cert.pem + httpOptions: + verify: false +" +`; + exports[`samples/fablo-config-hlf2-2orgs-2chaincodes-private-data.yaml should create proper e2e/__tmp__/samples/fablo-config-hlf2-2orgs-2chaincodes-private-data.yaml.tmpdir/fablo-target/fabric-config/connection-profiles/connection-profile-org1.json from samples/fablo-config-hlf2-2orgs-2chaincodes-private-data.yaml 1`] = ` "{ "name": "fablo-test-network-org1", @@ -482,6 +748,34 @@ exports[`samples/fablo-config-hlf2-2orgs-2chaincodes-private-data.yaml should cr " `; +exports[`samples/fablo-config-hlf2-2orgs-2chaincodes-private-data.yaml should create proper e2e/__tmp__/samples/fablo-config-hlf2-2orgs-2chaincodes-private-data.yaml.tmpdir/fablo-target/fabric-config/crypto-config-orderer1.yaml from samples/fablo-config-hlf2-2orgs-2chaincodes-private-data.yaml 1`] = ` +"PeerOrgs: + - Name: Orderer1 + Domain: orderer1.com + Specs: + - Hostname: orderer0.group1 + - Hostname: orderer1.group1 + - Hostname: orderer2.group1 + Template: + Count: 0 + Users: + Count: 1 +" +`; + +exports[`samples/fablo-config-hlf2-2orgs-2chaincodes-private-data.yaml should create proper e2e/__tmp__/samples/fablo-config-hlf2-2orgs-2chaincodes-private-data.yaml.tmpdir/fablo-target/fabric-config/crypto-config-orderer2.yaml from samples/fablo-config-hlf2-2orgs-2chaincodes-private-data.yaml 1`] = ` +"PeerOrgs: + - Name: Orderer2 + Domain: orderer2.com + Specs: + - Hostname: orderer0.group2 + Template: + Count: 0 + Users: + Count: 1 +" +`; + exports[`samples/fablo-config-hlf2-2orgs-2chaincodes-private-data.yaml should create proper e2e/__tmp__/samples/fablo-config-hlf2-2orgs-2chaincodes-private-data.yaml.tmpdir/fablo-target/fabric-config/crypto-config-org1.yaml from samples/fablo-config-hlf2-2orgs-2chaincodes-private-data.yaml 1`] = ` "PeerOrgs: - Name: Org1 @@ -1024,6 +1318,1008 @@ metrics: " `; +exports[`samples/fablo-config-hlf2-2orgs-2chaincodes-private-data.yaml should create proper e2e/__tmp__/samples/fablo-config-hlf2-2orgs-2chaincodes-private-data.yaml.tmpdir/fablo-target/fabric-config/fabric-ca-server-config/orderer1.com/fabric-ca-server-config.yaml from samples/fablo-config-hlf2-2orgs-2chaincodes-private-data.yaml 1`] = ` +"############################################################################# +# This is a configuration file for the fabric-ca-server command. +# +# COMMAND LINE ARGUMENTS AND ENVIRONMENT VARIABLES +# ------------------------------------------------ +# Each configuration element can be overridden via command line +# arguments or environment variables. The precedence for determining +# the value of each element is as follows: +# 1) command line argument +# Examples: +# a) --port 443 +# To set the listening port +# b) --ca.keyfile ../mykey.pem +# To set the "keyfile" element in the "ca" section below; +# note the '.' separator character. +# 2) environment variable +# Examples: +# a) FABRIC_CA_SERVER_PORT=443 +# To set the listening port +# b) FABRIC_CA_SERVER_CA_KEYFILE="../mykey.pem" +# To set the "keyfile" element in the "ca" section below; +# note the '_' separator character. +# 3) configuration file +# 4) default value (if there is one) +# All default values are shown beside each element below. +# +# FILE NAME ELEMENTS +# ------------------ +# The value of all fields whose name ends with "file" or "files" are +# name or names of other files. +# For example, see "tls.certfile" and "tls.clientauth.certfiles". +# The value of each of these fields can be a simple filename, a +# relative path, or an absolute path. If the value is not an +# absolute path, it is interpreted as being relative to the location +# of this configuration file. +# +############################################################################# + +# Version of config file +version: 1.5.5 + +# Server's listening port (default: 7054) +port: 7054 + +# Cross-Origin Resource Sharing (CORS) +cors: + enabled: false + origins: + - "*" + +# Enables debug logging (default: false) +debug: false + +# Size limit of an acceptable CRL in bytes (default: 512000) +crlsizelimit: 512000 + +############################################################################# +# TLS section for the server's listening port +# +# The following types are supported for client authentication: NoClientCert, +# RequestClientCert, RequireAnyClientCert, VerifyClientCertIfGiven, +# and RequireAndVerifyClientCert. +# +# Certfiles is a list of root certificate authorities that the server uses +# when verifying client certificates. +############################################################################# +tls: + # Enable TLS (default: false) + enabled: false + # TLS for the server's listening port + certfile: + keyfile: + clientauth: + type: noclientcert + certfiles: + +############################################################################# +# The CA section contains information related to the Certificate Authority +# including the name of the CA, which should be unique for all members +# of a blockchain network. It also includes the key and certificate files +# used when issuing enrollment certificates (ECerts). +# The chainfile (if it exists) contains the certificate chain which +# should be trusted for this CA, where the 1st in the chain is always the +# root CA certificate. +############################################################################# +ca: + # Name of this CA + name: + # Key file (is only used to import a private key into BCCSP) + keyfile: + # Certificate file (default: ca-cert.pem) + certfile: + # Chain file + chainfile: + +############################################################################# +# The gencrl REST endpoint is used to generate a CRL that contains revoked +# certificates. This section contains configuration options that are used +# during gencrl request processing. +############################################################################# +crl: + # Specifies expiration for the generated CRL. The number of hours + # specified by this property is added to the UTC time, the resulting time + # is used to set the 'Next Update' date of the CRL. + expiry: 24h + +############################################################################# +# The registry section controls how the fabric-ca-server does two things: +# 1) authenticates enrollment requests which contain a username and password +# (also known as an enrollment ID and secret). +# 2) once authenticated, retrieves the identity's attribute names and values. +# These attributes are useful for making access control decisions in +# chaincode. +# There are two main configuration options: +# 1) The fabric-ca-server is the registry. +# This is true if "ldap.enabled" in the ldap section below is false. +# 2) An LDAP server is the registry, in which case the fabric-ca-server +# calls the LDAP server to perform these tasks. +# This is true if "ldap.enabled" in the ldap section below is true, +# which means this "registry" section is ignored. +############################################################################# +registry: + # Maximum number of times a password/secret can be reused for enrollment + # (default: -1, which means there is no limit) + maxenrollments: -1 + + # Contains identity information which is used when LDAP is disabled + identities: + - name: admin + pass: adminpw + type: client + affiliation: "" + attrs: + hf.Registrar.Roles: "*" + hf.Registrar.DelegateRoles: "*" + hf.Revoker: true + hf.IntermediateCA: true + hf.GenCRL: true + hf.Registrar.Attributes: "*" + hf.AffiliationMgr: true + +############################################################################# +# Database section +# Supported types are: "sqlite3", "postgres", and "mysql". +# The datasource value depends on the type. +# If the type is "sqlite3", the datasource value is a file name to use +# as the database store. Since "sqlite3" is an embedded database, it +# may not be used if you want to run the fabric-ca-server in a cluster. +# To run the fabric-ca-server in a cluster, you must choose "postgres" +# or "mysql". +############################################################################# +db: + type: sqlite3 + datasource: fabric-ca-server.db + tls: + enabled: false + certfiles: + client: + certfile: + keyfile: + +############################################################################# +# LDAP section +# If LDAP is enabled, the fabric-ca-server calls LDAP to: +# 1) authenticate enrollment ID and secret (i.e. username and password) +# for enrollment requests; +# 2) To retrieve identity attributes +############################################################################# +ldap: + # Enables or disables the LDAP client (default: false) + # If this is set to true, the "registry" section is ignored. + enabled: false + # The URL of the LDAP server + url: ldap://:@:/ + # TLS configuration for the client connection to the LDAP server + tls: + certfiles: + client: + certfile: + keyfile: + # Attribute related configuration for mapping from LDAP entries to Fabric CA attributes + attribute: + # 'names' is an array of strings containing the LDAP attribute names which are + # requested from the LDAP server for an LDAP identity's entry + names: ['uid', 'member'] + # The 'converters' section is used to convert an LDAP entry to the value of + # a fabric CA attribute. + # For example, the following converts an LDAP 'uid' attribute + # whose value begins with 'revoker' to a fabric CA attribute + # named "hf.Revoker" with a value of "true" (because the boolean expression + # evaluates to true). + # converters: + # - name: hf.Revoker + # value: attr("uid") =~ "revoker*" + converters: + - name: + value: + # The 'maps' section contains named maps which may be referenced by the 'map' + # function in the 'converters' section to map LDAP responses to arbitrary values. + # For example, assume a user has an LDAP attribute named 'member' which has multiple + # values which are each a distinguished name (i.e. a DN). For simplicity, assume the + # values of the 'member' attribute are 'dn1', 'dn2', and 'dn3'. + # Further assume the following configuration. + # converters: + # - name: hf.Registrar.Roles + # value: map(attr("member"),"groups") + # maps: + # groups: + # - name: dn1 + # value: peer + # - name: dn2 + # value: client + # The value of the user's 'hf.Registrar.Roles' attribute is then computed to be + # "peer,client,dn3". This is because the value of 'attr("member")' is + # "dn1,dn2,dn3", and the call to 'map' with a 2nd argument of + # "group" replaces "dn1" with "peer" and "dn2" with "client". + maps: + groups: + - name: + value: + +############################################################################# +# Affiliations section. Fabric CA server can be bootstrapped with the +# affiliations specified in this section. Affiliations are specified as maps. +# For example: +# businessunit1: +# department1: +# - team1 +# businessunit2: +# - department2 +# - department3 +# +# Affiliations are hierarchical in nature. In the above example, +# department1 (used as businessunit1.department1) is the child of businessunit1. +# team1 (used as businessunit1.department1.team1) is the child of department1. +# department2 (used as businessunit2.department2) and department3 (businessunit2.department3) +# are children of businessunit2. +# Note: Affiliations are case sensitive except for the non-leaf affiliations +# (like businessunit1, department1, businessunit2) that are specified in the configuration file, +# which are always stored in lower case. +############################################################################# +affiliations: + orderer1: + +############################################################################# +# Signing section +# +# The "default" subsection is used to sign enrollment certificates; +# the default expiration ("expiry" field) is "8760h", which is 1 year in hours. +# +# The "ca" profile subsection is used to sign intermediate CA certificates; +# the default expiration ("expiry" field) is "43800h" which is 5 years in hours. +# Note that "isca" is true, meaning that it issues a CA certificate. +# A maxpathlen of 0 means that the intermediate CA cannot issue other +# intermediate CA certificates, though it can still issue end entity certificates. +# (See RFC 5280, section 4.2.1.9) +# +# The "tls" profile subsection is used to sign TLS certificate requests; +# the default expiration ("expiry" field) is "8760h", which is 1 year in hours. +############################################################################# +signing: + default: + usage: + - digital signature + expiry: 8760h + profiles: + ca: + usage: + - cert sign + - crl sign + expiry: 43800h + caconstraint: + isca: true + maxpathlen: 0 + tls: + usage: + - signing + - key encipherment + - server auth + - client auth + - key agreement + expiry: 8760h + +########################################################################### +# Certificate Signing Request (CSR) section. +# This controls the creation of the root CA certificate. +# The expiration for the root CA certificate is configured with the +# "ca.expiry" field below, whose default value is "131400h" which is +# 15 years in hours. +# The pathlength field is used to limit CA certificate hierarchy as described +# in section 4.2.1.9 of RFC 5280. +# Examples: +# 1) No pathlength value means no limit is requested. +# 2) pathlength == 1 means a limit of 1 is requested which is the default for +# a root CA. This means the root CA can issue intermediate CA certificates, +# but these intermediate CAs may not in turn issue other CA certificates +# though they can still issue end entity certificates. +# 3) pathlength == 0 means a limit of 0 is requested; +# this is the default for an intermediate CA, which means it can not issue +# CA certificates though it can still issue end entity certificates. +########################################################################### +csr: + cn: fabric-ca-server + keyrequest: + algo: ecdsa + size: 256 + names: + - C: US + ST: "North Carolina" + L: + O: Hyperledger + OU: Fabric + hosts: + - 483cccf16a98 + - localhost + ca: + expiry: 131400h + pathlength: 1 + +########################################################################### +# Each CA can issue both X509 enrollment certificate as well as Idemix +# Credential. This section specifies configuration for the issuer component +# that is responsible for issuing Idemix credentials. +########################################################################### +idemix: + # Specifies pool size for revocation handles. A revocation handle is an unique identifier of an + # Idemix credential. The issuer will create a pool revocation handles of this specified size. When + # a credential is requested, issuer will get handle from the pool and assign it to the credential. + # Issuer will repopulate the pool with new handles when the last handle in the pool is used. + # A revocation handle and credential revocation information (CRI) are used to create non revocation proof + # by the prover to prove to the verifier that her credential is not revoked. + rhpoolsize: 1000 + + # The Idemix credential issuance is a two step process. First step is to get a nonce from the issuer + # and second step is send credential request that is constructed using the nonce to the isuser to + # request a credential. This configuration property specifies expiration for the nonces. By default is + # nonces expire after 15 seconds. The value is expressed in the time.Duration format (see https://golang.org/pkg/time/#ParseDuration). + nonceexpiration: 15s + + # Specifies interval at which expired nonces are removed from datastore. Default value is 15 minutes. + # The value is expressed in the time.Duration format (see https://golang.org/pkg/time/#ParseDuration) + noncesweepinterval: 15m + +############################################################################# +# BCCSP (BlockChain Crypto Service Provider) section is used to select which +# crypto library implementation to use +############################################################################# +bccsp: + default: SW + sw: + hash: SHA2 + security: 256 + filekeystore: + # The directory used for the software file-based keystore + keystore: msp/keystore + +############################################################################# +# Multi CA section +# +# Each Fabric CA server contains one CA by default. This section is used +# to configure multiple CAs in a single server. +# +# 1) --cacount +# Automatically generate non-default CAs. The names of these +# additional CAs are "ca1", "ca2", ... "caN", where "N" is +# This is particularly useful in a development environment to quickly set up +# multiple CAs. Note that, this config option is not applicable to intermediate CA server +# i.e., Fabric CA server that is started with intermediate.parentserver.url config +# option (-u command line option) +# +# 2) --cafiles +# For each CA config file in the list, generate a separate signing CA. Each CA +# config file in this list MAY contain all of the same elements as are found in +# the server config file except port, debug, and tls sections. +# +# Examples: +# fabric-ca-server start -b admin:adminpw --cacount 2 +# +# fabric-ca-server start -b admin:adminpw --cafiles ca/ca1/fabric-ca-server-config.yaml +# --cafiles ca/ca2/fabric-ca-server-config.yaml +# +############################################################################# + +cacount: + +cafiles: + +############################################################################# +# Intermediate CA section +# +# The relationship between servers and CAs is as follows: +# 1) A single server process may contain or function as one or more CAs. +# This is configured by the "Multi CA section" above. +# 2) Each CA is either a root CA or an intermediate CA. +# 3) Each intermediate CA has a parent CA which is either a root CA or another intermediate CA. +# +# This section pertains to configuration of #2 and #3. +# If the "intermediate.parentserver.url" property is set, +# then this is an intermediate CA with the specified parent +# CA. +# +# parentserver section +# url - The URL of the parent server +# caname - Name of the CA to enroll within the server +# +# enrollment section used to enroll intermediate CA with parent CA +# profile - Name of the signing profile to use in issuing the certificate +# label - Label to use in HSM operations +# +# tls section for secure socket connection +# certfiles - PEM-encoded list of trusted root certificate files +# client: +# certfile - PEM-encoded certificate file for when client authentication +# is enabled on server +# keyfile - PEM-encoded key file for when client authentication +# is enabled on server +############################################################################# +intermediate: + parentserver: + url: + caname: + + enrollment: + hosts: + profile: + label: + + tls: + certfiles: + client: + certfile: + keyfile: + +############################################################################# +# CA configuration section +# +# Configure the number of incorrect password attempts are allowed for +# identities. By default, the value of 'passwordattempts' is 10, which +# means that 10 incorrect password attempts can be made before an identity get +# locked out. +############################################################################# +cfg: + identities: + passwordattempts: 10 + +############################################################################### +# +# Operations section +# +############################################################################### +operations: + # host and port for the operations server + listenAddress: 127.0.0.1:9443 + + # TLS configuration for the operations endpoint + tls: + # TLS enabled + enabled: false + + # path to PEM encoded server certificate for the operations server + cert: + file: + + # path to PEM encoded server key for the operations server + key: + file: + + # require client certificate authentication to access all resources + clientAuthRequired: false + + # paths to PEM encoded ca certificates to trust for client authentication + clientRootCAs: + files: [] + +############################################################################### +# +# Metrics section +# +############################################################################### +metrics: + # statsd, prometheus, or disabled + provider: disabled + + # statsd configuration + statsd: + # network type: tcp or udp + network: udp + + # statsd server address + address: 127.0.0.1:8125 + + # the interval at which locally cached counters and gauges are pushed + # to statsd; timings are pushed immediately + writeInterval: 10s + + # prefix is prepended to all emitted statsd metrics + prefix: server +" +`; + +exports[`samples/fablo-config-hlf2-2orgs-2chaincodes-private-data.yaml should create proper e2e/__tmp__/samples/fablo-config-hlf2-2orgs-2chaincodes-private-data.yaml.tmpdir/fablo-target/fabric-config/fabric-ca-server-config/orderer2.com/fabric-ca-server-config.yaml from samples/fablo-config-hlf2-2orgs-2chaincodes-private-data.yaml 1`] = ` +"############################################################################# +# This is a configuration file for the fabric-ca-server command. +# +# COMMAND LINE ARGUMENTS AND ENVIRONMENT VARIABLES +# ------------------------------------------------ +# Each configuration element can be overridden via command line +# arguments or environment variables. The precedence for determining +# the value of each element is as follows: +# 1) command line argument +# Examples: +# a) --port 443 +# To set the listening port +# b) --ca.keyfile ../mykey.pem +# To set the "keyfile" element in the "ca" section below; +# note the '.' separator character. +# 2) environment variable +# Examples: +# a) FABRIC_CA_SERVER_PORT=443 +# To set the listening port +# b) FABRIC_CA_SERVER_CA_KEYFILE="../mykey.pem" +# To set the "keyfile" element in the "ca" section below; +# note the '_' separator character. +# 3) configuration file +# 4) default value (if there is one) +# All default values are shown beside each element below. +# +# FILE NAME ELEMENTS +# ------------------ +# The value of all fields whose name ends with "file" or "files" are +# name or names of other files. +# For example, see "tls.certfile" and "tls.clientauth.certfiles". +# The value of each of these fields can be a simple filename, a +# relative path, or an absolute path. If the value is not an +# absolute path, it is interpreted as being relative to the location +# of this configuration file. +# +############################################################################# + +# Version of config file +version: 1.5.5 + +# Server's listening port (default: 7054) +port: 7054 + +# Cross-Origin Resource Sharing (CORS) +cors: + enabled: false + origins: + - "*" + +# Enables debug logging (default: false) +debug: false + +# Size limit of an acceptable CRL in bytes (default: 512000) +crlsizelimit: 512000 + +############################################################################# +# TLS section for the server's listening port +# +# The following types are supported for client authentication: NoClientCert, +# RequestClientCert, RequireAnyClientCert, VerifyClientCertIfGiven, +# and RequireAndVerifyClientCert. +# +# Certfiles is a list of root certificate authorities that the server uses +# when verifying client certificates. +############################################################################# +tls: + # Enable TLS (default: false) + enabled: false + # TLS for the server's listening port + certfile: + keyfile: + clientauth: + type: noclientcert + certfiles: + +############################################################################# +# The CA section contains information related to the Certificate Authority +# including the name of the CA, which should be unique for all members +# of a blockchain network. It also includes the key and certificate files +# used when issuing enrollment certificates (ECerts). +# The chainfile (if it exists) contains the certificate chain which +# should be trusted for this CA, where the 1st in the chain is always the +# root CA certificate. +############################################################################# +ca: + # Name of this CA + name: + # Key file (is only used to import a private key into BCCSP) + keyfile: + # Certificate file (default: ca-cert.pem) + certfile: + # Chain file + chainfile: + +############################################################################# +# The gencrl REST endpoint is used to generate a CRL that contains revoked +# certificates. This section contains configuration options that are used +# during gencrl request processing. +############################################################################# +crl: + # Specifies expiration for the generated CRL. The number of hours + # specified by this property is added to the UTC time, the resulting time + # is used to set the 'Next Update' date of the CRL. + expiry: 24h + +############################################################################# +# The registry section controls how the fabric-ca-server does two things: +# 1) authenticates enrollment requests which contain a username and password +# (also known as an enrollment ID and secret). +# 2) once authenticated, retrieves the identity's attribute names and values. +# These attributes are useful for making access control decisions in +# chaincode. +# There are two main configuration options: +# 1) The fabric-ca-server is the registry. +# This is true if "ldap.enabled" in the ldap section below is false. +# 2) An LDAP server is the registry, in which case the fabric-ca-server +# calls the LDAP server to perform these tasks. +# This is true if "ldap.enabled" in the ldap section below is true, +# which means this "registry" section is ignored. +############################################################################# +registry: + # Maximum number of times a password/secret can be reused for enrollment + # (default: -1, which means there is no limit) + maxenrollments: -1 + + # Contains identity information which is used when LDAP is disabled + identities: + - name: admin + pass: adminpw + type: client + affiliation: "" + attrs: + hf.Registrar.Roles: "*" + hf.Registrar.DelegateRoles: "*" + hf.Revoker: true + hf.IntermediateCA: true + hf.GenCRL: true + hf.Registrar.Attributes: "*" + hf.AffiliationMgr: true + +############################################################################# +# Database section +# Supported types are: "sqlite3", "postgres", and "mysql". +# The datasource value depends on the type. +# If the type is "sqlite3", the datasource value is a file name to use +# as the database store. Since "sqlite3" is an embedded database, it +# may not be used if you want to run the fabric-ca-server in a cluster. +# To run the fabric-ca-server in a cluster, you must choose "postgres" +# or "mysql". +############################################################################# +db: + type: sqlite3 + datasource: fabric-ca-server.db + tls: + enabled: false + certfiles: + client: + certfile: + keyfile: + +############################################################################# +# LDAP section +# If LDAP is enabled, the fabric-ca-server calls LDAP to: +# 1) authenticate enrollment ID and secret (i.e. username and password) +# for enrollment requests; +# 2) To retrieve identity attributes +############################################################################# +ldap: + # Enables or disables the LDAP client (default: false) + # If this is set to true, the "registry" section is ignored. + enabled: false + # The URL of the LDAP server + url: ldap://:@:/ + # TLS configuration for the client connection to the LDAP server + tls: + certfiles: + client: + certfile: + keyfile: + # Attribute related configuration for mapping from LDAP entries to Fabric CA attributes + attribute: + # 'names' is an array of strings containing the LDAP attribute names which are + # requested from the LDAP server for an LDAP identity's entry + names: ['uid', 'member'] + # The 'converters' section is used to convert an LDAP entry to the value of + # a fabric CA attribute. + # For example, the following converts an LDAP 'uid' attribute + # whose value begins with 'revoker' to a fabric CA attribute + # named "hf.Revoker" with a value of "true" (because the boolean expression + # evaluates to true). + # converters: + # - name: hf.Revoker + # value: attr("uid") =~ "revoker*" + converters: + - name: + value: + # The 'maps' section contains named maps which may be referenced by the 'map' + # function in the 'converters' section to map LDAP responses to arbitrary values. + # For example, assume a user has an LDAP attribute named 'member' which has multiple + # values which are each a distinguished name (i.e. a DN). For simplicity, assume the + # values of the 'member' attribute are 'dn1', 'dn2', and 'dn3'. + # Further assume the following configuration. + # converters: + # - name: hf.Registrar.Roles + # value: map(attr("member"),"groups") + # maps: + # groups: + # - name: dn1 + # value: peer + # - name: dn2 + # value: client + # The value of the user's 'hf.Registrar.Roles' attribute is then computed to be + # "peer,client,dn3". This is because the value of 'attr("member")' is + # "dn1,dn2,dn3", and the call to 'map' with a 2nd argument of + # "group" replaces "dn1" with "peer" and "dn2" with "client". + maps: + groups: + - name: + value: + +############################################################################# +# Affiliations section. Fabric CA server can be bootstrapped with the +# affiliations specified in this section. Affiliations are specified as maps. +# For example: +# businessunit1: +# department1: +# - team1 +# businessunit2: +# - department2 +# - department3 +# +# Affiliations are hierarchical in nature. In the above example, +# department1 (used as businessunit1.department1) is the child of businessunit1. +# team1 (used as businessunit1.department1.team1) is the child of department1. +# department2 (used as businessunit2.department2) and department3 (businessunit2.department3) +# are children of businessunit2. +# Note: Affiliations are case sensitive except for the non-leaf affiliations +# (like businessunit1, department1, businessunit2) that are specified in the configuration file, +# which are always stored in lower case. +############################################################################# +affiliations: + orderer2: + +############################################################################# +# Signing section +# +# The "default" subsection is used to sign enrollment certificates; +# the default expiration ("expiry" field) is "8760h", which is 1 year in hours. +# +# The "ca" profile subsection is used to sign intermediate CA certificates; +# the default expiration ("expiry" field) is "43800h" which is 5 years in hours. +# Note that "isca" is true, meaning that it issues a CA certificate. +# A maxpathlen of 0 means that the intermediate CA cannot issue other +# intermediate CA certificates, though it can still issue end entity certificates. +# (See RFC 5280, section 4.2.1.9) +# +# The "tls" profile subsection is used to sign TLS certificate requests; +# the default expiration ("expiry" field) is "8760h", which is 1 year in hours. +############################################################################# +signing: + default: + usage: + - digital signature + expiry: 8760h + profiles: + ca: + usage: + - cert sign + - crl sign + expiry: 43800h + caconstraint: + isca: true + maxpathlen: 0 + tls: + usage: + - signing + - key encipherment + - server auth + - client auth + - key agreement + expiry: 8760h + +########################################################################### +# Certificate Signing Request (CSR) section. +# This controls the creation of the root CA certificate. +# The expiration for the root CA certificate is configured with the +# "ca.expiry" field below, whose default value is "131400h" which is +# 15 years in hours. +# The pathlength field is used to limit CA certificate hierarchy as described +# in section 4.2.1.9 of RFC 5280. +# Examples: +# 1) No pathlength value means no limit is requested. +# 2) pathlength == 1 means a limit of 1 is requested which is the default for +# a root CA. This means the root CA can issue intermediate CA certificates, +# but these intermediate CAs may not in turn issue other CA certificates +# though they can still issue end entity certificates. +# 3) pathlength == 0 means a limit of 0 is requested; +# this is the default for an intermediate CA, which means it can not issue +# CA certificates though it can still issue end entity certificates. +########################################################################### +csr: + cn: fabric-ca-server + keyrequest: + algo: ecdsa + size: 256 + names: + - C: US + ST: "North Carolina" + L: + O: Hyperledger + OU: Fabric + hosts: + - 483cccf16a98 + - localhost + ca: + expiry: 131400h + pathlength: 1 + +########################################################################### +# Each CA can issue both X509 enrollment certificate as well as Idemix +# Credential. This section specifies configuration for the issuer component +# that is responsible for issuing Idemix credentials. +########################################################################### +idemix: + # Specifies pool size for revocation handles. A revocation handle is an unique identifier of an + # Idemix credential. The issuer will create a pool revocation handles of this specified size. When + # a credential is requested, issuer will get handle from the pool and assign it to the credential. + # Issuer will repopulate the pool with new handles when the last handle in the pool is used. + # A revocation handle and credential revocation information (CRI) are used to create non revocation proof + # by the prover to prove to the verifier that her credential is not revoked. + rhpoolsize: 1000 + + # The Idemix credential issuance is a two step process. First step is to get a nonce from the issuer + # and second step is send credential request that is constructed using the nonce to the isuser to + # request a credential. This configuration property specifies expiration for the nonces. By default is + # nonces expire after 15 seconds. The value is expressed in the time.Duration format (see https://golang.org/pkg/time/#ParseDuration). + nonceexpiration: 15s + + # Specifies interval at which expired nonces are removed from datastore. Default value is 15 minutes. + # The value is expressed in the time.Duration format (see https://golang.org/pkg/time/#ParseDuration) + noncesweepinterval: 15m + +############################################################################# +# BCCSP (BlockChain Crypto Service Provider) section is used to select which +# crypto library implementation to use +############################################################################# +bccsp: + default: SW + sw: + hash: SHA2 + security: 256 + filekeystore: + # The directory used for the software file-based keystore + keystore: msp/keystore + +############################################################################# +# Multi CA section +# +# Each Fabric CA server contains one CA by default. This section is used +# to configure multiple CAs in a single server. +# +# 1) --cacount +# Automatically generate non-default CAs. The names of these +# additional CAs are "ca1", "ca2", ... "caN", where "N" is +# This is particularly useful in a development environment to quickly set up +# multiple CAs. Note that, this config option is not applicable to intermediate CA server +# i.e., Fabric CA server that is started with intermediate.parentserver.url config +# option (-u command line option) +# +# 2) --cafiles +# For each CA config file in the list, generate a separate signing CA. Each CA +# config file in this list MAY contain all of the same elements as are found in +# the server config file except port, debug, and tls sections. +# +# Examples: +# fabric-ca-server start -b admin:adminpw --cacount 2 +# +# fabric-ca-server start -b admin:adminpw --cafiles ca/ca1/fabric-ca-server-config.yaml +# --cafiles ca/ca2/fabric-ca-server-config.yaml +# +############################################################################# + +cacount: + +cafiles: + +############################################################################# +# Intermediate CA section +# +# The relationship between servers and CAs is as follows: +# 1) A single server process may contain or function as one or more CAs. +# This is configured by the "Multi CA section" above. +# 2) Each CA is either a root CA or an intermediate CA. +# 3) Each intermediate CA has a parent CA which is either a root CA or another intermediate CA. +# +# This section pertains to configuration of #2 and #3. +# If the "intermediate.parentserver.url" property is set, +# then this is an intermediate CA with the specified parent +# CA. +# +# parentserver section +# url - The URL of the parent server +# caname - Name of the CA to enroll within the server +# +# enrollment section used to enroll intermediate CA with parent CA +# profile - Name of the signing profile to use in issuing the certificate +# label - Label to use in HSM operations +# +# tls section for secure socket connection +# certfiles - PEM-encoded list of trusted root certificate files +# client: +# certfile - PEM-encoded certificate file for when client authentication +# is enabled on server +# keyfile - PEM-encoded key file for when client authentication +# is enabled on server +############################################################################# +intermediate: + parentserver: + url: + caname: + + enrollment: + hosts: + profile: + label: + + tls: + certfiles: + client: + certfile: + keyfile: + +############################################################################# +# CA configuration section +# +# Configure the number of incorrect password attempts are allowed for +# identities. By default, the value of 'passwordattempts' is 10, which +# means that 10 incorrect password attempts can be made before an identity get +# locked out. +############################################################################# +cfg: + identities: + passwordattempts: 10 + +############################################################################### +# +# Operations section +# +############################################################################### +operations: + # host and port for the operations server + listenAddress: 127.0.0.1:9443 + + # TLS configuration for the operations endpoint + tls: + # TLS enabled + enabled: false + + # path to PEM encoded server certificate for the operations server + cert: + file: + + # path to PEM encoded server key for the operations server + key: + file: + + # require client certificate authentication to access all resources + clientAuthRequired: false + + # paths to PEM encoded ca certificates to trust for client authentication + clientRootCAs: + files: [] + +############################################################################### +# +# Metrics section +# +############################################################################### +metrics: + # statsd, prometheus, or disabled + provider: disabled + + # statsd configuration + statsd: + # network type: tcp or udp + network: udp + + # statsd server address + address: 127.0.0.1:8125 + + # the interval at which locally cached counters and gauges are pushed + # to statsd; timings are pushed immediately + writeInterval: 10s + + # prefix is prepended to all emitted statsd metrics + prefix: server +" +`; + exports[`samples/fablo-config-hlf2-2orgs-2chaincodes-private-data.yaml should create proper e2e/__tmp__/samples/fablo-config-hlf2-2orgs-2chaincodes-private-data.yaml.tmpdir/fablo-target/fabric-config/fabric-ca-server-config/org1.example.com/fabric-ca-server-config.yaml from samples/fablo-config-hlf2-2orgs-2chaincodes-private-data.yaml 1`] = ` "############################################################################# # This is a configuration file for the fabric-ca-server command. diff --git a/e2e/fabloCommands.test.ts b/e2e/fabloCommands.test.ts index a5d69a650..95fd897ca 100644 --- a/e2e/fabloCommands.test.ts +++ b/e2e/fabloCommands.test.ts @@ -137,17 +137,31 @@ describe("validate", () => { expect(commandResult.output).toContain(" instance.orgs[0].organization.mspName : does not match pattern"); expect(commands.getFiles()).toEqual([]); }); + it("should throw an error for duplicate chaincode names across different channels", () => { // Given + commands.fabloExec("init"); const fabloConfig = `${commands.relativeRoot}/samples/fablo-config-hlf2-2orgs-2chaincodes-private-data-duplicate.yaml`; // When const commandResult = commands.fabloExec(`validate ${fabloConfig}`); // Then - expect(commandResult).toEqual(TestCommands.failure()); - expect(commandResult.output).toContain("Duplicate chaincode name found"); + expect(commandResult.output).toContain("Chaincode name 'duplicateChaincode' is not unique"); + }); + + it("should validate when all chaincode names are unique across channels", () => { + // Given + const fabloConfig = `${commands.relativeRoot}/samples/fablo-config-hlf2-2orgs-2chaincodes-raft.yaml`; + + // When + const commandResult = commands.fabloExec(`validate ${fabloConfig}`); + + // Then + expect(commandResult.output).toContain("Validation errors count: 0"); + expect(commandResult.output).not.toContain("is not unique"); +}); }); describe("extend config", () => { diff --git a/samples/fablo-config-hlf2-2orgs-2chaincodes-private-data-duplicate.yaml b/samples/fablo-config-hlf2-2orgs-2chaincodes-private-data-duplicate.yaml new file mode 100644 index 000000000..da25c1f21 --- /dev/null +++ b/samples/fablo-config-hlf2-2orgs-2chaincodes-private-data-duplicate.yaml @@ -0,0 +1,59 @@ +--- +$schema: "https://github.com/hyperledger-labs/fablo/releases/download/2.2.0/schema.json" +global: + fabricVersion: "2.4.7" + tls: false + +orgs: + - organization: + name: Orderer + domain: orderer.example.com + orderer: + type: raft + instances: 1 + - organization: + name: Org1 + domain: org1.example.com + peer: + instances: 1 + ca: + prefix: ca + - organization: + name: Org2 + domain: org2.example.com + peer: + instances: 1 + ca: + prefix: ca + +channels: + - name: channel1 + orgs: + - name: Org1 + peers: [peer0] + - name: Org2 + peers: [peer0] + - name: Orderer + peers: [] + - name: channel2 + orgs: + - name: Org1 + peers: [peer0] + - name: Org2 + peers: [peer0] + - name: Orderer + peers: [] + +chaincodes: + - name: duplicateChaincode + version: "1.0" + lang: node + channel: channel1 + directory: "./chaincodes/chaincode-kv-node" + endorsement: "OR('Org1MSP.member', 'Org2MSP.member')" + - name: duplicateChaincode + version: "1.0" + lang: node + channel: channel2 + directory: "./chaincodes/chaincode-kv-node" + endorsement: "OR('Org1MSP.member', 'Org2MSP.member')" \ No newline at end of file diff --git a/samples/fablo-config-hlf2-2orgs-2chaincodes-private-data.yaml b/samples/fablo-config-hlf2-2orgs-2chaincodes-private-data.yaml index 6f3a00f66..1d298bdd3 100644 --- a/samples/fablo-config-hlf2-2orgs-2chaincodes-private-data.yaml +++ b/samples/fablo-config-hlf2-2orgs-2chaincodes-private-data.yaml @@ -55,4 +55,4 @@ chaincodes: - name: both-orgs-collection orgNames: - Org1 - - Org2 + - Org2 \ No newline at end of file diff --git a/src/extend-config/extendChaincodesConfig.ts b/src/extend-config/extendChaincodesConfig.ts index 17559cacb..1ceffb2ea 100644 --- a/src/extend-config/extendChaincodesConfig.ts +++ b/src/extend-config/extendChaincodesConfig.ts @@ -41,7 +41,7 @@ const checkUniqueChaincodeNames = (chaincodes: ChaincodeJson[]): void => { const chaincodeNames = new Set(); chaincodes.forEach((chaincode) => { if (chaincodeNames.has(chaincode.name)) { - throw new Error(`Duplicate chaincode name found: '${chaincode.name}'`); + throw new Error(`Chaincode name '${chaincode.name}' is not unique across channels.`); } chaincodeNames.add(chaincode.name); }); From f249ec908f1e341e37c4ebbe0f8b5831ac388048 Mon Sep 17 00:00:00 2001 From: Osama Rabea Date: Fri, 15 Aug 2025 08:57:00 +0300 Subject: [PATCH 03/10] feat: continue PR #528- Add check for unique chaincode names Signed-off-by: Osama Rabea --- e2e/__snapshots__/extendConfig.test.ts.snap | 1594 +++++++++++++++++ ...2chaincodes-private-data.yaml.test.ts.snap | 1296 -------------- e2e/__snapshots__/fabloCommands.test.ts.snap | 13 +- e2e/fabloCommands.test.ts | 17 +- ...gs-2chaincodes-private-data-duplicate.yaml | 26 +- src/extend-config/extendChaincodesConfig.ts | 13 +- 6 files changed, 1626 insertions(+), 1333 deletions(-) diff --git a/e2e/__snapshots__/extendConfig.test.ts.snap b/e2e/__snapshots__/extendConfig.test.ts.snap index 6fd3d4722..bfeb4c772 100644 --- a/e2e/__snapshots__/extendConfig.test.ts.snap +++ b/e2e/__snapshots__/extendConfig.test.ts.snap @@ -3886,6 +3886,1600 @@ exports[`extend config samples/fablo-config-hlf2-2orgs-2chaincodes-private-data. } `; +exports[`extend config samples/fablo-config-hlf2-2orgs-2chaincodes-private-data-duplicate.yaml 1`] = ` +{ + "chaincodes": [ + { + "channel": { + "instantiatingOrg": { + "anchorPeers": [ + { + "address": "peer0.org1.example.com", + "couchDbExposePort": 5100, + "db": { + "type": "LevelDb", + }, + "fullAddress": "peer0.org1.example.com:7041", + "gatewayEnabled": true, + "isAnchorPeer": true, + "name": "peer0", + "port": 7041, + }, + { + "address": "peer1.org1.example.com", + "couchDbExposePort": 5101, + "db": { + "type": "LevelDb", + }, + "fullAddress": "peer1.org1.example.com:7042", + "gatewayEnabled": true, + "isAnchorPeer": true, + "name": "peer1", + "port": 7042, + }, + ], + "bootstrapPeers": ""peer0.org1.example.com:7041 peer1.org1.example.com:7042"", + "ca": { + "address": "ca.org1.example.com", + "caAdminNameVar": "ORG1_CA_ADMIN_NAME", + "caAdminPassVar": "ORG1_CA_ADMIN_PASSWORD", + "db": "sqlite", + "exposePort": 7040, + "fullAddress": "ca.org1.example.com:7054", + "port": 7054, + "prefix": "ca", + }, + "cli": { + "address": "cli.org1.example.com", + }, + "cryptoConfigFileName": "crypto-config-org1", + "domain": "org1.example.com", + "headPeer": { + "address": "peer0.org1.example.com", + "couchDbExposePort": 5100, + "db": { + "type": "LevelDb", + }, + "fullAddress": "peer0.org1.example.com:7041", + "gatewayEnabled": true, + "isAnchorPeer": true, + "name": "peer0", + "port": 7041, + }, + "mspName": "Org1MSP", + "name": "Org1", + "ordererGroups": [], + "peers": [ + { + "address": "peer0.org1.example.com", + "couchDbExposePort": 5100, + "db": { + "type": "LevelDb", + }, + "fullAddress": "peer0.org1.example.com:7041", + "gatewayEnabled": true, + "isAnchorPeer": true, + "name": "peer0", + "port": 7041, + }, + ], + "peersCount": 2, + "tools": {}, + }, + "name": "my-channel1", + "ordererGroup": { + "configtxOrdererDefaults": "Group1Defaults", + "consensus": "solo", + "genesisBlockName": "Group1Genesis.block", + "hostingOrgs": [ + "Orderer", + ], + "name": "group1", + "ordererHead": { + "address": "orderer0.group1.orderer.example.com", + "adminPort": 7053, + "consensus": "solo", + "domain": "orderer.example.com", + "fullAddress": "orderer0.group1.orderer.example.com:7030", + "name": "orderer0.group1", + "orgMspName": "OrdererMSP", + "orgName": "Orderer", + "port": 7030, + }, + "ordererHeads": [ + { + "address": "orderer0.group1.orderer.example.com", + "adminPort": 7053, + "consensus": "solo", + "domain": "orderer.example.com", + "fullAddress": "orderer0.group1.orderer.example.com:7030", + "name": "orderer0.group1", + "orgMspName": "OrdererMSP", + "orgName": "Orderer", + "port": 7030, + }, + ], + "orderers": [ + { + "address": "orderer0.group1.orderer.example.com", + "adminPort": 7053, + "consensus": "solo", + "domain": "orderer.example.com", + "fullAddress": "orderer0.group1.orderer.example.com:7030", + "name": "orderer0.group1", + "orgMspName": "OrdererMSP", + "orgName": "Orderer", + "port": 7030, + }, + ], + "profileName": "Group1Genesis", + }, + "ordererHead": { + "address": "orderer0.group1.orderer.example.com", + "adminPort": 7053, + "consensus": "solo", + "domain": "orderer.example.com", + "fullAddress": "orderer0.group1.orderer.example.com:7030", + "name": "orderer0.group1", + "orgMspName": "OrdererMSP", + "orgName": "Orderer", + "port": 7030, + }, + "orgs": [ + { + "anchorPeers": [ + { + "address": "peer0.org1.example.com", + "couchDbExposePort": 5100, + "db": { + "type": "LevelDb", + }, + "fullAddress": "peer0.org1.example.com:7041", + "gatewayEnabled": true, + "isAnchorPeer": true, + "name": "peer0", + "port": 7041, + }, + { + "address": "peer1.org1.example.com", + "couchDbExposePort": 5101, + "db": { + "type": "LevelDb", + }, + "fullAddress": "peer1.org1.example.com:7042", + "gatewayEnabled": true, + "isAnchorPeer": true, + "name": "peer1", + "port": 7042, + }, + ], + "bootstrapPeers": ""peer0.org1.example.com:7041 peer1.org1.example.com:7042"", + "ca": { + "address": "ca.org1.example.com", + "caAdminNameVar": "ORG1_CA_ADMIN_NAME", + "caAdminPassVar": "ORG1_CA_ADMIN_PASSWORD", + "db": "sqlite", + "exposePort": 7040, + "fullAddress": "ca.org1.example.com:7054", + "port": 7054, + "prefix": "ca", + }, + "cli": { + "address": "cli.org1.example.com", + }, + "cryptoConfigFileName": "crypto-config-org1", + "domain": "org1.example.com", + "headPeer": { + "address": "peer0.org1.example.com", + "couchDbExposePort": 5100, + "db": { + "type": "LevelDb", + }, + "fullAddress": "peer0.org1.example.com:7041", + "gatewayEnabled": true, + "isAnchorPeer": true, + "name": "peer0", + "port": 7041, + }, + "mspName": "Org1MSP", + "name": "Org1", + "ordererGroups": [], + "peers": [ + { + "address": "peer0.org1.example.com", + "couchDbExposePort": 5100, + "db": { + "type": "LevelDb", + }, + "fullAddress": "peer0.org1.example.com:7041", + "gatewayEnabled": true, + "isAnchorPeer": true, + "name": "peer0", + "port": 7041, + }, + ], + "peersCount": 2, + "tools": {}, + }, + { + "anchorPeers": [ + { + "address": "peer0.org2.example.com", + "couchDbExposePort": 5120, + "db": { + "type": "LevelDb", + }, + "fullAddress": "peer0.org2.example.com:7061", + "gatewayEnabled": true, + "isAnchorPeer": true, + "name": "peer0", + "port": 7061, + }, + ], + "bootstrapPeers": "peer0.org2.example.com:7061", + "ca": { + "address": "ca.org2.example.com", + "caAdminNameVar": "ORG2_CA_ADMIN_NAME", + "caAdminPassVar": "ORG2_CA_ADMIN_PASSWORD", + "db": "sqlite", + "exposePort": 7060, + "fullAddress": "ca.org2.example.com:7054", + "port": 7054, + "prefix": "ca", + }, + "cli": { + "address": "cli.org2.example.com", + }, + "cryptoConfigFileName": "crypto-config-org2", + "domain": "org2.example.com", + "headPeer": { + "address": "peer0.org2.example.com", + "couchDbExposePort": 5120, + "db": { + "type": "LevelDb", + }, + "fullAddress": "peer0.org2.example.com:7061", + "gatewayEnabled": true, + "isAnchorPeer": true, + "name": "peer0", + "port": 7061, + }, + "mspName": "Org2MSP", + "name": "Org2", + "ordererGroups": [], + "peers": [ + { + "address": "peer0.org2.example.com", + "couchDbExposePort": 5120, + "db": { + "type": "LevelDb", + }, + "fullAddress": "peer0.org2.example.com:7061", + "gatewayEnabled": true, + "isAnchorPeer": true, + "name": "peer0", + "port": 7061, + }, + ], + "peersCount": 1, + "tools": {}, + }, + ], + "profileName": "MyChannel1", + }, + "directory": "./chaincodes/chaincode-kv-node", + "endorsement": "OR('Org1MSP.member', 'Org2MSP.member')", + "initRequired": false, + "instantiatingOrg": { + "anchorPeers": [ + { + "address": "peer0.org1.example.com", + "couchDbExposePort": 5100, + "db": { + "type": "LevelDb", + }, + "fullAddress": "peer0.org1.example.com:7041", + "gatewayEnabled": true, + "isAnchorPeer": true, + "name": "peer0", + "port": 7041, + }, + { + "address": "peer1.org1.example.com", + "couchDbExposePort": 5101, + "db": { + "type": "LevelDb", + }, + "fullAddress": "peer1.org1.example.com:7042", + "gatewayEnabled": true, + "isAnchorPeer": true, + "name": "peer1", + "port": 7042, + }, + ], + "bootstrapPeers": ""peer0.org1.example.com:7041 peer1.org1.example.com:7042"", + "ca": { + "address": "ca.org1.example.com", + "caAdminNameVar": "ORG1_CA_ADMIN_NAME", + "caAdminPassVar": "ORG1_CA_ADMIN_PASSWORD", + "db": "sqlite", + "exposePort": 7040, + "fullAddress": "ca.org1.example.com:7054", + "port": 7054, + "prefix": "ca", + }, + "cli": { + "address": "cli.org1.example.com", + }, + "cryptoConfigFileName": "crypto-config-org1", + "domain": "org1.example.com", + "headPeer": { + "address": "peer0.org1.example.com", + "couchDbExposePort": 5100, + "db": { + "type": "LevelDb", + }, + "fullAddress": "peer0.org1.example.com:7041", + "gatewayEnabled": true, + "isAnchorPeer": true, + "name": "peer0", + "port": 7041, + }, + "mspName": "Org1MSP", + "name": "Org1", + "ordererGroups": [], + "peers": [ + { + "address": "peer0.org1.example.com", + "couchDbExposePort": 5100, + "db": { + "type": "LevelDb", + }, + "fullAddress": "peer0.org1.example.com:7041", + "gatewayEnabled": true, + "isAnchorPeer": true, + "name": "peer0", + "port": 7041, + }, + ], + "peersCount": 2, + "tools": {}, + }, + "lang": "node", + "name": "duplicateChaincode", + "privateData": [], + "privateDataConfigFile": undefined, + "version": "1.0", + }, + { + "channel": { + "instantiatingOrg": { + "anchorPeers": [ + { + "address": "peer0.org1.example.com", + "couchDbExposePort": 5100, + "db": { + "type": "LevelDb", + }, + "fullAddress": "peer0.org1.example.com:7041", + "gatewayEnabled": true, + "isAnchorPeer": true, + "name": "peer0", + "port": 7041, + }, + { + "address": "peer1.org1.example.com", + "couchDbExposePort": 5101, + "db": { + "type": "LevelDb", + }, + "fullAddress": "peer1.org1.example.com:7042", + "gatewayEnabled": true, + "isAnchorPeer": true, + "name": "peer1", + "port": 7042, + }, + ], + "bootstrapPeers": ""peer0.org1.example.com:7041 peer1.org1.example.com:7042"", + "ca": { + "address": "ca.org1.example.com", + "caAdminNameVar": "ORG1_CA_ADMIN_NAME", + "caAdminPassVar": "ORG1_CA_ADMIN_PASSWORD", + "db": "sqlite", + "exposePort": 7040, + "fullAddress": "ca.org1.example.com:7054", + "port": 7054, + "prefix": "ca", + }, + "cli": { + "address": "cli.org1.example.com", + }, + "cryptoConfigFileName": "crypto-config-org1", + "domain": "org1.example.com", + "headPeer": { + "address": "peer0.org1.example.com", + "couchDbExposePort": 5100, + "db": { + "type": "LevelDb", + }, + "fullAddress": "peer0.org1.example.com:7041", + "gatewayEnabled": true, + "isAnchorPeer": true, + "name": "peer0", + "port": 7041, + }, + "mspName": "Org1MSP", + "name": "Org1", + "ordererGroups": [], + "peers": [ + { + "address": "peer0.org1.example.com", + "couchDbExposePort": 5100, + "db": { + "type": "LevelDb", + }, + "fullAddress": "peer0.org1.example.com:7041", + "gatewayEnabled": true, + "isAnchorPeer": true, + "name": "peer0", + "port": 7041, + }, + ], + "peersCount": 2, + "tools": {}, + }, + "name": "my-channel2", + "ordererGroup": { + "configtxOrdererDefaults": "Group1Defaults", + "consensus": "solo", + "genesisBlockName": "Group1Genesis.block", + "hostingOrgs": [ + "Orderer", + ], + "name": "group1", + "ordererHead": { + "address": "orderer0.group1.orderer.example.com", + "adminPort": 7053, + "consensus": "solo", + "domain": "orderer.example.com", + "fullAddress": "orderer0.group1.orderer.example.com:7030", + "name": "orderer0.group1", + "orgMspName": "OrdererMSP", + "orgName": "Orderer", + "port": 7030, + }, + "ordererHeads": [ + { + "address": "orderer0.group1.orderer.example.com", + "adminPort": 7053, + "consensus": "solo", + "domain": "orderer.example.com", + "fullAddress": "orderer0.group1.orderer.example.com:7030", + "name": "orderer0.group1", + "orgMspName": "OrdererMSP", + "orgName": "Orderer", + "port": 7030, + }, + ], + "orderers": [ + { + "address": "orderer0.group1.orderer.example.com", + "adminPort": 7053, + "consensus": "solo", + "domain": "orderer.example.com", + "fullAddress": "orderer0.group1.orderer.example.com:7030", + "name": "orderer0.group1", + "orgMspName": "OrdererMSP", + "orgName": "Orderer", + "port": 7030, + }, + ], + "profileName": "Group1Genesis", + }, + "ordererHead": { + "address": "orderer0.group1.orderer.example.com", + "adminPort": 7053, + "consensus": "solo", + "domain": "orderer.example.com", + "fullAddress": "orderer0.group1.orderer.example.com:7030", + "name": "orderer0.group1", + "orgMspName": "OrdererMSP", + "orgName": "Orderer", + "port": 7030, + }, + "orgs": [ + { + "anchorPeers": [ + { + "address": "peer0.org1.example.com", + "couchDbExposePort": 5100, + "db": { + "type": "LevelDb", + }, + "fullAddress": "peer0.org1.example.com:7041", + "gatewayEnabled": true, + "isAnchorPeer": true, + "name": "peer0", + "port": 7041, + }, + { + "address": "peer1.org1.example.com", + "couchDbExposePort": 5101, + "db": { + "type": "LevelDb", + }, + "fullAddress": "peer1.org1.example.com:7042", + "gatewayEnabled": true, + "isAnchorPeer": true, + "name": "peer1", + "port": 7042, + }, + ], + "bootstrapPeers": ""peer0.org1.example.com:7041 peer1.org1.example.com:7042"", + "ca": { + "address": "ca.org1.example.com", + "caAdminNameVar": "ORG1_CA_ADMIN_NAME", + "caAdminPassVar": "ORG1_CA_ADMIN_PASSWORD", + "db": "sqlite", + "exposePort": 7040, + "fullAddress": "ca.org1.example.com:7054", + "port": 7054, + "prefix": "ca", + }, + "cli": { + "address": "cli.org1.example.com", + }, + "cryptoConfigFileName": "crypto-config-org1", + "domain": "org1.example.com", + "headPeer": { + "address": "peer0.org1.example.com", + "couchDbExposePort": 5100, + "db": { + "type": "LevelDb", + }, + "fullAddress": "peer0.org1.example.com:7041", + "gatewayEnabled": true, + "isAnchorPeer": true, + "name": "peer0", + "port": 7041, + }, + "mspName": "Org1MSP", + "name": "Org1", + "ordererGroups": [], + "peers": [ + { + "address": "peer0.org1.example.com", + "couchDbExposePort": 5100, + "db": { + "type": "LevelDb", + }, + "fullAddress": "peer0.org1.example.com:7041", + "gatewayEnabled": true, + "isAnchorPeer": true, + "name": "peer0", + "port": 7041, + }, + ], + "peersCount": 2, + "tools": {}, + }, + { + "anchorPeers": [ + { + "address": "peer0.org2.example.com", + "couchDbExposePort": 5120, + "db": { + "type": "LevelDb", + }, + "fullAddress": "peer0.org2.example.com:7061", + "gatewayEnabled": true, + "isAnchorPeer": true, + "name": "peer0", + "port": 7061, + }, + ], + "bootstrapPeers": "peer0.org2.example.com:7061", + "ca": { + "address": "ca.org2.example.com", + "caAdminNameVar": "ORG2_CA_ADMIN_NAME", + "caAdminPassVar": "ORG2_CA_ADMIN_PASSWORD", + "db": "sqlite", + "exposePort": 7060, + "fullAddress": "ca.org2.example.com:7054", + "port": 7054, + "prefix": "ca", + }, + "cli": { + "address": "cli.org2.example.com", + }, + "cryptoConfigFileName": "crypto-config-org2", + "domain": "org2.example.com", + "headPeer": { + "address": "peer0.org2.example.com", + "couchDbExposePort": 5120, + "db": { + "type": "LevelDb", + }, + "fullAddress": "peer0.org2.example.com:7061", + "gatewayEnabled": true, + "isAnchorPeer": true, + "name": "peer0", + "port": 7061, + }, + "mspName": "Org2MSP", + "name": "Org2", + "ordererGroups": [], + "peers": [ + { + "address": "peer0.org2.example.com", + "couchDbExposePort": 5120, + "db": { + "type": "LevelDb", + }, + "fullAddress": "peer0.org2.example.com:7061", + "gatewayEnabled": true, + "isAnchorPeer": true, + "name": "peer0", + "port": 7061, + }, + ], + "peersCount": 1, + "tools": {}, + }, + ], + "profileName": "MyChannel2", + }, + "directory": "./chaincodes/chaincode-kv-node", + "endorsement": "OR('Org1MSP.member', 'Org2MSP.member')", + "initRequired": false, + "instantiatingOrg": { + "anchorPeers": [ + { + "address": "peer0.org1.example.com", + "couchDbExposePort": 5100, + "db": { + "type": "LevelDb", + }, + "fullAddress": "peer0.org1.example.com:7041", + "gatewayEnabled": true, + "isAnchorPeer": true, + "name": "peer0", + "port": 7041, + }, + { + "address": "peer1.org1.example.com", + "couchDbExposePort": 5101, + "db": { + "type": "LevelDb", + }, + "fullAddress": "peer1.org1.example.com:7042", + "gatewayEnabled": true, + "isAnchorPeer": true, + "name": "peer1", + "port": 7042, + }, + ], + "bootstrapPeers": ""peer0.org1.example.com:7041 peer1.org1.example.com:7042"", + "ca": { + "address": "ca.org1.example.com", + "caAdminNameVar": "ORG1_CA_ADMIN_NAME", + "caAdminPassVar": "ORG1_CA_ADMIN_PASSWORD", + "db": "sqlite", + "exposePort": 7040, + "fullAddress": "ca.org1.example.com:7054", + "port": 7054, + "prefix": "ca", + }, + "cli": { + "address": "cli.org1.example.com", + }, + "cryptoConfigFileName": "crypto-config-org1", + "domain": "org1.example.com", + "headPeer": { + "address": "peer0.org1.example.com", + "couchDbExposePort": 5100, + "db": { + "type": "LevelDb", + }, + "fullAddress": "peer0.org1.example.com:7041", + "gatewayEnabled": true, + "isAnchorPeer": true, + "name": "peer0", + "port": 7041, + }, + "mspName": "Org1MSP", + "name": "Org1", + "ordererGroups": [], + "peers": [ + { + "address": "peer0.org1.example.com", + "couchDbExposePort": 5100, + "db": { + "type": "LevelDb", + }, + "fullAddress": "peer0.org1.example.com:7041", + "gatewayEnabled": true, + "isAnchorPeer": true, + "name": "peer0", + "port": 7041, + }, + ], + "peersCount": 2, + "tools": {}, + }, + "lang": "node", + "name": "duplicateChaincode", + "privateData": [], + "privateDataConfigFile": undefined, + "version": "1.0", + }, + ], + "channels": [ + { + "instantiatingOrg": { + "anchorPeers": [ + { + "address": "peer0.org1.example.com", + "couchDbExposePort": 5100, + "db": { + "type": "LevelDb", + }, + "fullAddress": "peer0.org1.example.com:7041", + "gatewayEnabled": true, + "isAnchorPeer": true, + "name": "peer0", + "port": 7041, + }, + { + "address": "peer1.org1.example.com", + "couchDbExposePort": 5101, + "db": { + "type": "LevelDb", + }, + "fullAddress": "peer1.org1.example.com:7042", + "gatewayEnabled": true, + "isAnchorPeer": true, + "name": "peer1", + "port": 7042, + }, + ], + "bootstrapPeers": ""peer0.org1.example.com:7041 peer1.org1.example.com:7042"", + "ca": { + "address": "ca.org1.example.com", + "caAdminNameVar": "ORG1_CA_ADMIN_NAME", + "caAdminPassVar": "ORG1_CA_ADMIN_PASSWORD", + "db": "sqlite", + "exposePort": 7040, + "fullAddress": "ca.org1.example.com:7054", + "port": 7054, + "prefix": "ca", + }, + "cli": { + "address": "cli.org1.example.com", + }, + "cryptoConfigFileName": "crypto-config-org1", + "domain": "org1.example.com", + "headPeer": { + "address": "peer0.org1.example.com", + "couchDbExposePort": 5100, + "db": { + "type": "LevelDb", + }, + "fullAddress": "peer0.org1.example.com:7041", + "gatewayEnabled": true, + "isAnchorPeer": true, + "name": "peer0", + "port": 7041, + }, + "mspName": "Org1MSP", + "name": "Org1", + "ordererGroups": [], + "peers": [ + { + "address": "peer0.org1.example.com", + "couchDbExposePort": 5100, + "db": { + "type": "LevelDb", + }, + "fullAddress": "peer0.org1.example.com:7041", + "gatewayEnabled": true, + "isAnchorPeer": true, + "name": "peer0", + "port": 7041, + }, + ], + "peersCount": 2, + "tools": {}, + }, + "name": "my-channel1", + "ordererGroup": { + "configtxOrdererDefaults": "Group1Defaults", + "consensus": "solo", + "genesisBlockName": "Group1Genesis.block", + "hostingOrgs": [ + "Orderer", + ], + "name": "group1", + "ordererHead": { + "address": "orderer0.group1.orderer.example.com", + "adminPort": 7053, + "consensus": "solo", + "domain": "orderer.example.com", + "fullAddress": "orderer0.group1.orderer.example.com:7030", + "name": "orderer0.group1", + "orgMspName": "OrdererMSP", + "orgName": "Orderer", + "port": 7030, + }, + "ordererHeads": [ + { + "address": "orderer0.group1.orderer.example.com", + "adminPort": 7053, + "consensus": "solo", + "domain": "orderer.example.com", + "fullAddress": "orderer0.group1.orderer.example.com:7030", + "name": "orderer0.group1", + "orgMspName": "OrdererMSP", + "orgName": "Orderer", + "port": 7030, + }, + ], + "orderers": [ + { + "address": "orderer0.group1.orderer.example.com", + "adminPort": 7053, + "consensus": "solo", + "domain": "orderer.example.com", + "fullAddress": "orderer0.group1.orderer.example.com:7030", + "name": "orderer0.group1", + "orgMspName": "OrdererMSP", + "orgName": "Orderer", + "port": 7030, + }, + ], + "profileName": "Group1Genesis", + }, + "ordererHead": { + "address": "orderer0.group1.orderer.example.com", + "adminPort": 7053, + "consensus": "solo", + "domain": "orderer.example.com", + "fullAddress": "orderer0.group1.orderer.example.com:7030", + "name": "orderer0.group1", + "orgMspName": "OrdererMSP", + "orgName": "Orderer", + "port": 7030, + }, + "orgs": [ + { + "anchorPeers": [ + { + "address": "peer0.org1.example.com", + "couchDbExposePort": 5100, + "db": { + "type": "LevelDb", + }, + "fullAddress": "peer0.org1.example.com:7041", + "gatewayEnabled": true, + "isAnchorPeer": true, + "name": "peer0", + "port": 7041, + }, + { + "address": "peer1.org1.example.com", + "couchDbExposePort": 5101, + "db": { + "type": "LevelDb", + }, + "fullAddress": "peer1.org1.example.com:7042", + "gatewayEnabled": true, + "isAnchorPeer": true, + "name": "peer1", + "port": 7042, + }, + ], + "bootstrapPeers": ""peer0.org1.example.com:7041 peer1.org1.example.com:7042"", + "ca": { + "address": "ca.org1.example.com", + "caAdminNameVar": "ORG1_CA_ADMIN_NAME", + "caAdminPassVar": "ORG1_CA_ADMIN_PASSWORD", + "db": "sqlite", + "exposePort": 7040, + "fullAddress": "ca.org1.example.com:7054", + "port": 7054, + "prefix": "ca", + }, + "cli": { + "address": "cli.org1.example.com", + }, + "cryptoConfigFileName": "crypto-config-org1", + "domain": "org1.example.com", + "headPeer": { + "address": "peer0.org1.example.com", + "couchDbExposePort": 5100, + "db": { + "type": "LevelDb", + }, + "fullAddress": "peer0.org1.example.com:7041", + "gatewayEnabled": true, + "isAnchorPeer": true, + "name": "peer0", + "port": 7041, + }, + "mspName": "Org1MSP", + "name": "Org1", + "ordererGroups": [], + "peers": [ + { + "address": "peer0.org1.example.com", + "couchDbExposePort": 5100, + "db": { + "type": "LevelDb", + }, + "fullAddress": "peer0.org1.example.com:7041", + "gatewayEnabled": true, + "isAnchorPeer": true, + "name": "peer0", + "port": 7041, + }, + ], + "peersCount": 2, + "tools": {}, + }, + { + "anchorPeers": [ + { + "address": "peer0.org2.example.com", + "couchDbExposePort": 5120, + "db": { + "type": "LevelDb", + }, + "fullAddress": "peer0.org2.example.com:7061", + "gatewayEnabled": true, + "isAnchorPeer": true, + "name": "peer0", + "port": 7061, + }, + ], + "bootstrapPeers": "peer0.org2.example.com:7061", + "ca": { + "address": "ca.org2.example.com", + "caAdminNameVar": "ORG2_CA_ADMIN_NAME", + "caAdminPassVar": "ORG2_CA_ADMIN_PASSWORD", + "db": "sqlite", + "exposePort": 7060, + "fullAddress": "ca.org2.example.com:7054", + "port": 7054, + "prefix": "ca", + }, + "cli": { + "address": "cli.org2.example.com", + }, + "cryptoConfigFileName": "crypto-config-org2", + "domain": "org2.example.com", + "headPeer": { + "address": "peer0.org2.example.com", + "couchDbExposePort": 5120, + "db": { + "type": "LevelDb", + }, + "fullAddress": "peer0.org2.example.com:7061", + "gatewayEnabled": true, + "isAnchorPeer": true, + "name": "peer0", + "port": 7061, + }, + "mspName": "Org2MSP", + "name": "Org2", + "ordererGroups": [], + "peers": [ + { + "address": "peer0.org2.example.com", + "couchDbExposePort": 5120, + "db": { + "type": "LevelDb", + }, + "fullAddress": "peer0.org2.example.com:7061", + "gatewayEnabled": true, + "isAnchorPeer": true, + "name": "peer0", + "port": 7061, + }, + ], + "peersCount": 1, + "tools": {}, + }, + ], + "profileName": "MyChannel1", + }, + { + "instantiatingOrg": { + "anchorPeers": [ + { + "address": "peer0.org1.example.com", + "couchDbExposePort": 5100, + "db": { + "type": "LevelDb", + }, + "fullAddress": "peer0.org1.example.com:7041", + "gatewayEnabled": true, + "isAnchorPeer": true, + "name": "peer0", + "port": 7041, + }, + { + "address": "peer1.org1.example.com", + "couchDbExposePort": 5101, + "db": { + "type": "LevelDb", + }, + "fullAddress": "peer1.org1.example.com:7042", + "gatewayEnabled": true, + "isAnchorPeer": true, + "name": "peer1", + "port": 7042, + }, + ], + "bootstrapPeers": ""peer0.org1.example.com:7041 peer1.org1.example.com:7042"", + "ca": { + "address": "ca.org1.example.com", + "caAdminNameVar": "ORG1_CA_ADMIN_NAME", + "caAdminPassVar": "ORG1_CA_ADMIN_PASSWORD", + "db": "sqlite", + "exposePort": 7040, + "fullAddress": "ca.org1.example.com:7054", + "port": 7054, + "prefix": "ca", + }, + "cli": { + "address": "cli.org1.example.com", + }, + "cryptoConfigFileName": "crypto-config-org1", + "domain": "org1.example.com", + "headPeer": { + "address": "peer0.org1.example.com", + "couchDbExposePort": 5100, + "db": { + "type": "LevelDb", + }, + "fullAddress": "peer0.org1.example.com:7041", + "gatewayEnabled": true, + "isAnchorPeer": true, + "name": "peer0", + "port": 7041, + }, + "mspName": "Org1MSP", + "name": "Org1", + "ordererGroups": [], + "peers": [ + { + "address": "peer0.org1.example.com", + "couchDbExposePort": 5100, + "db": { + "type": "LevelDb", + }, + "fullAddress": "peer0.org1.example.com:7041", + "gatewayEnabled": true, + "isAnchorPeer": true, + "name": "peer0", + "port": 7041, + }, + ], + "peersCount": 2, + "tools": {}, + }, + "name": "my-channel2", + "ordererGroup": { + "configtxOrdererDefaults": "Group1Defaults", + "consensus": "solo", + "genesisBlockName": "Group1Genesis.block", + "hostingOrgs": [ + "Orderer", + ], + "name": "group1", + "ordererHead": { + "address": "orderer0.group1.orderer.example.com", + "adminPort": 7053, + "consensus": "solo", + "domain": "orderer.example.com", + "fullAddress": "orderer0.group1.orderer.example.com:7030", + "name": "orderer0.group1", + "orgMspName": "OrdererMSP", + "orgName": "Orderer", + "port": 7030, + }, + "ordererHeads": [ + { + "address": "orderer0.group1.orderer.example.com", + "adminPort": 7053, + "consensus": "solo", + "domain": "orderer.example.com", + "fullAddress": "orderer0.group1.orderer.example.com:7030", + "name": "orderer0.group1", + "orgMspName": "OrdererMSP", + "orgName": "Orderer", + "port": 7030, + }, + ], + "orderers": [ + { + "address": "orderer0.group1.orderer.example.com", + "adminPort": 7053, + "consensus": "solo", + "domain": "orderer.example.com", + "fullAddress": "orderer0.group1.orderer.example.com:7030", + "name": "orderer0.group1", + "orgMspName": "OrdererMSP", + "orgName": "Orderer", + "port": 7030, + }, + ], + "profileName": "Group1Genesis", + }, + "ordererHead": { + "address": "orderer0.group1.orderer.example.com", + "adminPort": 7053, + "consensus": "solo", + "domain": "orderer.example.com", + "fullAddress": "orderer0.group1.orderer.example.com:7030", + "name": "orderer0.group1", + "orgMspName": "OrdererMSP", + "orgName": "Orderer", + "port": 7030, + }, + "orgs": [ + { + "anchorPeers": [ + { + "address": "peer0.org1.example.com", + "couchDbExposePort": 5100, + "db": { + "type": "LevelDb", + }, + "fullAddress": "peer0.org1.example.com:7041", + "gatewayEnabled": true, + "isAnchorPeer": true, + "name": "peer0", + "port": 7041, + }, + { + "address": "peer1.org1.example.com", + "couchDbExposePort": 5101, + "db": { + "type": "LevelDb", + }, + "fullAddress": "peer1.org1.example.com:7042", + "gatewayEnabled": true, + "isAnchorPeer": true, + "name": "peer1", + "port": 7042, + }, + ], + "bootstrapPeers": ""peer0.org1.example.com:7041 peer1.org1.example.com:7042"", + "ca": { + "address": "ca.org1.example.com", + "caAdminNameVar": "ORG1_CA_ADMIN_NAME", + "caAdminPassVar": "ORG1_CA_ADMIN_PASSWORD", + "db": "sqlite", + "exposePort": 7040, + "fullAddress": "ca.org1.example.com:7054", + "port": 7054, + "prefix": "ca", + }, + "cli": { + "address": "cli.org1.example.com", + }, + "cryptoConfigFileName": "crypto-config-org1", + "domain": "org1.example.com", + "headPeer": { + "address": "peer0.org1.example.com", + "couchDbExposePort": 5100, + "db": { + "type": "LevelDb", + }, + "fullAddress": "peer0.org1.example.com:7041", + "gatewayEnabled": true, + "isAnchorPeer": true, + "name": "peer0", + "port": 7041, + }, + "mspName": "Org1MSP", + "name": "Org1", + "ordererGroups": [], + "peers": [ + { + "address": "peer0.org1.example.com", + "couchDbExposePort": 5100, + "db": { + "type": "LevelDb", + }, + "fullAddress": "peer0.org1.example.com:7041", + "gatewayEnabled": true, + "isAnchorPeer": true, + "name": "peer0", + "port": 7041, + }, + ], + "peersCount": 2, + "tools": {}, + }, + { + "anchorPeers": [ + { + "address": "peer0.org2.example.com", + "couchDbExposePort": 5120, + "db": { + "type": "LevelDb", + }, + "fullAddress": "peer0.org2.example.com:7061", + "gatewayEnabled": true, + "isAnchorPeer": true, + "name": "peer0", + "port": 7061, + }, + ], + "bootstrapPeers": "peer0.org2.example.com:7061", + "ca": { + "address": "ca.org2.example.com", + "caAdminNameVar": "ORG2_CA_ADMIN_NAME", + "caAdminPassVar": "ORG2_CA_ADMIN_PASSWORD", + "db": "sqlite", + "exposePort": 7060, + "fullAddress": "ca.org2.example.com:7054", + "port": 7054, + "prefix": "ca", + }, + "cli": { + "address": "cli.org2.example.com", + }, + "cryptoConfigFileName": "crypto-config-org2", + "domain": "org2.example.com", + "headPeer": { + "address": "peer0.org2.example.com", + "couchDbExposePort": 5120, + "db": { + "type": "LevelDb", + }, + "fullAddress": "peer0.org2.example.com:7061", + "gatewayEnabled": true, + "isAnchorPeer": true, + "name": "peer0", + "port": 7061, + }, + "mspName": "Org2MSP", + "name": "Org2", + "ordererGroups": [], + "peers": [ + { + "address": "peer0.org2.example.com", + "couchDbExposePort": 5120, + "db": { + "type": "LevelDb", + }, + "fullAddress": "peer0.org2.example.com:7061", + "gatewayEnabled": true, + "isAnchorPeer": true, + "name": "peer0", + "port": 7061, + }, + ], + "peersCount": 1, + "tools": {}, + }, + ], + "profileName": "MyChannel2", + }, + ], + "global": { + "capabilities": { + "application": "V2_0", + "channel": "V2_0", + "isV2": true, + "isV3": false, + "orderer": "V2_0", + }, + "engine": "docker", + "fabricBaseosVersion": "2.4.7", + "fabricCaVersion": "1.5.5", + "fabricCcenvVersion": "2.4.7", + "fabricJavaenvVersion": "2.4", + "fabricNodeenvVersion": "2.4", + "fabricRecommendedNodeVersion": "16", + "fabricToolsVersion": "2.4.7", + "fabricVersion": "2.4.7", + "monitoring": { + "loglevel": "info", + }, + "paths": { + "chaincodesBaseDir": "", + "fabloConfig": "", + }, + "tls": false, + "tools": {}, + }, + "hooks": { + "postGenerate": "", + }, + "orderedHeadsDistinct": [ + { + "address": "orderer0.group1.orderer.example.com", + "adminPort": 7053, + "consensus": "solo", + "domain": "orderer.example.com", + "fullAddress": "orderer0.group1.orderer.example.com:7030", + "name": "orderer0.group1", + "orgMspName": "OrdererMSP", + "orgName": "Orderer", + "port": 7030, + }, + ], + "ordererGroups": [ + { + "configtxOrdererDefaults": "Group1Defaults", + "consensus": "solo", + "genesisBlockName": "Group1Genesis.block", + "hostingOrgs": [ + "Orderer", + ], + "name": "group1", + "ordererHead": { + "address": "orderer0.group1.orderer.example.com", + "adminPort": 7053, + "consensus": "solo", + "domain": "orderer.example.com", + "fullAddress": "orderer0.group1.orderer.example.com:7030", + "name": "orderer0.group1", + "orgMspName": "OrdererMSP", + "orgName": "Orderer", + "port": 7030, + }, + "ordererHeads": [ + { + "address": "orderer0.group1.orderer.example.com", + "adminPort": 7053, + "consensus": "solo", + "domain": "orderer.example.com", + "fullAddress": "orderer0.group1.orderer.example.com:7030", + "name": "orderer0.group1", + "orgMspName": "OrdererMSP", + "orgName": "Orderer", + "port": 7030, + }, + ], + "orderers": [ + { + "address": "orderer0.group1.orderer.example.com", + "adminPort": 7053, + "consensus": "solo", + "domain": "orderer.example.com", + "fullAddress": "orderer0.group1.orderer.example.com:7030", + "name": "orderer0.group1", + "orgMspName": "OrdererMSP", + "orgName": "Orderer", + "port": 7030, + }, + ], + "profileName": "Group1Genesis", + }, + ], + "orgs": [ + { + "anchorPeers": [], + "bootstrapPeers": """", + "ca": { + "address": "ca.orderer.example.com", + "caAdminNameVar": "ORDERER_CA_ADMIN_NAME", + "caAdminPassVar": "ORDERER_CA_ADMIN_PASSWORD", + "db": "sqlite", + "exposePort": 7020, + "fullAddress": "ca.orderer.example.com:7054", + "port": 7054, + "prefix": "ca", + }, + "cli": { + "address": "cli.orderer.example.com", + }, + "cryptoConfigFileName": "crypto-config-orderer", + "domain": "orderer.example.com", + "headPeer": undefined, + "mspName": "OrdererMSP", + "name": "Orderer", + "ordererGroups": [ + { + "configtxOrdererDefaults": "Group1Defaults", + "consensus": "solo", + "genesisBlockName": "Group1Genesis.block", + "hostingOrgs": [ + "Orderer", + ], + "name": "group1", + "ordererHeads": [ + { + "address": "orderer0.group1.orderer.example.com", + "adminPort": 7053, + "consensus": "solo", + "domain": "orderer.example.com", + "fullAddress": "orderer0.group1.orderer.example.com:7030", + "name": "orderer0.group1", + "orgMspName": "OrdererMSP", + "orgName": "Orderer", + "port": 7030, + }, + ], + "orderers": [ + { + "address": "orderer0.group1.orderer.example.com", + "adminPort": 7053, + "consensus": "solo", + "domain": "orderer.example.com", + "fullAddress": "orderer0.group1.orderer.example.com:7030", + "name": "orderer0.group1", + "orgMspName": "OrdererMSP", + "orgName": "Orderer", + "port": 7030, + }, + ], + "profileName": "Group1Genesis", + }, + ], + "peers": [], + "peersCount": 0, + "tools": {}, + }, + { + "anchorPeers": [ + { + "address": "peer0.org1.example.com", + "couchDbExposePort": 5100, + "db": { + "type": "LevelDb", + }, + "fullAddress": "peer0.org1.example.com:7041", + "gatewayEnabled": true, + "isAnchorPeer": true, + "name": "peer0", + "port": 7041, + }, + { + "address": "peer1.org1.example.com", + "couchDbExposePort": 5101, + "db": { + "type": "LevelDb", + }, + "fullAddress": "peer1.org1.example.com:7042", + "gatewayEnabled": true, + "isAnchorPeer": true, + "name": "peer1", + "port": 7042, + }, + ], + "bootstrapPeers": ""peer0.org1.example.com:7041 peer1.org1.example.com:7042"", + "ca": { + "address": "ca.org1.example.com", + "caAdminNameVar": "ORG1_CA_ADMIN_NAME", + "caAdminPassVar": "ORG1_CA_ADMIN_PASSWORD", + "db": "sqlite", + "exposePort": 7040, + "fullAddress": "ca.org1.example.com:7054", + "port": 7054, + "prefix": "ca", + }, + "cli": { + "address": "cli.org1.example.com", + }, + "cryptoConfigFileName": "crypto-config-org1", + "domain": "org1.example.com", + "headPeer": { + "address": "peer0.org1.example.com", + "couchDbExposePort": 5100, + "db": { + "type": "LevelDb", + }, + "fullAddress": "peer0.org1.example.com:7041", + "gatewayEnabled": true, + "isAnchorPeer": true, + "name": "peer0", + "port": 7041, + }, + "mspName": "Org1MSP", + "name": "Org1", + "ordererGroups": [], + "peers": [ + { + "address": "peer0.org1.example.com", + "couchDbExposePort": 5100, + "db": { + "type": "LevelDb", + }, + "fullAddress": "peer0.org1.example.com:7041", + "gatewayEnabled": true, + "isAnchorPeer": true, + "name": "peer0", + "port": 7041, + }, + { + "address": "peer1.org1.example.com", + "couchDbExposePort": 5101, + "db": { + "type": "LevelDb", + }, + "fullAddress": "peer1.org1.example.com:7042", + "gatewayEnabled": true, + "isAnchorPeer": true, + "name": "peer1", + "port": 7042, + }, + ], + "peersCount": 2, + "tools": {}, + }, + { + "anchorPeers": [ + { + "address": "peer0.org2.example.com", + "couchDbExposePort": 5120, + "db": { + "type": "LevelDb", + }, + "fullAddress": "peer0.org2.example.com:7061", + "gatewayEnabled": true, + "isAnchorPeer": true, + "name": "peer0", + "port": 7061, + }, + ], + "bootstrapPeers": "peer0.org2.example.com:7061", + "ca": { + "address": "ca.org2.example.com", + "caAdminNameVar": "ORG2_CA_ADMIN_NAME", + "caAdminPassVar": "ORG2_CA_ADMIN_PASSWORD", + "db": "sqlite", + "exposePort": 7060, + "fullAddress": "ca.org2.example.com:7054", + "port": 7054, + "prefix": "ca", + }, + "cli": { + "address": "cli.org2.example.com", + }, + "cryptoConfigFileName": "crypto-config-org2", + "domain": "org2.example.com", + "headPeer": { + "address": "peer0.org2.example.com", + "couchDbExposePort": 5120, + "db": { + "type": "LevelDb", + }, + "fullAddress": "peer0.org2.example.com:7061", + "gatewayEnabled": true, + "isAnchorPeer": true, + "name": "peer0", + "port": 7061, + }, + "mspName": "Org2MSP", + "name": "Org2", + "ordererGroups": [], + "peers": [ + { + "address": "peer0.org2.example.com", + "couchDbExposePort": 5120, + "db": { + "type": "LevelDb", + }, + "fullAddress": "peer0.org2.example.com:7061", + "gatewayEnabled": true, + "isAnchorPeer": true, + "name": "peer0", + "port": 7061, + }, + ], + "peersCount": 1, + "tools": {}, + }, + ], +} +`; + exports[`extend config samples/fablo-config-hlf2-2orgs-2chaincodes-raft.yaml 1`] = ` { "chaincodes": [ diff --git a/e2e/__snapshots__/fablo-config-hlf2-2orgs-2chaincodes-private-data.yaml.test.ts.snap b/e2e/__snapshots__/fablo-config-hlf2-2orgs-2chaincodes-private-data.yaml.test.ts.snap index b5180992d..aeb7fcbae 100644 --- a/e2e/__snapshots__/fablo-config-hlf2-2orgs-2chaincodes-private-data.yaml.test.ts.snap +++ b/e2e/__snapshots__/fablo-config-hlf2-2orgs-2chaincodes-private-data.yaml.test.ts.snap @@ -317,272 +317,6 @@ certificateAuthorities: " `; -exports[`samples/fablo-config-hlf2-2orgs-2chaincodes-private-data.yaml should create proper e2e/__tmp__/samples/fablo-config-hlf2-2orgs-2chaincodes-private-data.yaml.tmpdir/fablo-target/fabric-config/connection-profiles/connection-profile-orderer1.json from samples/fablo-config-hlf2-2orgs-2chaincodes-private-data.yaml 1`] = ` -"{ - "name": "fablo-test-network-orderer1", - "description": "Connection profile for Orderer1 in Fablo network", - "version": "1.0.0", - "client": { - "organization": "Orderer1" - }, - "organizations": { - "Orderer1": { - "mspid": "Orderer1MSP", - "peers": [ - "peer0.org1.example.com", - "peer1.org1.example.com", - "peer0.org2.example.com", - "peer1.org2.example.com" - ], - "certificateAuthorities": [ - "ca.orderer1.com" - ] - } - }, - "peers": { - "peer0.org1.example.com": { - "url": "grpcs://localhost:7061", - "tlsCACerts": { - "path": "/samples/fablo-target/fabric-config/crypto-config/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/tls/ca.crt" - }, - "grpcOptions": { - "ssl-target-name-override": "peer0.org1.example.com" - } - }, - "peer1.org1.example.com": { - "url": "grpcs://localhost:7062", - "tlsCACerts": { - "path": "/samples/fablo-target/fabric-config/crypto-config/peerOrganizations/org1.example.com/peers/peer1.org1.example.com/tls/ca.crt" - }, - "grpcOptions": { - "ssl-target-name-override": "peer1.org1.example.com" - } - }, - "peer0.org2.example.com": { - "url": "grpcs://localhost:7081", - "tlsCACerts": { - "path": "/samples/fablo-target/fabric-config/crypto-config/peerOrganizations/org2.example.com/peers/peer0.org2.example.com/tls/ca.crt" - }, - "grpcOptions": { - "ssl-target-name-override": "peer0.org2.example.com" - } - }, - "peer1.org2.example.com": { - "url": "grpcs://localhost:7082", - "tlsCACerts": { - "path": "/samples/fablo-target/fabric-config/crypto-config/peerOrganizations/org2.example.com/peers/peer1.org2.example.com/tls/ca.crt" - }, - "grpcOptions": { - "ssl-target-name-override": "peer1.org2.example.com" - } - } - }, - "certificateAuthorities": { - "ca.orderer1.com": { - "url": "https://localhost:7020", - "caName": "ca.orderer1.com", - "tlsCACerts": { - "path": "/samples/fablo-target/fabric-config/crypto-config/peerOrganizations/orderer1.com/ca/ca.orderer1.com-cert.pem" - }, - "httpOptions": { - "verify": false - } - } - } -} -" -`; - -exports[`samples/fablo-config-hlf2-2orgs-2chaincodes-private-data.yaml should create proper e2e/__tmp__/samples/fablo-config-hlf2-2orgs-2chaincodes-private-data.yaml.tmpdir/fablo-target/fabric-config/connection-profiles/connection-profile-orderer1.yaml from samples/fablo-config-hlf2-2orgs-2chaincodes-private-data.yaml 1`] = ` -"name: fablo-test-network-orderer1 -description: Connection profile for Orderer1 in Fablo network -version: 1.0.0 -client: - organization: Orderer1 -organizations: - Orderer1: - mspid: Orderer1MSP - peers: - - peer0.org1.example.com - - peer1.org1.example.com - - peer0.org2.example.com - - peer1.org2.example.com - certificateAuthorities: - - ca.orderer1.com -peers: - peer0.org1.example.com: - url: grpcs://localhost:7061 - tlsCACerts: - path: >- - /samples/fablo-target/fabric-config/crypto-config/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/tls/ca.crt - grpcOptions: - ssl-target-name-override: peer0.org1.example.com - peer1.org1.example.com: - url: grpcs://localhost:7062 - tlsCACerts: - path: >- - /samples/fablo-target/fabric-config/crypto-config/peerOrganizations/org1.example.com/peers/peer1.org1.example.com/tls/ca.crt - grpcOptions: - ssl-target-name-override: peer1.org1.example.com - peer0.org2.example.com: - url: grpcs://localhost:7081 - tlsCACerts: - path: >- - /samples/fablo-target/fabric-config/crypto-config/peerOrganizations/org2.example.com/peers/peer0.org2.example.com/tls/ca.crt - grpcOptions: - ssl-target-name-override: peer0.org2.example.com - peer1.org2.example.com: - url: grpcs://localhost:7082 - tlsCACerts: - path: >- - /samples/fablo-target/fabric-config/crypto-config/peerOrganizations/org2.example.com/peers/peer1.org2.example.com/tls/ca.crt - grpcOptions: - ssl-target-name-override: peer1.org2.example.com -certificateAuthorities: - ca.orderer1.com: - url: https://localhost:7020 - caName: ca.orderer1.com - tlsCACerts: - path: >- - /samples/fablo-target/fabric-config/crypto-config/peerOrganizations/orderer1.com/ca/ca.orderer1.com-cert.pem - httpOptions: - verify: false -" -`; - -exports[`samples/fablo-config-hlf2-2orgs-2chaincodes-private-data.yaml should create proper e2e/__tmp__/samples/fablo-config-hlf2-2orgs-2chaincodes-private-data.yaml.tmpdir/fablo-target/fabric-config/connection-profiles/connection-profile-orderer2.json from samples/fablo-config-hlf2-2orgs-2chaincodes-private-data.yaml 1`] = ` -"{ - "name": "fablo-test-network-orderer2", - "description": "Connection profile for Orderer2 in Fablo network", - "version": "1.0.0", - "client": { - "organization": "Orderer2" - }, - "organizations": { - "Orderer2": { - "mspid": "Orderer2MSP", - "peers": [ - "peer0.org1.example.com", - "peer1.org1.example.com", - "peer0.org2.example.com", - "peer1.org2.example.com" - ], - "certificateAuthorities": [ - "ca.orderer2.com" - ] - } - }, - "peers": { - "peer0.org1.example.com": { - "url": "grpcs://localhost:7061", - "tlsCACerts": { - "path": "/samples/fablo-target/fabric-config/crypto-config/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/tls/ca.crt" - }, - "grpcOptions": { - "ssl-target-name-override": "peer0.org1.example.com" - } - }, - "peer1.org1.example.com": { - "url": "grpcs://localhost:7062", - "tlsCACerts": { - "path": "/samples/fablo-target/fabric-config/crypto-config/peerOrganizations/org1.example.com/peers/peer1.org1.example.com/tls/ca.crt" - }, - "grpcOptions": { - "ssl-target-name-override": "peer1.org1.example.com" - } - }, - "peer0.org2.example.com": { - "url": "grpcs://localhost:7081", - "tlsCACerts": { - "path": "/samples/fablo-target/fabric-config/crypto-config/peerOrganizations/org2.example.com/peers/peer0.org2.example.com/tls/ca.crt" - }, - "grpcOptions": { - "ssl-target-name-override": "peer0.org2.example.com" - } - }, - "peer1.org2.example.com": { - "url": "grpcs://localhost:7082", - "tlsCACerts": { - "path": "/samples/fablo-target/fabric-config/crypto-config/peerOrganizations/org2.example.com/peers/peer1.org2.example.com/tls/ca.crt" - }, - "grpcOptions": { - "ssl-target-name-override": "peer1.org2.example.com" - } - } - }, - "certificateAuthorities": { - "ca.orderer2.com": { - "url": "https://localhost:7040", - "caName": "ca.orderer2.com", - "tlsCACerts": { - "path": "/samples/fablo-target/fabric-config/crypto-config/peerOrganizations/orderer2.com/ca/ca.orderer2.com-cert.pem" - }, - "httpOptions": { - "verify": false - } - } - } -} -" -`; - -exports[`samples/fablo-config-hlf2-2orgs-2chaincodes-private-data.yaml should create proper e2e/__tmp__/samples/fablo-config-hlf2-2orgs-2chaincodes-private-data.yaml.tmpdir/fablo-target/fabric-config/connection-profiles/connection-profile-orderer2.yaml from samples/fablo-config-hlf2-2orgs-2chaincodes-private-data.yaml 1`] = ` -"name: fablo-test-network-orderer2 -description: Connection profile for Orderer2 in Fablo network -version: 1.0.0 -client: - organization: Orderer2 -organizations: - Orderer2: - mspid: Orderer2MSP - peers: - - peer0.org1.example.com - - peer1.org1.example.com - - peer0.org2.example.com - - peer1.org2.example.com - certificateAuthorities: - - ca.orderer2.com -peers: - peer0.org1.example.com: - url: grpcs://localhost:7061 - tlsCACerts: - path: >- - /samples/fablo-target/fabric-config/crypto-config/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/tls/ca.crt - grpcOptions: - ssl-target-name-override: peer0.org1.example.com - peer1.org1.example.com: - url: grpcs://localhost:7062 - tlsCACerts: - path: >- - /samples/fablo-target/fabric-config/crypto-config/peerOrganizations/org1.example.com/peers/peer1.org1.example.com/tls/ca.crt - grpcOptions: - ssl-target-name-override: peer1.org1.example.com - peer0.org2.example.com: - url: grpcs://localhost:7081 - tlsCACerts: - path: >- - /samples/fablo-target/fabric-config/crypto-config/peerOrganizations/org2.example.com/peers/peer0.org2.example.com/tls/ca.crt - grpcOptions: - ssl-target-name-override: peer0.org2.example.com - peer1.org2.example.com: - url: grpcs://localhost:7082 - tlsCACerts: - path: >- - /samples/fablo-target/fabric-config/crypto-config/peerOrganizations/org2.example.com/peers/peer1.org2.example.com/tls/ca.crt - grpcOptions: - ssl-target-name-override: peer1.org2.example.com -certificateAuthorities: - ca.orderer2.com: - url: https://localhost:7040 - caName: ca.orderer2.com - tlsCACerts: - path: >- - /samples/fablo-target/fabric-config/crypto-config/peerOrganizations/orderer2.com/ca/ca.orderer2.com-cert.pem - httpOptions: - verify: false -" -`; - exports[`samples/fablo-config-hlf2-2orgs-2chaincodes-private-data.yaml should create proper e2e/__tmp__/samples/fablo-config-hlf2-2orgs-2chaincodes-private-data.yaml.tmpdir/fablo-target/fabric-config/connection-profiles/connection-profile-org1.json from samples/fablo-config-hlf2-2orgs-2chaincodes-private-data.yaml 1`] = ` "{ "name": "fablo-test-network-org1", @@ -748,34 +482,6 @@ exports[`samples/fablo-config-hlf2-2orgs-2chaincodes-private-data.yaml should cr " `; -exports[`samples/fablo-config-hlf2-2orgs-2chaincodes-private-data.yaml should create proper e2e/__tmp__/samples/fablo-config-hlf2-2orgs-2chaincodes-private-data.yaml.tmpdir/fablo-target/fabric-config/crypto-config-orderer1.yaml from samples/fablo-config-hlf2-2orgs-2chaincodes-private-data.yaml 1`] = ` -"PeerOrgs: - - Name: Orderer1 - Domain: orderer1.com - Specs: - - Hostname: orderer0.group1 - - Hostname: orderer1.group1 - - Hostname: orderer2.group1 - Template: - Count: 0 - Users: - Count: 1 -" -`; - -exports[`samples/fablo-config-hlf2-2orgs-2chaincodes-private-data.yaml should create proper e2e/__tmp__/samples/fablo-config-hlf2-2orgs-2chaincodes-private-data.yaml.tmpdir/fablo-target/fabric-config/crypto-config-orderer2.yaml from samples/fablo-config-hlf2-2orgs-2chaincodes-private-data.yaml 1`] = ` -"PeerOrgs: - - Name: Orderer2 - Domain: orderer2.com - Specs: - - Hostname: orderer0.group2 - Template: - Count: 0 - Users: - Count: 1 -" -`; - exports[`samples/fablo-config-hlf2-2orgs-2chaincodes-private-data.yaml should create proper e2e/__tmp__/samples/fablo-config-hlf2-2orgs-2chaincodes-private-data.yaml.tmpdir/fablo-target/fabric-config/crypto-config-org1.yaml from samples/fablo-config-hlf2-2orgs-2chaincodes-private-data.yaml 1`] = ` "PeerOrgs: - Name: Org1 @@ -1318,1008 +1024,6 @@ metrics: " `; -exports[`samples/fablo-config-hlf2-2orgs-2chaincodes-private-data.yaml should create proper e2e/__tmp__/samples/fablo-config-hlf2-2orgs-2chaincodes-private-data.yaml.tmpdir/fablo-target/fabric-config/fabric-ca-server-config/orderer1.com/fabric-ca-server-config.yaml from samples/fablo-config-hlf2-2orgs-2chaincodes-private-data.yaml 1`] = ` -"############################################################################# -# This is a configuration file for the fabric-ca-server command. -# -# COMMAND LINE ARGUMENTS AND ENVIRONMENT VARIABLES -# ------------------------------------------------ -# Each configuration element can be overridden via command line -# arguments or environment variables. The precedence for determining -# the value of each element is as follows: -# 1) command line argument -# Examples: -# a) --port 443 -# To set the listening port -# b) --ca.keyfile ../mykey.pem -# To set the "keyfile" element in the "ca" section below; -# note the '.' separator character. -# 2) environment variable -# Examples: -# a) FABRIC_CA_SERVER_PORT=443 -# To set the listening port -# b) FABRIC_CA_SERVER_CA_KEYFILE="../mykey.pem" -# To set the "keyfile" element in the "ca" section below; -# note the '_' separator character. -# 3) configuration file -# 4) default value (if there is one) -# All default values are shown beside each element below. -# -# FILE NAME ELEMENTS -# ------------------ -# The value of all fields whose name ends with "file" or "files" are -# name or names of other files. -# For example, see "tls.certfile" and "tls.clientauth.certfiles". -# The value of each of these fields can be a simple filename, a -# relative path, or an absolute path. If the value is not an -# absolute path, it is interpreted as being relative to the location -# of this configuration file. -# -############################################################################# - -# Version of config file -version: 1.5.5 - -# Server's listening port (default: 7054) -port: 7054 - -# Cross-Origin Resource Sharing (CORS) -cors: - enabled: false - origins: - - "*" - -# Enables debug logging (default: false) -debug: false - -# Size limit of an acceptable CRL in bytes (default: 512000) -crlsizelimit: 512000 - -############################################################################# -# TLS section for the server's listening port -# -# The following types are supported for client authentication: NoClientCert, -# RequestClientCert, RequireAnyClientCert, VerifyClientCertIfGiven, -# and RequireAndVerifyClientCert. -# -# Certfiles is a list of root certificate authorities that the server uses -# when verifying client certificates. -############################################################################# -tls: - # Enable TLS (default: false) - enabled: false - # TLS for the server's listening port - certfile: - keyfile: - clientauth: - type: noclientcert - certfiles: - -############################################################################# -# The CA section contains information related to the Certificate Authority -# including the name of the CA, which should be unique for all members -# of a blockchain network. It also includes the key and certificate files -# used when issuing enrollment certificates (ECerts). -# The chainfile (if it exists) contains the certificate chain which -# should be trusted for this CA, where the 1st in the chain is always the -# root CA certificate. -############################################################################# -ca: - # Name of this CA - name: - # Key file (is only used to import a private key into BCCSP) - keyfile: - # Certificate file (default: ca-cert.pem) - certfile: - # Chain file - chainfile: - -############################################################################# -# The gencrl REST endpoint is used to generate a CRL that contains revoked -# certificates. This section contains configuration options that are used -# during gencrl request processing. -############################################################################# -crl: - # Specifies expiration for the generated CRL. The number of hours - # specified by this property is added to the UTC time, the resulting time - # is used to set the 'Next Update' date of the CRL. - expiry: 24h - -############################################################################# -# The registry section controls how the fabric-ca-server does two things: -# 1) authenticates enrollment requests which contain a username and password -# (also known as an enrollment ID and secret). -# 2) once authenticated, retrieves the identity's attribute names and values. -# These attributes are useful for making access control decisions in -# chaincode. -# There are two main configuration options: -# 1) The fabric-ca-server is the registry. -# This is true if "ldap.enabled" in the ldap section below is false. -# 2) An LDAP server is the registry, in which case the fabric-ca-server -# calls the LDAP server to perform these tasks. -# This is true if "ldap.enabled" in the ldap section below is true, -# which means this "registry" section is ignored. -############################################################################# -registry: - # Maximum number of times a password/secret can be reused for enrollment - # (default: -1, which means there is no limit) - maxenrollments: -1 - - # Contains identity information which is used when LDAP is disabled - identities: - - name: admin - pass: adminpw - type: client - affiliation: "" - attrs: - hf.Registrar.Roles: "*" - hf.Registrar.DelegateRoles: "*" - hf.Revoker: true - hf.IntermediateCA: true - hf.GenCRL: true - hf.Registrar.Attributes: "*" - hf.AffiliationMgr: true - -############################################################################# -# Database section -# Supported types are: "sqlite3", "postgres", and "mysql". -# The datasource value depends on the type. -# If the type is "sqlite3", the datasource value is a file name to use -# as the database store. Since "sqlite3" is an embedded database, it -# may not be used if you want to run the fabric-ca-server in a cluster. -# To run the fabric-ca-server in a cluster, you must choose "postgres" -# or "mysql". -############################################################################# -db: - type: sqlite3 - datasource: fabric-ca-server.db - tls: - enabled: false - certfiles: - client: - certfile: - keyfile: - -############################################################################# -# LDAP section -# If LDAP is enabled, the fabric-ca-server calls LDAP to: -# 1) authenticate enrollment ID and secret (i.e. username and password) -# for enrollment requests; -# 2) To retrieve identity attributes -############################################################################# -ldap: - # Enables or disables the LDAP client (default: false) - # If this is set to true, the "registry" section is ignored. - enabled: false - # The URL of the LDAP server - url: ldap://:@:/ - # TLS configuration for the client connection to the LDAP server - tls: - certfiles: - client: - certfile: - keyfile: - # Attribute related configuration for mapping from LDAP entries to Fabric CA attributes - attribute: - # 'names' is an array of strings containing the LDAP attribute names which are - # requested from the LDAP server for an LDAP identity's entry - names: ['uid', 'member'] - # The 'converters' section is used to convert an LDAP entry to the value of - # a fabric CA attribute. - # For example, the following converts an LDAP 'uid' attribute - # whose value begins with 'revoker' to a fabric CA attribute - # named "hf.Revoker" with a value of "true" (because the boolean expression - # evaluates to true). - # converters: - # - name: hf.Revoker - # value: attr("uid") =~ "revoker*" - converters: - - name: - value: - # The 'maps' section contains named maps which may be referenced by the 'map' - # function in the 'converters' section to map LDAP responses to arbitrary values. - # For example, assume a user has an LDAP attribute named 'member' which has multiple - # values which are each a distinguished name (i.e. a DN). For simplicity, assume the - # values of the 'member' attribute are 'dn1', 'dn2', and 'dn3'. - # Further assume the following configuration. - # converters: - # - name: hf.Registrar.Roles - # value: map(attr("member"),"groups") - # maps: - # groups: - # - name: dn1 - # value: peer - # - name: dn2 - # value: client - # The value of the user's 'hf.Registrar.Roles' attribute is then computed to be - # "peer,client,dn3". This is because the value of 'attr("member")' is - # "dn1,dn2,dn3", and the call to 'map' with a 2nd argument of - # "group" replaces "dn1" with "peer" and "dn2" with "client". - maps: - groups: - - name: - value: - -############################################################################# -# Affiliations section. Fabric CA server can be bootstrapped with the -# affiliations specified in this section. Affiliations are specified as maps. -# For example: -# businessunit1: -# department1: -# - team1 -# businessunit2: -# - department2 -# - department3 -# -# Affiliations are hierarchical in nature. In the above example, -# department1 (used as businessunit1.department1) is the child of businessunit1. -# team1 (used as businessunit1.department1.team1) is the child of department1. -# department2 (used as businessunit2.department2) and department3 (businessunit2.department3) -# are children of businessunit2. -# Note: Affiliations are case sensitive except for the non-leaf affiliations -# (like businessunit1, department1, businessunit2) that are specified in the configuration file, -# which are always stored in lower case. -############################################################################# -affiliations: - orderer1: - -############################################################################# -# Signing section -# -# The "default" subsection is used to sign enrollment certificates; -# the default expiration ("expiry" field) is "8760h", which is 1 year in hours. -# -# The "ca" profile subsection is used to sign intermediate CA certificates; -# the default expiration ("expiry" field) is "43800h" which is 5 years in hours. -# Note that "isca" is true, meaning that it issues a CA certificate. -# A maxpathlen of 0 means that the intermediate CA cannot issue other -# intermediate CA certificates, though it can still issue end entity certificates. -# (See RFC 5280, section 4.2.1.9) -# -# The "tls" profile subsection is used to sign TLS certificate requests; -# the default expiration ("expiry" field) is "8760h", which is 1 year in hours. -############################################################################# -signing: - default: - usage: - - digital signature - expiry: 8760h - profiles: - ca: - usage: - - cert sign - - crl sign - expiry: 43800h - caconstraint: - isca: true - maxpathlen: 0 - tls: - usage: - - signing - - key encipherment - - server auth - - client auth - - key agreement - expiry: 8760h - -########################################################################### -# Certificate Signing Request (CSR) section. -# This controls the creation of the root CA certificate. -# The expiration for the root CA certificate is configured with the -# "ca.expiry" field below, whose default value is "131400h" which is -# 15 years in hours. -# The pathlength field is used to limit CA certificate hierarchy as described -# in section 4.2.1.9 of RFC 5280. -# Examples: -# 1) No pathlength value means no limit is requested. -# 2) pathlength == 1 means a limit of 1 is requested which is the default for -# a root CA. This means the root CA can issue intermediate CA certificates, -# but these intermediate CAs may not in turn issue other CA certificates -# though they can still issue end entity certificates. -# 3) pathlength == 0 means a limit of 0 is requested; -# this is the default for an intermediate CA, which means it can not issue -# CA certificates though it can still issue end entity certificates. -########################################################################### -csr: - cn: fabric-ca-server - keyrequest: - algo: ecdsa - size: 256 - names: - - C: US - ST: "North Carolina" - L: - O: Hyperledger - OU: Fabric - hosts: - - 483cccf16a98 - - localhost - ca: - expiry: 131400h - pathlength: 1 - -########################################################################### -# Each CA can issue both X509 enrollment certificate as well as Idemix -# Credential. This section specifies configuration for the issuer component -# that is responsible for issuing Idemix credentials. -########################################################################### -idemix: - # Specifies pool size for revocation handles. A revocation handle is an unique identifier of an - # Idemix credential. The issuer will create a pool revocation handles of this specified size. When - # a credential is requested, issuer will get handle from the pool and assign it to the credential. - # Issuer will repopulate the pool with new handles when the last handle in the pool is used. - # A revocation handle and credential revocation information (CRI) are used to create non revocation proof - # by the prover to prove to the verifier that her credential is not revoked. - rhpoolsize: 1000 - - # The Idemix credential issuance is a two step process. First step is to get a nonce from the issuer - # and second step is send credential request that is constructed using the nonce to the isuser to - # request a credential. This configuration property specifies expiration for the nonces. By default is - # nonces expire after 15 seconds. The value is expressed in the time.Duration format (see https://golang.org/pkg/time/#ParseDuration). - nonceexpiration: 15s - - # Specifies interval at which expired nonces are removed from datastore. Default value is 15 minutes. - # The value is expressed in the time.Duration format (see https://golang.org/pkg/time/#ParseDuration) - noncesweepinterval: 15m - -############################################################################# -# BCCSP (BlockChain Crypto Service Provider) section is used to select which -# crypto library implementation to use -############################################################################# -bccsp: - default: SW - sw: - hash: SHA2 - security: 256 - filekeystore: - # The directory used for the software file-based keystore - keystore: msp/keystore - -############################################################################# -# Multi CA section -# -# Each Fabric CA server contains one CA by default. This section is used -# to configure multiple CAs in a single server. -# -# 1) --cacount -# Automatically generate non-default CAs. The names of these -# additional CAs are "ca1", "ca2", ... "caN", where "N" is -# This is particularly useful in a development environment to quickly set up -# multiple CAs. Note that, this config option is not applicable to intermediate CA server -# i.e., Fabric CA server that is started with intermediate.parentserver.url config -# option (-u command line option) -# -# 2) --cafiles -# For each CA config file in the list, generate a separate signing CA. Each CA -# config file in this list MAY contain all of the same elements as are found in -# the server config file except port, debug, and tls sections. -# -# Examples: -# fabric-ca-server start -b admin:adminpw --cacount 2 -# -# fabric-ca-server start -b admin:adminpw --cafiles ca/ca1/fabric-ca-server-config.yaml -# --cafiles ca/ca2/fabric-ca-server-config.yaml -# -############################################################################# - -cacount: - -cafiles: - -############################################################################# -# Intermediate CA section -# -# The relationship between servers and CAs is as follows: -# 1) A single server process may contain or function as one or more CAs. -# This is configured by the "Multi CA section" above. -# 2) Each CA is either a root CA or an intermediate CA. -# 3) Each intermediate CA has a parent CA which is either a root CA or another intermediate CA. -# -# This section pertains to configuration of #2 and #3. -# If the "intermediate.parentserver.url" property is set, -# then this is an intermediate CA with the specified parent -# CA. -# -# parentserver section -# url - The URL of the parent server -# caname - Name of the CA to enroll within the server -# -# enrollment section used to enroll intermediate CA with parent CA -# profile - Name of the signing profile to use in issuing the certificate -# label - Label to use in HSM operations -# -# tls section for secure socket connection -# certfiles - PEM-encoded list of trusted root certificate files -# client: -# certfile - PEM-encoded certificate file for when client authentication -# is enabled on server -# keyfile - PEM-encoded key file for when client authentication -# is enabled on server -############################################################################# -intermediate: - parentserver: - url: - caname: - - enrollment: - hosts: - profile: - label: - - tls: - certfiles: - client: - certfile: - keyfile: - -############################################################################# -# CA configuration section -# -# Configure the number of incorrect password attempts are allowed for -# identities. By default, the value of 'passwordattempts' is 10, which -# means that 10 incorrect password attempts can be made before an identity get -# locked out. -############################################################################# -cfg: - identities: - passwordattempts: 10 - -############################################################################### -# -# Operations section -# -############################################################################### -operations: - # host and port for the operations server - listenAddress: 127.0.0.1:9443 - - # TLS configuration for the operations endpoint - tls: - # TLS enabled - enabled: false - - # path to PEM encoded server certificate for the operations server - cert: - file: - - # path to PEM encoded server key for the operations server - key: - file: - - # require client certificate authentication to access all resources - clientAuthRequired: false - - # paths to PEM encoded ca certificates to trust for client authentication - clientRootCAs: - files: [] - -############################################################################### -# -# Metrics section -# -############################################################################### -metrics: - # statsd, prometheus, or disabled - provider: disabled - - # statsd configuration - statsd: - # network type: tcp or udp - network: udp - - # statsd server address - address: 127.0.0.1:8125 - - # the interval at which locally cached counters and gauges are pushed - # to statsd; timings are pushed immediately - writeInterval: 10s - - # prefix is prepended to all emitted statsd metrics - prefix: server -" -`; - -exports[`samples/fablo-config-hlf2-2orgs-2chaincodes-private-data.yaml should create proper e2e/__tmp__/samples/fablo-config-hlf2-2orgs-2chaincodes-private-data.yaml.tmpdir/fablo-target/fabric-config/fabric-ca-server-config/orderer2.com/fabric-ca-server-config.yaml from samples/fablo-config-hlf2-2orgs-2chaincodes-private-data.yaml 1`] = ` -"############################################################################# -# This is a configuration file for the fabric-ca-server command. -# -# COMMAND LINE ARGUMENTS AND ENVIRONMENT VARIABLES -# ------------------------------------------------ -# Each configuration element can be overridden via command line -# arguments or environment variables. The precedence for determining -# the value of each element is as follows: -# 1) command line argument -# Examples: -# a) --port 443 -# To set the listening port -# b) --ca.keyfile ../mykey.pem -# To set the "keyfile" element in the "ca" section below; -# note the '.' separator character. -# 2) environment variable -# Examples: -# a) FABRIC_CA_SERVER_PORT=443 -# To set the listening port -# b) FABRIC_CA_SERVER_CA_KEYFILE="../mykey.pem" -# To set the "keyfile" element in the "ca" section below; -# note the '_' separator character. -# 3) configuration file -# 4) default value (if there is one) -# All default values are shown beside each element below. -# -# FILE NAME ELEMENTS -# ------------------ -# The value of all fields whose name ends with "file" or "files" are -# name or names of other files. -# For example, see "tls.certfile" and "tls.clientauth.certfiles". -# The value of each of these fields can be a simple filename, a -# relative path, or an absolute path. If the value is not an -# absolute path, it is interpreted as being relative to the location -# of this configuration file. -# -############################################################################# - -# Version of config file -version: 1.5.5 - -# Server's listening port (default: 7054) -port: 7054 - -# Cross-Origin Resource Sharing (CORS) -cors: - enabled: false - origins: - - "*" - -# Enables debug logging (default: false) -debug: false - -# Size limit of an acceptable CRL in bytes (default: 512000) -crlsizelimit: 512000 - -############################################################################# -# TLS section for the server's listening port -# -# The following types are supported for client authentication: NoClientCert, -# RequestClientCert, RequireAnyClientCert, VerifyClientCertIfGiven, -# and RequireAndVerifyClientCert. -# -# Certfiles is a list of root certificate authorities that the server uses -# when verifying client certificates. -############################################################################# -tls: - # Enable TLS (default: false) - enabled: false - # TLS for the server's listening port - certfile: - keyfile: - clientauth: - type: noclientcert - certfiles: - -############################################################################# -# The CA section contains information related to the Certificate Authority -# including the name of the CA, which should be unique for all members -# of a blockchain network. It also includes the key and certificate files -# used when issuing enrollment certificates (ECerts). -# The chainfile (if it exists) contains the certificate chain which -# should be trusted for this CA, where the 1st in the chain is always the -# root CA certificate. -############################################################################# -ca: - # Name of this CA - name: - # Key file (is only used to import a private key into BCCSP) - keyfile: - # Certificate file (default: ca-cert.pem) - certfile: - # Chain file - chainfile: - -############################################################################# -# The gencrl REST endpoint is used to generate a CRL that contains revoked -# certificates. This section contains configuration options that are used -# during gencrl request processing. -############################################################################# -crl: - # Specifies expiration for the generated CRL. The number of hours - # specified by this property is added to the UTC time, the resulting time - # is used to set the 'Next Update' date of the CRL. - expiry: 24h - -############################################################################# -# The registry section controls how the fabric-ca-server does two things: -# 1) authenticates enrollment requests which contain a username and password -# (also known as an enrollment ID and secret). -# 2) once authenticated, retrieves the identity's attribute names and values. -# These attributes are useful for making access control decisions in -# chaincode. -# There are two main configuration options: -# 1) The fabric-ca-server is the registry. -# This is true if "ldap.enabled" in the ldap section below is false. -# 2) An LDAP server is the registry, in which case the fabric-ca-server -# calls the LDAP server to perform these tasks. -# This is true if "ldap.enabled" in the ldap section below is true, -# which means this "registry" section is ignored. -############################################################################# -registry: - # Maximum number of times a password/secret can be reused for enrollment - # (default: -1, which means there is no limit) - maxenrollments: -1 - - # Contains identity information which is used when LDAP is disabled - identities: - - name: admin - pass: adminpw - type: client - affiliation: "" - attrs: - hf.Registrar.Roles: "*" - hf.Registrar.DelegateRoles: "*" - hf.Revoker: true - hf.IntermediateCA: true - hf.GenCRL: true - hf.Registrar.Attributes: "*" - hf.AffiliationMgr: true - -############################################################################# -# Database section -# Supported types are: "sqlite3", "postgres", and "mysql". -# The datasource value depends on the type. -# If the type is "sqlite3", the datasource value is a file name to use -# as the database store. Since "sqlite3" is an embedded database, it -# may not be used if you want to run the fabric-ca-server in a cluster. -# To run the fabric-ca-server in a cluster, you must choose "postgres" -# or "mysql". -############################################################################# -db: - type: sqlite3 - datasource: fabric-ca-server.db - tls: - enabled: false - certfiles: - client: - certfile: - keyfile: - -############################################################################# -# LDAP section -# If LDAP is enabled, the fabric-ca-server calls LDAP to: -# 1) authenticate enrollment ID and secret (i.e. username and password) -# for enrollment requests; -# 2) To retrieve identity attributes -############################################################################# -ldap: - # Enables or disables the LDAP client (default: false) - # If this is set to true, the "registry" section is ignored. - enabled: false - # The URL of the LDAP server - url: ldap://:@:/ - # TLS configuration for the client connection to the LDAP server - tls: - certfiles: - client: - certfile: - keyfile: - # Attribute related configuration for mapping from LDAP entries to Fabric CA attributes - attribute: - # 'names' is an array of strings containing the LDAP attribute names which are - # requested from the LDAP server for an LDAP identity's entry - names: ['uid', 'member'] - # The 'converters' section is used to convert an LDAP entry to the value of - # a fabric CA attribute. - # For example, the following converts an LDAP 'uid' attribute - # whose value begins with 'revoker' to a fabric CA attribute - # named "hf.Revoker" with a value of "true" (because the boolean expression - # evaluates to true). - # converters: - # - name: hf.Revoker - # value: attr("uid") =~ "revoker*" - converters: - - name: - value: - # The 'maps' section contains named maps which may be referenced by the 'map' - # function in the 'converters' section to map LDAP responses to arbitrary values. - # For example, assume a user has an LDAP attribute named 'member' which has multiple - # values which are each a distinguished name (i.e. a DN). For simplicity, assume the - # values of the 'member' attribute are 'dn1', 'dn2', and 'dn3'. - # Further assume the following configuration. - # converters: - # - name: hf.Registrar.Roles - # value: map(attr("member"),"groups") - # maps: - # groups: - # - name: dn1 - # value: peer - # - name: dn2 - # value: client - # The value of the user's 'hf.Registrar.Roles' attribute is then computed to be - # "peer,client,dn3". This is because the value of 'attr("member")' is - # "dn1,dn2,dn3", and the call to 'map' with a 2nd argument of - # "group" replaces "dn1" with "peer" and "dn2" with "client". - maps: - groups: - - name: - value: - -############################################################################# -# Affiliations section. Fabric CA server can be bootstrapped with the -# affiliations specified in this section. Affiliations are specified as maps. -# For example: -# businessunit1: -# department1: -# - team1 -# businessunit2: -# - department2 -# - department3 -# -# Affiliations are hierarchical in nature. In the above example, -# department1 (used as businessunit1.department1) is the child of businessunit1. -# team1 (used as businessunit1.department1.team1) is the child of department1. -# department2 (used as businessunit2.department2) and department3 (businessunit2.department3) -# are children of businessunit2. -# Note: Affiliations are case sensitive except for the non-leaf affiliations -# (like businessunit1, department1, businessunit2) that are specified in the configuration file, -# which are always stored in lower case. -############################################################################# -affiliations: - orderer2: - -############################################################################# -# Signing section -# -# The "default" subsection is used to sign enrollment certificates; -# the default expiration ("expiry" field) is "8760h", which is 1 year in hours. -# -# The "ca" profile subsection is used to sign intermediate CA certificates; -# the default expiration ("expiry" field) is "43800h" which is 5 years in hours. -# Note that "isca" is true, meaning that it issues a CA certificate. -# A maxpathlen of 0 means that the intermediate CA cannot issue other -# intermediate CA certificates, though it can still issue end entity certificates. -# (See RFC 5280, section 4.2.1.9) -# -# The "tls" profile subsection is used to sign TLS certificate requests; -# the default expiration ("expiry" field) is "8760h", which is 1 year in hours. -############################################################################# -signing: - default: - usage: - - digital signature - expiry: 8760h - profiles: - ca: - usage: - - cert sign - - crl sign - expiry: 43800h - caconstraint: - isca: true - maxpathlen: 0 - tls: - usage: - - signing - - key encipherment - - server auth - - client auth - - key agreement - expiry: 8760h - -########################################################################### -# Certificate Signing Request (CSR) section. -# This controls the creation of the root CA certificate. -# The expiration for the root CA certificate is configured with the -# "ca.expiry" field below, whose default value is "131400h" which is -# 15 years in hours. -# The pathlength field is used to limit CA certificate hierarchy as described -# in section 4.2.1.9 of RFC 5280. -# Examples: -# 1) No pathlength value means no limit is requested. -# 2) pathlength == 1 means a limit of 1 is requested which is the default for -# a root CA. This means the root CA can issue intermediate CA certificates, -# but these intermediate CAs may not in turn issue other CA certificates -# though they can still issue end entity certificates. -# 3) pathlength == 0 means a limit of 0 is requested; -# this is the default for an intermediate CA, which means it can not issue -# CA certificates though it can still issue end entity certificates. -########################################################################### -csr: - cn: fabric-ca-server - keyrequest: - algo: ecdsa - size: 256 - names: - - C: US - ST: "North Carolina" - L: - O: Hyperledger - OU: Fabric - hosts: - - 483cccf16a98 - - localhost - ca: - expiry: 131400h - pathlength: 1 - -########################################################################### -# Each CA can issue both X509 enrollment certificate as well as Idemix -# Credential. This section specifies configuration for the issuer component -# that is responsible for issuing Idemix credentials. -########################################################################### -idemix: - # Specifies pool size for revocation handles. A revocation handle is an unique identifier of an - # Idemix credential. The issuer will create a pool revocation handles of this specified size. When - # a credential is requested, issuer will get handle from the pool and assign it to the credential. - # Issuer will repopulate the pool with new handles when the last handle in the pool is used. - # A revocation handle and credential revocation information (CRI) are used to create non revocation proof - # by the prover to prove to the verifier that her credential is not revoked. - rhpoolsize: 1000 - - # The Idemix credential issuance is a two step process. First step is to get a nonce from the issuer - # and second step is send credential request that is constructed using the nonce to the isuser to - # request a credential. This configuration property specifies expiration for the nonces. By default is - # nonces expire after 15 seconds. The value is expressed in the time.Duration format (see https://golang.org/pkg/time/#ParseDuration). - nonceexpiration: 15s - - # Specifies interval at which expired nonces are removed from datastore. Default value is 15 minutes. - # The value is expressed in the time.Duration format (see https://golang.org/pkg/time/#ParseDuration) - noncesweepinterval: 15m - -############################################################################# -# BCCSP (BlockChain Crypto Service Provider) section is used to select which -# crypto library implementation to use -############################################################################# -bccsp: - default: SW - sw: - hash: SHA2 - security: 256 - filekeystore: - # The directory used for the software file-based keystore - keystore: msp/keystore - -############################################################################# -# Multi CA section -# -# Each Fabric CA server contains one CA by default. This section is used -# to configure multiple CAs in a single server. -# -# 1) --cacount -# Automatically generate non-default CAs. The names of these -# additional CAs are "ca1", "ca2", ... "caN", where "N" is -# This is particularly useful in a development environment to quickly set up -# multiple CAs. Note that, this config option is not applicable to intermediate CA server -# i.e., Fabric CA server that is started with intermediate.parentserver.url config -# option (-u command line option) -# -# 2) --cafiles -# For each CA config file in the list, generate a separate signing CA. Each CA -# config file in this list MAY contain all of the same elements as are found in -# the server config file except port, debug, and tls sections. -# -# Examples: -# fabric-ca-server start -b admin:adminpw --cacount 2 -# -# fabric-ca-server start -b admin:adminpw --cafiles ca/ca1/fabric-ca-server-config.yaml -# --cafiles ca/ca2/fabric-ca-server-config.yaml -# -############################################################################# - -cacount: - -cafiles: - -############################################################################# -# Intermediate CA section -# -# The relationship between servers and CAs is as follows: -# 1) A single server process may contain or function as one or more CAs. -# This is configured by the "Multi CA section" above. -# 2) Each CA is either a root CA or an intermediate CA. -# 3) Each intermediate CA has a parent CA which is either a root CA or another intermediate CA. -# -# This section pertains to configuration of #2 and #3. -# If the "intermediate.parentserver.url" property is set, -# then this is an intermediate CA with the specified parent -# CA. -# -# parentserver section -# url - The URL of the parent server -# caname - Name of the CA to enroll within the server -# -# enrollment section used to enroll intermediate CA with parent CA -# profile - Name of the signing profile to use in issuing the certificate -# label - Label to use in HSM operations -# -# tls section for secure socket connection -# certfiles - PEM-encoded list of trusted root certificate files -# client: -# certfile - PEM-encoded certificate file for when client authentication -# is enabled on server -# keyfile - PEM-encoded key file for when client authentication -# is enabled on server -############################################################################# -intermediate: - parentserver: - url: - caname: - - enrollment: - hosts: - profile: - label: - - tls: - certfiles: - client: - certfile: - keyfile: - -############################################################################# -# CA configuration section -# -# Configure the number of incorrect password attempts are allowed for -# identities. By default, the value of 'passwordattempts' is 10, which -# means that 10 incorrect password attempts can be made before an identity get -# locked out. -############################################################################# -cfg: - identities: - passwordattempts: 10 - -############################################################################### -# -# Operations section -# -############################################################################### -operations: - # host and port for the operations server - listenAddress: 127.0.0.1:9443 - - # TLS configuration for the operations endpoint - tls: - # TLS enabled - enabled: false - - # path to PEM encoded server certificate for the operations server - cert: - file: - - # path to PEM encoded server key for the operations server - key: - file: - - # require client certificate authentication to access all resources - clientAuthRequired: false - - # paths to PEM encoded ca certificates to trust for client authentication - clientRootCAs: - files: [] - -############################################################################### -# -# Metrics section -# -############################################################################### -metrics: - # statsd, prometheus, or disabled - provider: disabled - - # statsd configuration - statsd: - # network type: tcp or udp - network: udp - - # statsd server address - address: 127.0.0.1:8125 - - # the interval at which locally cached counters and gauges are pushed - # to statsd; timings are pushed immediately - writeInterval: 10s - - # prefix is prepended to all emitted statsd metrics - prefix: server -" -`; - exports[`samples/fablo-config-hlf2-2orgs-2chaincodes-private-data.yaml should create proper e2e/__tmp__/samples/fablo-config-hlf2-2orgs-2chaincodes-private-data.yaml.tmpdir/fablo-target/fabric-config/fabric-ca-server-config/org1.example.com/fabric-ca-server-config.yaml from samples/fablo-config-hlf2-2orgs-2chaincodes-private-data.yaml 1`] = ` "############################################################################# # This is a configuration file for the fabric-ca-server command. diff --git a/e2e/__snapshots__/fabloCommands.test.ts.snap b/e2e/__snapshots__/fabloCommands.test.ts.snap index d6f843437..2e97c2fce 100644 --- a/e2e/__snapshots__/fabloCommands.test.ts.snap +++ b/e2e/__snapshots__/fabloCommands.test.ts.snap @@ -4,6 +4,7 @@ exports[`extend config should extend custom config 1`] = ` "Validation errors count: 0 Validation warnings count: 0 =========================================================== +Could not check for updates. Url: 'https://api.github.com/repos/hyperledger-labs/fablo/releases' not available { "global": { "fabricVersion": "2.4.3", @@ -2471,6 +2472,7 @@ exports[`extend config should extend default config 1`] = ` "Validation errors count: 0 Validation warnings count: 0 =========================================================== +Could not check for updates. Url: 'https://api.github.com/repos/hyperledger-labs/fablo/releases' not available { "global": { "fabricVersion": "2.5.12", @@ -3094,16 +3096,7 @@ exports[`init should init simple fablo config with node chaincode 1`] = ` ] } ], - "chaincodes": [ - { - "name": "chaincode1", - "version": "0.0.1", - "lang": "node", - "channel": "my-channel1", - "directory": "./chaincodes/chaincode-kv-node", - "privateData": [] - } - ], + "chaincodes": [], "hooks": {} }" `; diff --git a/e2e/fabloCommands.test.ts b/e2e/fabloCommands.test.ts index 48d4fa2b9..99d01716c 100644 --- a/e2e/fabloCommands.test.ts +++ b/e2e/fabloCommands.test.ts @@ -150,20 +150,19 @@ describe("validate", () => { // Then expect(commandResult.output).toContain("Chaincode name 'duplicateChaincode' is not unique"); - }); it("should validate when all chaincode names are unique across channels", () => { - // Given - const fabloConfig = `${commands.relativeRoot}/samples/fablo-config-hlf2-2orgs-2chaincodes-raft.yaml`; + // Given + const fabloConfig = `${commands.relativeRoot}/samples/fablo-config-hlf2-2orgs-2chaincodes-raft.yaml`; - // When - const commandResult = commands.fabloExec(`validate ${fabloConfig}`); + // When + const commandResult = commands.fabloExec(`validate ${fabloConfig}`); - // Then - expect(commandResult.output).toContain("Validation errors count: 0"); - expect(commandResult.output).not.toContain("is not unique"); -}); + // Then + expect(commandResult.output).toContain("Validation errors count: 0"); + expect(commandResult.output).not.toContain("is not unique"); + }); }); describe("extend config", () => { diff --git a/samples/fablo-config-hlf2-2orgs-2chaincodes-private-data-duplicate.yaml b/samples/fablo-config-hlf2-2orgs-2chaincodes-private-data-duplicate.yaml index da25c1f21..96d17faf3 100644 --- a/samples/fablo-config-hlf2-2orgs-2chaincodes-private-data-duplicate.yaml +++ b/samples/fablo-config-hlf2-2orgs-2chaincodes-private-data-duplicate.yaml @@ -8,52 +8,46 @@ orgs: - organization: name: Orderer domain: orderer.example.com - orderer: - type: raft - instances: 1 + orderers: + - groupName: group1 + prefix: orderer + type: solo + instances: 1 - organization: name: Org1 domain: org1.example.com peer: - instances: 1 - ca: - prefix: ca + instances: 2 - organization: name: Org2 domain: org2.example.com peer: instances: 1 - ca: - prefix: ca channels: - - name: channel1 + - name: my-channel1 orgs: - name: Org1 peers: [peer0] - name: Org2 peers: [peer0] - - name: Orderer - peers: [] - - name: channel2 + - name: my-channel2 orgs: - name: Org1 peers: [peer0] - name: Org2 peers: [peer0] - - name: Orderer - peers: [] chaincodes: - name: duplicateChaincode version: "1.0" lang: node - channel: channel1 + channel: my-channel1 directory: "./chaincodes/chaincode-kv-node" endorsement: "OR('Org1MSP.member', 'Org2MSP.member')" - name: duplicateChaincode version: "1.0" lang: node - channel: channel2 + channel: my-channel2 directory: "./chaincodes/chaincode-kv-node" endorsement: "OR('Org1MSP.member', 'Org2MSP.member')" \ No newline at end of file diff --git a/src/extend-config/extendChaincodesConfig.ts b/src/extend-config/extendChaincodesConfig.ts index 1ceffb2ea..108277052 100644 --- a/src/extend-config/extendChaincodesConfig.ts +++ b/src/extend-config/extendChaincodesConfig.ts @@ -37,9 +37,18 @@ const createPrivateCollectionConfig = ( }; }; -const checkUniqueChaincodeNames = (chaincodes: ChaincodeJson[]): void => { +const checkUniqueChaincodeNames = (allChannelsConfig: any): void => { const chaincodeNames = new Set(); - chaincodes.forEach((chaincode) => { + + const allChaincodes: ChaincodeJson[] = []; + + Object.values(allChannelsConfig.channels || {}).forEach((channel: any) => { + if (channel.chaincodes) { + allChaincodes.push(...channel.chaincodes); + } + }); + + allChaincodes.forEach((chaincode) => { if (chaincodeNames.has(chaincode.name)) { throw new Error(`Chaincode name '${chaincode.name}' is not unique across channels.`); } From d09c491cd11ad03fd612ff1135ea43cecf27a237 Mon Sep 17 00:00:00 2001 From: Osama Rabea Date: Fri, 15 Aug 2025 09:08:25 +0300 Subject: [PATCH 04/10] update snapshot Signed-off-by: Osama Rabea update snapshot Signed-off-by: Osama Rabea --- e2e/__snapshots__/fabloCommands.test.ts.snap | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/e2e/__snapshots__/fabloCommands.test.ts.snap b/e2e/__snapshots__/fabloCommands.test.ts.snap index 2e97c2fce..d6f843437 100644 --- a/e2e/__snapshots__/fabloCommands.test.ts.snap +++ b/e2e/__snapshots__/fabloCommands.test.ts.snap @@ -4,7 +4,6 @@ exports[`extend config should extend custom config 1`] = ` "Validation errors count: 0 Validation warnings count: 0 =========================================================== -Could not check for updates. Url: 'https://api.github.com/repos/hyperledger-labs/fablo/releases' not available { "global": { "fabricVersion": "2.4.3", @@ -2472,7 +2471,6 @@ exports[`extend config should extend default config 1`] = ` "Validation errors count: 0 Validation warnings count: 0 =========================================================== -Could not check for updates. Url: 'https://api.github.com/repos/hyperledger-labs/fablo/releases' not available { "global": { "fabricVersion": "2.5.12", @@ -3096,7 +3094,16 @@ exports[`init should init simple fablo config with node chaincode 1`] = ` ] } ], - "chaincodes": [], + "chaincodes": [ + { + "name": "chaincode1", + "version": "0.0.1", + "lang": "node", + "channel": "my-channel1", + "directory": "./chaincodes/chaincode-kv-node", + "privateData": [] + } + ], "hooks": {} }" `; From acaa0c26c54f40fa596ed7bdcdfc41cd27fb2f09 Mon Sep 17 00:00:00 2001 From: Osama Rabea Date: Fri, 15 Aug 2025 23:40:58 +0300 Subject: [PATCH 05/10] update and fix error lint error Signed-off-by: Osama Rabea --- e2e/__snapshots__/extendConfig.test.ts.snap | 14 +++++++------- ...s-private-data-duplicate.yaml.test.ts.snap | 14 ++++++++++++++ e2e/__snapshots__/fabloCommands.test.ts.snap | 19 +++---------------- ...ncodes-private-data-duplicate.yaml.test.ts | 7 +++++++ e2e/fabloCommands.test.ts | 1 + ...gs-2chaincodes-private-data-duplicate.yaml | 2 +- 6 files changed, 33 insertions(+), 24 deletions(-) create mode 100644 e2e/__snapshots__/fablo-config-hlf2-2orgs-2chaincodes-private-data-duplicate.yaml.test.ts.snap create mode 100644 e2e/fablo-config-hlf2-2orgs-2chaincodes-private-data-duplicate.yaml.test.ts diff --git a/e2e/__snapshots__/extendConfig.test.ts.snap b/e2e/__snapshots__/extendConfig.test.ts.snap index bfeb4c772..7d4e7cf05 100644 --- a/e2e/__snapshots__/extendConfig.test.ts.snap +++ b/e2e/__snapshots__/extendConfig.test.ts.snap @@ -5172,21 +5172,21 @@ exports[`extend config samples/fablo-config-hlf2-2orgs-2chaincodes-private-data- ], "global": { "capabilities": { - "application": "V2_0", + "application": "V2_5", "channel": "V2_0", "isV2": true, "isV3": false, "orderer": "V2_0", }, "engine": "docker", - "fabricBaseosVersion": "2.4.7", + "fabricBaseosVersion": "2.5.12", "fabricCaVersion": "1.5.5", - "fabricCcenvVersion": "2.4.7", - "fabricJavaenvVersion": "2.4", - "fabricNodeenvVersion": "2.4", + "fabricCcenvVersion": "2.5.12", + "fabricJavaenvVersion": "2.5", + "fabricNodeenvVersion": "2.5", "fabricRecommendedNodeVersion": "16", - "fabricToolsVersion": "2.4.7", - "fabricVersion": "2.4.7", + "fabricToolsVersion": "2.5.12", + "fabricVersion": "2.5.12", "monitoring": { "loglevel": "info", }, diff --git a/e2e/__snapshots__/fablo-config-hlf2-2orgs-2chaincodes-private-data-duplicate.yaml.test.ts.snap b/e2e/__snapshots__/fablo-config-hlf2-2orgs-2chaincodes-private-data-duplicate.yaml.test.ts.snap new file mode 100644 index 000000000..1cb5ca397 --- /dev/null +++ b/e2e/__snapshots__/fablo-config-hlf2-2orgs-2chaincodes-private-data-duplicate.yaml.test.ts.snap @@ -0,0 +1,14 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`samples/fablo-config-hlf2-2orgs-2chaincodes-private-data-duplicate.yaml should create proper e2e/__tmp__/samples/fablo-config-hlf2-2orgs-2chaincodes-private-data-duplicate.yaml.tmpdir/fablo-target/.config/configstore/update-notifier-yo.json from samples/fablo-config-hlf2-2orgs-2chaincodes-private-data-duplicate.yaml 1`] = ` +"{ + "optOut": false, + "lastUpdateCheck": 1755290146858 +}" +`; + +exports[`samples/fablo-config-hlf2-2orgs-2chaincodes-private-data-duplicate.yaml should create proper files from samples/fablo-config-hlf2-2orgs-2chaincodes-private-data-duplicate.yaml 1`] = ` +[ + "e2e/__tmp__/samples/fablo-config-hlf2-2orgs-2chaincodes-private-data-duplicate.yaml.tmpdir/fablo-target/.config/configstore/update-notifier-yo.json", +] +`; diff --git a/e2e/__snapshots__/fabloCommands.test.ts.snap b/e2e/__snapshots__/fabloCommands.test.ts.snap index d6f843437..e0fd6ef3d 100644 --- a/e2e/__snapshots__/fabloCommands.test.ts.snap +++ b/e2e/__snapshots__/fabloCommands.test.ts.snap @@ -3136,9 +3136,7 @@ exports[`init should init simple fablo config with node chaincode and rest api 1 "prefix": "orderer" } ], - "tools": { - "fabloRest": true - } + "tools": {} }, { "organization": { @@ -3156,9 +3154,7 @@ exports[`init should init simple fablo config with node chaincode and rest api 1 "db": "LevelDb", "prefix": "peer" }, - "tools": { - "fabloRest": true - } + "tools": {} } ], "channels": [ @@ -3175,16 +3171,7 @@ exports[`init should init simple fablo config with node chaincode and rest api 1 ] } ], - "chaincodes": [ - { - "name": "chaincode1", - "version": "0.0.1", - "lang": "node", - "channel": "my-channel1", - "directory": "./chaincodes/chaincode-kv-node", - "privateData": [] - } - ], + "chaincodes": [], "hooks": {} }" `; diff --git a/e2e/fablo-config-hlf2-2orgs-2chaincodes-private-data-duplicate.yaml.test.ts b/e2e/fablo-config-hlf2-2orgs-2chaincodes-private-data-duplicate.yaml.test.ts new file mode 100644 index 000000000..e6fc24997 --- /dev/null +++ b/e2e/fablo-config-hlf2-2orgs-2chaincodes-private-data-duplicate.yaml.test.ts @@ -0,0 +1,7 @@ +import performTests from "./performTests"; + +const config = "samples/fablo-config-hlf2-2orgs-2chaincodes-private-data-duplicate.yaml"; + +describe(config, () => { + performTests(config); +}); diff --git a/e2e/fabloCommands.test.ts b/e2e/fabloCommands.test.ts index 99d01716c..c0effdfa7 100644 --- a/e2e/fabloCommands.test.ts +++ b/e2e/fabloCommands.test.ts @@ -149,6 +149,7 @@ describe("validate", () => { const commandResult = commands.fabloExec(`validate ${fabloConfig}`); // Then + // expect(commandResult).toEqual(TestCommands.success()); expect(commandResult.output).toContain("Chaincode name 'duplicateChaincode' is not unique"); }); diff --git a/samples/fablo-config-hlf2-2orgs-2chaincodes-private-data-duplicate.yaml b/samples/fablo-config-hlf2-2orgs-2chaincodes-private-data-duplicate.yaml index 96d17faf3..17bb87ce7 100644 --- a/samples/fablo-config-hlf2-2orgs-2chaincodes-private-data-duplicate.yaml +++ b/samples/fablo-config-hlf2-2orgs-2chaincodes-private-data-duplicate.yaml @@ -1,7 +1,7 @@ --- $schema: "https://github.com/hyperledger-labs/fablo/releases/download/2.2.0/schema.json" global: - fabricVersion: "2.4.7" + fabricVersion: "2.5.12" tls: false orgs: From 6cfff67a947115288d5f3f8d2530f25ac38e00c2 Mon Sep 17 00:00:00 2001 From: Osama Rabea Date: Sat, 16 Aug 2025 00:18:58 +0300 Subject: [PATCH 06/10] update Signed-off-by: Osama Rabea --- ...s-private-data-duplicate.yaml.test.ts.snap | 13 +------------ e2e/__snapshots__/fabloCommands.test.ts.snap | 19 ++++++++++++++++--- 2 files changed, 17 insertions(+), 15 deletions(-) diff --git a/e2e/__snapshots__/fablo-config-hlf2-2orgs-2chaincodes-private-data-duplicate.yaml.test.ts.snap b/e2e/__snapshots__/fablo-config-hlf2-2orgs-2chaincodes-private-data-duplicate.yaml.test.ts.snap index 1cb5ca397..b4aeda952 100644 --- a/e2e/__snapshots__/fablo-config-hlf2-2orgs-2chaincodes-private-data-duplicate.yaml.test.ts.snap +++ b/e2e/__snapshots__/fablo-config-hlf2-2orgs-2chaincodes-private-data-duplicate.yaml.test.ts.snap @@ -1,14 +1,3 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP -exports[`samples/fablo-config-hlf2-2orgs-2chaincodes-private-data-duplicate.yaml should create proper e2e/__tmp__/samples/fablo-config-hlf2-2orgs-2chaincodes-private-data-duplicate.yaml.tmpdir/fablo-target/.config/configstore/update-notifier-yo.json from samples/fablo-config-hlf2-2orgs-2chaincodes-private-data-duplicate.yaml 1`] = ` -"{ - "optOut": false, - "lastUpdateCheck": 1755290146858 -}" -`; - -exports[`samples/fablo-config-hlf2-2orgs-2chaincodes-private-data-duplicate.yaml should create proper files from samples/fablo-config-hlf2-2orgs-2chaincodes-private-data-duplicate.yaml 1`] = ` -[ - "e2e/__tmp__/samples/fablo-config-hlf2-2orgs-2chaincodes-private-data-duplicate.yaml.tmpdir/fablo-target/.config/configstore/update-notifier-yo.json", -] -`; +exports[`samples/fablo-config-hlf2-2orgs-2chaincodes-private-data-duplicate.yaml should create proper files from samples/fablo-config-hlf2-2orgs-2chaincodes-private-data-duplicate.yaml 1`] = `[]`; diff --git a/e2e/__snapshots__/fabloCommands.test.ts.snap b/e2e/__snapshots__/fabloCommands.test.ts.snap index e0fd6ef3d..d6f843437 100644 --- a/e2e/__snapshots__/fabloCommands.test.ts.snap +++ b/e2e/__snapshots__/fabloCommands.test.ts.snap @@ -3136,7 +3136,9 @@ exports[`init should init simple fablo config with node chaincode and rest api 1 "prefix": "orderer" } ], - "tools": {} + "tools": { + "fabloRest": true + } }, { "organization": { @@ -3154,7 +3156,9 @@ exports[`init should init simple fablo config with node chaincode and rest api 1 "db": "LevelDb", "prefix": "peer" }, - "tools": {} + "tools": { + "fabloRest": true + } } ], "channels": [ @@ -3171,7 +3175,16 @@ exports[`init should init simple fablo config with node chaincode and rest api 1 ] } ], - "chaincodes": [], + "chaincodes": [ + { + "name": "chaincode1", + "version": "0.0.1", + "lang": "node", + "channel": "my-channel1", + "directory": "./chaincodes/chaincode-kv-node", + "privateData": [] + } + ], "hooks": {} }" `; From 5b7115b3c4d428b56bb63140e0156a74fb7d8f99 Mon Sep 17 00:00:00 2001 From: OsamaRab3 Date: Mon, 25 Aug 2025 09:13:31 +0300 Subject: [PATCH 07/10] remove redundant fablo config and snapshot Signed-off-by: OsamaRab3 --- ...ncodes-private-data-duplicate.yaml.test.ts | 7 --- e2e/fabloCommands.test.ts | 31 ++++------- ...gs-2chaincodes-private-data-duplicate.yaml | 53 ------------------- 3 files changed, 10 insertions(+), 81 deletions(-) delete mode 100644 e2e/fablo-config-hlf2-2orgs-2chaincodes-private-data-duplicate.yaml.test.ts delete mode 100644 samples/fablo-config-hlf2-2orgs-2chaincodes-private-data-duplicate.yaml diff --git a/e2e/fablo-config-hlf2-2orgs-2chaincodes-private-data-duplicate.yaml.test.ts b/e2e/fablo-config-hlf2-2orgs-2chaincodes-private-data-duplicate.yaml.test.ts deleted file mode 100644 index e6fc24997..000000000 --- a/e2e/fablo-config-hlf2-2orgs-2chaincodes-private-data-duplicate.yaml.test.ts +++ /dev/null @@ -1,7 +0,0 @@ -import performTests from "./performTests"; - -const config = "samples/fablo-config-hlf2-2orgs-2chaincodes-private-data-duplicate.yaml"; - -describe(config, () => { - performTests(config); -}); diff --git a/e2e/fabloCommands.test.ts b/e2e/fabloCommands.test.ts index c0effdfa7..0151f0231 100644 --- a/e2e/fabloCommands.test.ts +++ b/e2e/fabloCommands.test.ts @@ -140,30 +140,19 @@ describe("validate", () => { expect(commands.getFiles()).toEqual([]); }); - it("should throw an error for duplicate chaincode names across different channels", () => { - // Given - commands.fabloExec("init"); - const fabloConfig = `${commands.relativeRoot}/samples/fablo-config-hlf2-2orgs-2chaincodes-private-data-duplicate.yaml`; + // it("should throw an error for duplicate chaincode names across different channels", () => { + // // Given + // commands.fabloExec("init"); + // const fabloConfig = `${commands.relativeRoot}/samples/fablo-config-hlf2-2orgs-2chaincodes-private-data-duplicate.yaml`; - // When - const commandResult = commands.fabloExec(`validate ${fabloConfig}`); + // // When + // const commandResult = commands.fabloExec(`validate ${fabloConfig}`); - // Then - // expect(commandResult).toEqual(TestCommands.success()); - expect(commandResult.output).toContain("Chaincode name 'duplicateChaincode' is not unique"); - }); + // // Then + // // expect(commandResult).toEqual(TestCommands.success()); + // expect(commandResult.output).toContain("Chaincode name 'duplicateChaincode' is not unique"); + // }); - it("should validate when all chaincode names are unique across channels", () => { - // Given - const fabloConfig = `${commands.relativeRoot}/samples/fablo-config-hlf2-2orgs-2chaincodes-raft.yaml`; - - // When - const commandResult = commands.fabloExec(`validate ${fabloConfig}`); - - // Then - expect(commandResult.output).toContain("Validation errors count: 0"); - expect(commandResult.output).not.toContain("is not unique"); - }); }); describe("extend config", () => { diff --git a/samples/fablo-config-hlf2-2orgs-2chaincodes-private-data-duplicate.yaml b/samples/fablo-config-hlf2-2orgs-2chaincodes-private-data-duplicate.yaml deleted file mode 100644 index 17bb87ce7..000000000 --- a/samples/fablo-config-hlf2-2orgs-2chaincodes-private-data-duplicate.yaml +++ /dev/null @@ -1,53 +0,0 @@ ---- -$schema: "https://github.com/hyperledger-labs/fablo/releases/download/2.2.0/schema.json" -global: - fabricVersion: "2.5.12" - tls: false - -orgs: - - organization: - name: Orderer - domain: orderer.example.com - orderers: - - groupName: group1 - prefix: orderer - type: solo - instances: 1 - - organization: - name: Org1 - domain: org1.example.com - peer: - instances: 2 - - organization: - name: Org2 - domain: org2.example.com - peer: - instances: 1 - -channels: - - name: my-channel1 - orgs: - - name: Org1 - peers: [peer0] - - name: Org2 - peers: [peer0] - - name: my-channel2 - orgs: - - name: Org1 - peers: [peer0] - - name: Org2 - peers: [peer0] - -chaincodes: - - name: duplicateChaincode - version: "1.0" - lang: node - channel: my-channel1 - directory: "./chaincodes/chaincode-kv-node" - endorsement: "OR('Org1MSP.member', 'Org2MSP.member')" - - name: duplicateChaincode - version: "1.0" - lang: node - channel: my-channel2 - directory: "./chaincodes/chaincode-kv-node" - endorsement: "OR('Org1MSP.member', 'Org2MSP.member')" \ No newline at end of file From 690f30add868238ac17b3061a31e826e01b345da Mon Sep 17 00:00:00 2001 From: OsamaRab3 Date: Fri, 29 Aug 2025 11:15:22 +0300 Subject: [PATCH 08/10] test(e2e): update config on the fly to validate duplicate chaincode names across channels Signed-off-by: OsamaRab3 --- e2e/__snapshots__/extendConfig.test.ts.snap | 1594 ----------------- ...s-private-data-duplicate.yaml.test.ts.snap | 3 - e2e/fabloCommands.test.ts | 41 +- src/extend-config/extendChaincodesConfig.ts | 2 +- 4 files changed, 29 insertions(+), 1611 deletions(-) delete mode 100644 e2e/__snapshots__/fablo-config-hlf2-2orgs-2chaincodes-private-data-duplicate.yaml.test.ts.snap diff --git a/e2e/__snapshots__/extendConfig.test.ts.snap b/e2e/__snapshots__/extendConfig.test.ts.snap index 3a0ec60c0..e651bf26d 100644 --- a/e2e/__snapshots__/extendConfig.test.ts.snap +++ b/e2e/__snapshots__/extendConfig.test.ts.snap @@ -4702,1600 +4702,6 @@ exports[`extend config samples/fablo-config-hlf2-2orgs-2chaincodes-private-data. } `; -exports[`extend config samples/fablo-config-hlf2-2orgs-2chaincodes-private-data-duplicate.yaml 1`] = ` -{ - "chaincodes": [ - { - "channel": { - "instantiatingOrg": { - "anchorPeers": [ - { - "address": "peer0.org1.example.com", - "couchDbExposePort": 5100, - "db": { - "type": "LevelDb", - }, - "fullAddress": "peer0.org1.example.com:7041", - "gatewayEnabled": true, - "isAnchorPeer": true, - "name": "peer0", - "port": 7041, - }, - { - "address": "peer1.org1.example.com", - "couchDbExposePort": 5101, - "db": { - "type": "LevelDb", - }, - "fullAddress": "peer1.org1.example.com:7042", - "gatewayEnabled": true, - "isAnchorPeer": true, - "name": "peer1", - "port": 7042, - }, - ], - "bootstrapPeers": ""peer0.org1.example.com:7041 peer1.org1.example.com:7042"", - "ca": { - "address": "ca.org1.example.com", - "caAdminNameVar": "ORG1_CA_ADMIN_NAME", - "caAdminPassVar": "ORG1_CA_ADMIN_PASSWORD", - "db": "sqlite", - "exposePort": 7040, - "fullAddress": "ca.org1.example.com:7054", - "port": 7054, - "prefix": "ca", - }, - "cli": { - "address": "cli.org1.example.com", - }, - "cryptoConfigFileName": "crypto-config-org1", - "domain": "org1.example.com", - "headPeer": { - "address": "peer0.org1.example.com", - "couchDbExposePort": 5100, - "db": { - "type": "LevelDb", - }, - "fullAddress": "peer0.org1.example.com:7041", - "gatewayEnabled": true, - "isAnchorPeer": true, - "name": "peer0", - "port": 7041, - }, - "mspName": "Org1MSP", - "name": "Org1", - "ordererGroups": [], - "peers": [ - { - "address": "peer0.org1.example.com", - "couchDbExposePort": 5100, - "db": { - "type": "LevelDb", - }, - "fullAddress": "peer0.org1.example.com:7041", - "gatewayEnabled": true, - "isAnchorPeer": true, - "name": "peer0", - "port": 7041, - }, - ], - "peersCount": 2, - "tools": {}, - }, - "name": "my-channel1", - "ordererGroup": { - "configtxOrdererDefaults": "Group1Defaults", - "consensus": "solo", - "genesisBlockName": "Group1Genesis.block", - "hostingOrgs": [ - "Orderer", - ], - "name": "group1", - "ordererHead": { - "address": "orderer0.group1.orderer.example.com", - "adminPort": 7053, - "consensus": "solo", - "domain": "orderer.example.com", - "fullAddress": "orderer0.group1.orderer.example.com:7030", - "name": "orderer0.group1", - "orgMspName": "OrdererMSP", - "orgName": "Orderer", - "port": 7030, - }, - "ordererHeads": [ - { - "address": "orderer0.group1.orderer.example.com", - "adminPort": 7053, - "consensus": "solo", - "domain": "orderer.example.com", - "fullAddress": "orderer0.group1.orderer.example.com:7030", - "name": "orderer0.group1", - "orgMspName": "OrdererMSP", - "orgName": "Orderer", - "port": 7030, - }, - ], - "orderers": [ - { - "address": "orderer0.group1.orderer.example.com", - "adminPort": 7053, - "consensus": "solo", - "domain": "orderer.example.com", - "fullAddress": "orderer0.group1.orderer.example.com:7030", - "name": "orderer0.group1", - "orgMspName": "OrdererMSP", - "orgName": "Orderer", - "port": 7030, - }, - ], - "profileName": "Group1Genesis", - }, - "ordererHead": { - "address": "orderer0.group1.orderer.example.com", - "adminPort": 7053, - "consensus": "solo", - "domain": "orderer.example.com", - "fullAddress": "orderer0.group1.orderer.example.com:7030", - "name": "orderer0.group1", - "orgMspName": "OrdererMSP", - "orgName": "Orderer", - "port": 7030, - }, - "orgs": [ - { - "anchorPeers": [ - { - "address": "peer0.org1.example.com", - "couchDbExposePort": 5100, - "db": { - "type": "LevelDb", - }, - "fullAddress": "peer0.org1.example.com:7041", - "gatewayEnabled": true, - "isAnchorPeer": true, - "name": "peer0", - "port": 7041, - }, - { - "address": "peer1.org1.example.com", - "couchDbExposePort": 5101, - "db": { - "type": "LevelDb", - }, - "fullAddress": "peer1.org1.example.com:7042", - "gatewayEnabled": true, - "isAnchorPeer": true, - "name": "peer1", - "port": 7042, - }, - ], - "bootstrapPeers": ""peer0.org1.example.com:7041 peer1.org1.example.com:7042"", - "ca": { - "address": "ca.org1.example.com", - "caAdminNameVar": "ORG1_CA_ADMIN_NAME", - "caAdminPassVar": "ORG1_CA_ADMIN_PASSWORD", - "db": "sqlite", - "exposePort": 7040, - "fullAddress": "ca.org1.example.com:7054", - "port": 7054, - "prefix": "ca", - }, - "cli": { - "address": "cli.org1.example.com", - }, - "cryptoConfigFileName": "crypto-config-org1", - "domain": "org1.example.com", - "headPeer": { - "address": "peer0.org1.example.com", - "couchDbExposePort": 5100, - "db": { - "type": "LevelDb", - }, - "fullAddress": "peer0.org1.example.com:7041", - "gatewayEnabled": true, - "isAnchorPeer": true, - "name": "peer0", - "port": 7041, - }, - "mspName": "Org1MSP", - "name": "Org1", - "ordererGroups": [], - "peers": [ - { - "address": "peer0.org1.example.com", - "couchDbExposePort": 5100, - "db": { - "type": "LevelDb", - }, - "fullAddress": "peer0.org1.example.com:7041", - "gatewayEnabled": true, - "isAnchorPeer": true, - "name": "peer0", - "port": 7041, - }, - ], - "peersCount": 2, - "tools": {}, - }, - { - "anchorPeers": [ - { - "address": "peer0.org2.example.com", - "couchDbExposePort": 5120, - "db": { - "type": "LevelDb", - }, - "fullAddress": "peer0.org2.example.com:7061", - "gatewayEnabled": true, - "isAnchorPeer": true, - "name": "peer0", - "port": 7061, - }, - ], - "bootstrapPeers": "peer0.org2.example.com:7061", - "ca": { - "address": "ca.org2.example.com", - "caAdminNameVar": "ORG2_CA_ADMIN_NAME", - "caAdminPassVar": "ORG2_CA_ADMIN_PASSWORD", - "db": "sqlite", - "exposePort": 7060, - "fullAddress": "ca.org2.example.com:7054", - "port": 7054, - "prefix": "ca", - }, - "cli": { - "address": "cli.org2.example.com", - }, - "cryptoConfigFileName": "crypto-config-org2", - "domain": "org2.example.com", - "headPeer": { - "address": "peer0.org2.example.com", - "couchDbExposePort": 5120, - "db": { - "type": "LevelDb", - }, - "fullAddress": "peer0.org2.example.com:7061", - "gatewayEnabled": true, - "isAnchorPeer": true, - "name": "peer0", - "port": 7061, - }, - "mspName": "Org2MSP", - "name": "Org2", - "ordererGroups": [], - "peers": [ - { - "address": "peer0.org2.example.com", - "couchDbExposePort": 5120, - "db": { - "type": "LevelDb", - }, - "fullAddress": "peer0.org2.example.com:7061", - "gatewayEnabled": true, - "isAnchorPeer": true, - "name": "peer0", - "port": 7061, - }, - ], - "peersCount": 1, - "tools": {}, - }, - ], - "profileName": "MyChannel1", - }, - "directory": "./chaincodes/chaincode-kv-node", - "endorsement": "OR('Org1MSP.member', 'Org2MSP.member')", - "initRequired": false, - "instantiatingOrg": { - "anchorPeers": [ - { - "address": "peer0.org1.example.com", - "couchDbExposePort": 5100, - "db": { - "type": "LevelDb", - }, - "fullAddress": "peer0.org1.example.com:7041", - "gatewayEnabled": true, - "isAnchorPeer": true, - "name": "peer0", - "port": 7041, - }, - { - "address": "peer1.org1.example.com", - "couchDbExposePort": 5101, - "db": { - "type": "LevelDb", - }, - "fullAddress": "peer1.org1.example.com:7042", - "gatewayEnabled": true, - "isAnchorPeer": true, - "name": "peer1", - "port": 7042, - }, - ], - "bootstrapPeers": ""peer0.org1.example.com:7041 peer1.org1.example.com:7042"", - "ca": { - "address": "ca.org1.example.com", - "caAdminNameVar": "ORG1_CA_ADMIN_NAME", - "caAdminPassVar": "ORG1_CA_ADMIN_PASSWORD", - "db": "sqlite", - "exposePort": 7040, - "fullAddress": "ca.org1.example.com:7054", - "port": 7054, - "prefix": "ca", - }, - "cli": { - "address": "cli.org1.example.com", - }, - "cryptoConfigFileName": "crypto-config-org1", - "domain": "org1.example.com", - "headPeer": { - "address": "peer0.org1.example.com", - "couchDbExposePort": 5100, - "db": { - "type": "LevelDb", - }, - "fullAddress": "peer0.org1.example.com:7041", - "gatewayEnabled": true, - "isAnchorPeer": true, - "name": "peer0", - "port": 7041, - }, - "mspName": "Org1MSP", - "name": "Org1", - "ordererGroups": [], - "peers": [ - { - "address": "peer0.org1.example.com", - "couchDbExposePort": 5100, - "db": { - "type": "LevelDb", - }, - "fullAddress": "peer0.org1.example.com:7041", - "gatewayEnabled": true, - "isAnchorPeer": true, - "name": "peer0", - "port": 7041, - }, - ], - "peersCount": 2, - "tools": {}, - }, - "lang": "node", - "name": "duplicateChaincode", - "privateData": [], - "privateDataConfigFile": undefined, - "version": "1.0", - }, - { - "channel": { - "instantiatingOrg": { - "anchorPeers": [ - { - "address": "peer0.org1.example.com", - "couchDbExposePort": 5100, - "db": { - "type": "LevelDb", - }, - "fullAddress": "peer0.org1.example.com:7041", - "gatewayEnabled": true, - "isAnchorPeer": true, - "name": "peer0", - "port": 7041, - }, - { - "address": "peer1.org1.example.com", - "couchDbExposePort": 5101, - "db": { - "type": "LevelDb", - }, - "fullAddress": "peer1.org1.example.com:7042", - "gatewayEnabled": true, - "isAnchorPeer": true, - "name": "peer1", - "port": 7042, - }, - ], - "bootstrapPeers": ""peer0.org1.example.com:7041 peer1.org1.example.com:7042"", - "ca": { - "address": "ca.org1.example.com", - "caAdminNameVar": "ORG1_CA_ADMIN_NAME", - "caAdminPassVar": "ORG1_CA_ADMIN_PASSWORD", - "db": "sqlite", - "exposePort": 7040, - "fullAddress": "ca.org1.example.com:7054", - "port": 7054, - "prefix": "ca", - }, - "cli": { - "address": "cli.org1.example.com", - }, - "cryptoConfigFileName": "crypto-config-org1", - "domain": "org1.example.com", - "headPeer": { - "address": "peer0.org1.example.com", - "couchDbExposePort": 5100, - "db": { - "type": "LevelDb", - }, - "fullAddress": "peer0.org1.example.com:7041", - "gatewayEnabled": true, - "isAnchorPeer": true, - "name": "peer0", - "port": 7041, - }, - "mspName": "Org1MSP", - "name": "Org1", - "ordererGroups": [], - "peers": [ - { - "address": "peer0.org1.example.com", - "couchDbExposePort": 5100, - "db": { - "type": "LevelDb", - }, - "fullAddress": "peer0.org1.example.com:7041", - "gatewayEnabled": true, - "isAnchorPeer": true, - "name": "peer0", - "port": 7041, - }, - ], - "peersCount": 2, - "tools": {}, - }, - "name": "my-channel2", - "ordererGroup": { - "configtxOrdererDefaults": "Group1Defaults", - "consensus": "solo", - "genesisBlockName": "Group1Genesis.block", - "hostingOrgs": [ - "Orderer", - ], - "name": "group1", - "ordererHead": { - "address": "orderer0.group1.orderer.example.com", - "adminPort": 7053, - "consensus": "solo", - "domain": "orderer.example.com", - "fullAddress": "orderer0.group1.orderer.example.com:7030", - "name": "orderer0.group1", - "orgMspName": "OrdererMSP", - "orgName": "Orderer", - "port": 7030, - }, - "ordererHeads": [ - { - "address": "orderer0.group1.orderer.example.com", - "adminPort": 7053, - "consensus": "solo", - "domain": "orderer.example.com", - "fullAddress": "orderer0.group1.orderer.example.com:7030", - "name": "orderer0.group1", - "orgMspName": "OrdererMSP", - "orgName": "Orderer", - "port": 7030, - }, - ], - "orderers": [ - { - "address": "orderer0.group1.orderer.example.com", - "adminPort": 7053, - "consensus": "solo", - "domain": "orderer.example.com", - "fullAddress": "orderer0.group1.orderer.example.com:7030", - "name": "orderer0.group1", - "orgMspName": "OrdererMSP", - "orgName": "Orderer", - "port": 7030, - }, - ], - "profileName": "Group1Genesis", - }, - "ordererHead": { - "address": "orderer0.group1.orderer.example.com", - "adminPort": 7053, - "consensus": "solo", - "domain": "orderer.example.com", - "fullAddress": "orderer0.group1.orderer.example.com:7030", - "name": "orderer0.group1", - "orgMspName": "OrdererMSP", - "orgName": "Orderer", - "port": 7030, - }, - "orgs": [ - { - "anchorPeers": [ - { - "address": "peer0.org1.example.com", - "couchDbExposePort": 5100, - "db": { - "type": "LevelDb", - }, - "fullAddress": "peer0.org1.example.com:7041", - "gatewayEnabled": true, - "isAnchorPeer": true, - "name": "peer0", - "port": 7041, - }, - { - "address": "peer1.org1.example.com", - "couchDbExposePort": 5101, - "db": { - "type": "LevelDb", - }, - "fullAddress": "peer1.org1.example.com:7042", - "gatewayEnabled": true, - "isAnchorPeer": true, - "name": "peer1", - "port": 7042, - }, - ], - "bootstrapPeers": ""peer0.org1.example.com:7041 peer1.org1.example.com:7042"", - "ca": { - "address": "ca.org1.example.com", - "caAdminNameVar": "ORG1_CA_ADMIN_NAME", - "caAdminPassVar": "ORG1_CA_ADMIN_PASSWORD", - "db": "sqlite", - "exposePort": 7040, - "fullAddress": "ca.org1.example.com:7054", - "port": 7054, - "prefix": "ca", - }, - "cli": { - "address": "cli.org1.example.com", - }, - "cryptoConfigFileName": "crypto-config-org1", - "domain": "org1.example.com", - "headPeer": { - "address": "peer0.org1.example.com", - "couchDbExposePort": 5100, - "db": { - "type": "LevelDb", - }, - "fullAddress": "peer0.org1.example.com:7041", - "gatewayEnabled": true, - "isAnchorPeer": true, - "name": "peer0", - "port": 7041, - }, - "mspName": "Org1MSP", - "name": "Org1", - "ordererGroups": [], - "peers": [ - { - "address": "peer0.org1.example.com", - "couchDbExposePort": 5100, - "db": { - "type": "LevelDb", - }, - "fullAddress": "peer0.org1.example.com:7041", - "gatewayEnabled": true, - "isAnchorPeer": true, - "name": "peer0", - "port": 7041, - }, - ], - "peersCount": 2, - "tools": {}, - }, - { - "anchorPeers": [ - { - "address": "peer0.org2.example.com", - "couchDbExposePort": 5120, - "db": { - "type": "LevelDb", - }, - "fullAddress": "peer0.org2.example.com:7061", - "gatewayEnabled": true, - "isAnchorPeer": true, - "name": "peer0", - "port": 7061, - }, - ], - "bootstrapPeers": "peer0.org2.example.com:7061", - "ca": { - "address": "ca.org2.example.com", - "caAdminNameVar": "ORG2_CA_ADMIN_NAME", - "caAdminPassVar": "ORG2_CA_ADMIN_PASSWORD", - "db": "sqlite", - "exposePort": 7060, - "fullAddress": "ca.org2.example.com:7054", - "port": 7054, - "prefix": "ca", - }, - "cli": { - "address": "cli.org2.example.com", - }, - "cryptoConfigFileName": "crypto-config-org2", - "domain": "org2.example.com", - "headPeer": { - "address": "peer0.org2.example.com", - "couchDbExposePort": 5120, - "db": { - "type": "LevelDb", - }, - "fullAddress": "peer0.org2.example.com:7061", - "gatewayEnabled": true, - "isAnchorPeer": true, - "name": "peer0", - "port": 7061, - }, - "mspName": "Org2MSP", - "name": "Org2", - "ordererGroups": [], - "peers": [ - { - "address": "peer0.org2.example.com", - "couchDbExposePort": 5120, - "db": { - "type": "LevelDb", - }, - "fullAddress": "peer0.org2.example.com:7061", - "gatewayEnabled": true, - "isAnchorPeer": true, - "name": "peer0", - "port": 7061, - }, - ], - "peersCount": 1, - "tools": {}, - }, - ], - "profileName": "MyChannel2", - }, - "directory": "./chaincodes/chaincode-kv-node", - "endorsement": "OR('Org1MSP.member', 'Org2MSP.member')", - "initRequired": false, - "instantiatingOrg": { - "anchorPeers": [ - { - "address": "peer0.org1.example.com", - "couchDbExposePort": 5100, - "db": { - "type": "LevelDb", - }, - "fullAddress": "peer0.org1.example.com:7041", - "gatewayEnabled": true, - "isAnchorPeer": true, - "name": "peer0", - "port": 7041, - }, - { - "address": "peer1.org1.example.com", - "couchDbExposePort": 5101, - "db": { - "type": "LevelDb", - }, - "fullAddress": "peer1.org1.example.com:7042", - "gatewayEnabled": true, - "isAnchorPeer": true, - "name": "peer1", - "port": 7042, - }, - ], - "bootstrapPeers": ""peer0.org1.example.com:7041 peer1.org1.example.com:7042"", - "ca": { - "address": "ca.org1.example.com", - "caAdminNameVar": "ORG1_CA_ADMIN_NAME", - "caAdminPassVar": "ORG1_CA_ADMIN_PASSWORD", - "db": "sqlite", - "exposePort": 7040, - "fullAddress": "ca.org1.example.com:7054", - "port": 7054, - "prefix": "ca", - }, - "cli": { - "address": "cli.org1.example.com", - }, - "cryptoConfigFileName": "crypto-config-org1", - "domain": "org1.example.com", - "headPeer": { - "address": "peer0.org1.example.com", - "couchDbExposePort": 5100, - "db": { - "type": "LevelDb", - }, - "fullAddress": "peer0.org1.example.com:7041", - "gatewayEnabled": true, - "isAnchorPeer": true, - "name": "peer0", - "port": 7041, - }, - "mspName": "Org1MSP", - "name": "Org1", - "ordererGroups": [], - "peers": [ - { - "address": "peer0.org1.example.com", - "couchDbExposePort": 5100, - "db": { - "type": "LevelDb", - }, - "fullAddress": "peer0.org1.example.com:7041", - "gatewayEnabled": true, - "isAnchorPeer": true, - "name": "peer0", - "port": 7041, - }, - ], - "peersCount": 2, - "tools": {}, - }, - "lang": "node", - "name": "duplicateChaincode", - "privateData": [], - "privateDataConfigFile": undefined, - "version": "1.0", - }, - ], - "channels": [ - { - "instantiatingOrg": { - "anchorPeers": [ - { - "address": "peer0.org1.example.com", - "couchDbExposePort": 5100, - "db": { - "type": "LevelDb", - }, - "fullAddress": "peer0.org1.example.com:7041", - "gatewayEnabled": true, - "isAnchorPeer": true, - "name": "peer0", - "port": 7041, - }, - { - "address": "peer1.org1.example.com", - "couchDbExposePort": 5101, - "db": { - "type": "LevelDb", - }, - "fullAddress": "peer1.org1.example.com:7042", - "gatewayEnabled": true, - "isAnchorPeer": true, - "name": "peer1", - "port": 7042, - }, - ], - "bootstrapPeers": ""peer0.org1.example.com:7041 peer1.org1.example.com:7042"", - "ca": { - "address": "ca.org1.example.com", - "caAdminNameVar": "ORG1_CA_ADMIN_NAME", - "caAdminPassVar": "ORG1_CA_ADMIN_PASSWORD", - "db": "sqlite", - "exposePort": 7040, - "fullAddress": "ca.org1.example.com:7054", - "port": 7054, - "prefix": "ca", - }, - "cli": { - "address": "cli.org1.example.com", - }, - "cryptoConfigFileName": "crypto-config-org1", - "domain": "org1.example.com", - "headPeer": { - "address": "peer0.org1.example.com", - "couchDbExposePort": 5100, - "db": { - "type": "LevelDb", - }, - "fullAddress": "peer0.org1.example.com:7041", - "gatewayEnabled": true, - "isAnchorPeer": true, - "name": "peer0", - "port": 7041, - }, - "mspName": "Org1MSP", - "name": "Org1", - "ordererGroups": [], - "peers": [ - { - "address": "peer0.org1.example.com", - "couchDbExposePort": 5100, - "db": { - "type": "LevelDb", - }, - "fullAddress": "peer0.org1.example.com:7041", - "gatewayEnabled": true, - "isAnchorPeer": true, - "name": "peer0", - "port": 7041, - }, - ], - "peersCount": 2, - "tools": {}, - }, - "name": "my-channel1", - "ordererGroup": { - "configtxOrdererDefaults": "Group1Defaults", - "consensus": "solo", - "genesisBlockName": "Group1Genesis.block", - "hostingOrgs": [ - "Orderer", - ], - "name": "group1", - "ordererHead": { - "address": "orderer0.group1.orderer.example.com", - "adminPort": 7053, - "consensus": "solo", - "domain": "orderer.example.com", - "fullAddress": "orderer0.group1.orderer.example.com:7030", - "name": "orderer0.group1", - "orgMspName": "OrdererMSP", - "orgName": "Orderer", - "port": 7030, - }, - "ordererHeads": [ - { - "address": "orderer0.group1.orderer.example.com", - "adminPort": 7053, - "consensus": "solo", - "domain": "orderer.example.com", - "fullAddress": "orderer0.group1.orderer.example.com:7030", - "name": "orderer0.group1", - "orgMspName": "OrdererMSP", - "orgName": "Orderer", - "port": 7030, - }, - ], - "orderers": [ - { - "address": "orderer0.group1.orderer.example.com", - "adminPort": 7053, - "consensus": "solo", - "domain": "orderer.example.com", - "fullAddress": "orderer0.group1.orderer.example.com:7030", - "name": "orderer0.group1", - "orgMspName": "OrdererMSP", - "orgName": "Orderer", - "port": 7030, - }, - ], - "profileName": "Group1Genesis", - }, - "ordererHead": { - "address": "orderer0.group1.orderer.example.com", - "adminPort": 7053, - "consensus": "solo", - "domain": "orderer.example.com", - "fullAddress": "orderer0.group1.orderer.example.com:7030", - "name": "orderer0.group1", - "orgMspName": "OrdererMSP", - "orgName": "Orderer", - "port": 7030, - }, - "orgs": [ - { - "anchorPeers": [ - { - "address": "peer0.org1.example.com", - "couchDbExposePort": 5100, - "db": { - "type": "LevelDb", - }, - "fullAddress": "peer0.org1.example.com:7041", - "gatewayEnabled": true, - "isAnchorPeer": true, - "name": "peer0", - "port": 7041, - }, - { - "address": "peer1.org1.example.com", - "couchDbExposePort": 5101, - "db": { - "type": "LevelDb", - }, - "fullAddress": "peer1.org1.example.com:7042", - "gatewayEnabled": true, - "isAnchorPeer": true, - "name": "peer1", - "port": 7042, - }, - ], - "bootstrapPeers": ""peer0.org1.example.com:7041 peer1.org1.example.com:7042"", - "ca": { - "address": "ca.org1.example.com", - "caAdminNameVar": "ORG1_CA_ADMIN_NAME", - "caAdminPassVar": "ORG1_CA_ADMIN_PASSWORD", - "db": "sqlite", - "exposePort": 7040, - "fullAddress": "ca.org1.example.com:7054", - "port": 7054, - "prefix": "ca", - }, - "cli": { - "address": "cli.org1.example.com", - }, - "cryptoConfigFileName": "crypto-config-org1", - "domain": "org1.example.com", - "headPeer": { - "address": "peer0.org1.example.com", - "couchDbExposePort": 5100, - "db": { - "type": "LevelDb", - }, - "fullAddress": "peer0.org1.example.com:7041", - "gatewayEnabled": true, - "isAnchorPeer": true, - "name": "peer0", - "port": 7041, - }, - "mspName": "Org1MSP", - "name": "Org1", - "ordererGroups": [], - "peers": [ - { - "address": "peer0.org1.example.com", - "couchDbExposePort": 5100, - "db": { - "type": "LevelDb", - }, - "fullAddress": "peer0.org1.example.com:7041", - "gatewayEnabled": true, - "isAnchorPeer": true, - "name": "peer0", - "port": 7041, - }, - ], - "peersCount": 2, - "tools": {}, - }, - { - "anchorPeers": [ - { - "address": "peer0.org2.example.com", - "couchDbExposePort": 5120, - "db": { - "type": "LevelDb", - }, - "fullAddress": "peer0.org2.example.com:7061", - "gatewayEnabled": true, - "isAnchorPeer": true, - "name": "peer0", - "port": 7061, - }, - ], - "bootstrapPeers": "peer0.org2.example.com:7061", - "ca": { - "address": "ca.org2.example.com", - "caAdminNameVar": "ORG2_CA_ADMIN_NAME", - "caAdminPassVar": "ORG2_CA_ADMIN_PASSWORD", - "db": "sqlite", - "exposePort": 7060, - "fullAddress": "ca.org2.example.com:7054", - "port": 7054, - "prefix": "ca", - }, - "cli": { - "address": "cli.org2.example.com", - }, - "cryptoConfigFileName": "crypto-config-org2", - "domain": "org2.example.com", - "headPeer": { - "address": "peer0.org2.example.com", - "couchDbExposePort": 5120, - "db": { - "type": "LevelDb", - }, - "fullAddress": "peer0.org2.example.com:7061", - "gatewayEnabled": true, - "isAnchorPeer": true, - "name": "peer0", - "port": 7061, - }, - "mspName": "Org2MSP", - "name": "Org2", - "ordererGroups": [], - "peers": [ - { - "address": "peer0.org2.example.com", - "couchDbExposePort": 5120, - "db": { - "type": "LevelDb", - }, - "fullAddress": "peer0.org2.example.com:7061", - "gatewayEnabled": true, - "isAnchorPeer": true, - "name": "peer0", - "port": 7061, - }, - ], - "peersCount": 1, - "tools": {}, - }, - ], - "profileName": "MyChannel1", - }, - { - "instantiatingOrg": { - "anchorPeers": [ - { - "address": "peer0.org1.example.com", - "couchDbExposePort": 5100, - "db": { - "type": "LevelDb", - }, - "fullAddress": "peer0.org1.example.com:7041", - "gatewayEnabled": true, - "isAnchorPeer": true, - "name": "peer0", - "port": 7041, - }, - { - "address": "peer1.org1.example.com", - "couchDbExposePort": 5101, - "db": { - "type": "LevelDb", - }, - "fullAddress": "peer1.org1.example.com:7042", - "gatewayEnabled": true, - "isAnchorPeer": true, - "name": "peer1", - "port": 7042, - }, - ], - "bootstrapPeers": ""peer0.org1.example.com:7041 peer1.org1.example.com:7042"", - "ca": { - "address": "ca.org1.example.com", - "caAdminNameVar": "ORG1_CA_ADMIN_NAME", - "caAdminPassVar": "ORG1_CA_ADMIN_PASSWORD", - "db": "sqlite", - "exposePort": 7040, - "fullAddress": "ca.org1.example.com:7054", - "port": 7054, - "prefix": "ca", - }, - "cli": { - "address": "cli.org1.example.com", - }, - "cryptoConfigFileName": "crypto-config-org1", - "domain": "org1.example.com", - "headPeer": { - "address": "peer0.org1.example.com", - "couchDbExposePort": 5100, - "db": { - "type": "LevelDb", - }, - "fullAddress": "peer0.org1.example.com:7041", - "gatewayEnabled": true, - "isAnchorPeer": true, - "name": "peer0", - "port": 7041, - }, - "mspName": "Org1MSP", - "name": "Org1", - "ordererGroups": [], - "peers": [ - { - "address": "peer0.org1.example.com", - "couchDbExposePort": 5100, - "db": { - "type": "LevelDb", - }, - "fullAddress": "peer0.org1.example.com:7041", - "gatewayEnabled": true, - "isAnchorPeer": true, - "name": "peer0", - "port": 7041, - }, - ], - "peersCount": 2, - "tools": {}, - }, - "name": "my-channel2", - "ordererGroup": { - "configtxOrdererDefaults": "Group1Defaults", - "consensus": "solo", - "genesisBlockName": "Group1Genesis.block", - "hostingOrgs": [ - "Orderer", - ], - "name": "group1", - "ordererHead": { - "address": "orderer0.group1.orderer.example.com", - "adminPort": 7053, - "consensus": "solo", - "domain": "orderer.example.com", - "fullAddress": "orderer0.group1.orderer.example.com:7030", - "name": "orderer0.group1", - "orgMspName": "OrdererMSP", - "orgName": "Orderer", - "port": 7030, - }, - "ordererHeads": [ - { - "address": "orderer0.group1.orderer.example.com", - "adminPort": 7053, - "consensus": "solo", - "domain": "orderer.example.com", - "fullAddress": "orderer0.group1.orderer.example.com:7030", - "name": "orderer0.group1", - "orgMspName": "OrdererMSP", - "orgName": "Orderer", - "port": 7030, - }, - ], - "orderers": [ - { - "address": "orderer0.group1.orderer.example.com", - "adminPort": 7053, - "consensus": "solo", - "domain": "orderer.example.com", - "fullAddress": "orderer0.group1.orderer.example.com:7030", - "name": "orderer0.group1", - "orgMspName": "OrdererMSP", - "orgName": "Orderer", - "port": 7030, - }, - ], - "profileName": "Group1Genesis", - }, - "ordererHead": { - "address": "orderer0.group1.orderer.example.com", - "adminPort": 7053, - "consensus": "solo", - "domain": "orderer.example.com", - "fullAddress": "orderer0.group1.orderer.example.com:7030", - "name": "orderer0.group1", - "orgMspName": "OrdererMSP", - "orgName": "Orderer", - "port": 7030, - }, - "orgs": [ - { - "anchorPeers": [ - { - "address": "peer0.org1.example.com", - "couchDbExposePort": 5100, - "db": { - "type": "LevelDb", - }, - "fullAddress": "peer0.org1.example.com:7041", - "gatewayEnabled": true, - "isAnchorPeer": true, - "name": "peer0", - "port": 7041, - }, - { - "address": "peer1.org1.example.com", - "couchDbExposePort": 5101, - "db": { - "type": "LevelDb", - }, - "fullAddress": "peer1.org1.example.com:7042", - "gatewayEnabled": true, - "isAnchorPeer": true, - "name": "peer1", - "port": 7042, - }, - ], - "bootstrapPeers": ""peer0.org1.example.com:7041 peer1.org1.example.com:7042"", - "ca": { - "address": "ca.org1.example.com", - "caAdminNameVar": "ORG1_CA_ADMIN_NAME", - "caAdminPassVar": "ORG1_CA_ADMIN_PASSWORD", - "db": "sqlite", - "exposePort": 7040, - "fullAddress": "ca.org1.example.com:7054", - "port": 7054, - "prefix": "ca", - }, - "cli": { - "address": "cli.org1.example.com", - }, - "cryptoConfigFileName": "crypto-config-org1", - "domain": "org1.example.com", - "headPeer": { - "address": "peer0.org1.example.com", - "couchDbExposePort": 5100, - "db": { - "type": "LevelDb", - }, - "fullAddress": "peer0.org1.example.com:7041", - "gatewayEnabled": true, - "isAnchorPeer": true, - "name": "peer0", - "port": 7041, - }, - "mspName": "Org1MSP", - "name": "Org1", - "ordererGroups": [], - "peers": [ - { - "address": "peer0.org1.example.com", - "couchDbExposePort": 5100, - "db": { - "type": "LevelDb", - }, - "fullAddress": "peer0.org1.example.com:7041", - "gatewayEnabled": true, - "isAnchorPeer": true, - "name": "peer0", - "port": 7041, - }, - ], - "peersCount": 2, - "tools": {}, - }, - { - "anchorPeers": [ - { - "address": "peer0.org2.example.com", - "couchDbExposePort": 5120, - "db": { - "type": "LevelDb", - }, - "fullAddress": "peer0.org2.example.com:7061", - "gatewayEnabled": true, - "isAnchorPeer": true, - "name": "peer0", - "port": 7061, - }, - ], - "bootstrapPeers": "peer0.org2.example.com:7061", - "ca": { - "address": "ca.org2.example.com", - "caAdminNameVar": "ORG2_CA_ADMIN_NAME", - "caAdminPassVar": "ORG2_CA_ADMIN_PASSWORD", - "db": "sqlite", - "exposePort": 7060, - "fullAddress": "ca.org2.example.com:7054", - "port": 7054, - "prefix": "ca", - }, - "cli": { - "address": "cli.org2.example.com", - }, - "cryptoConfigFileName": "crypto-config-org2", - "domain": "org2.example.com", - "headPeer": { - "address": "peer0.org2.example.com", - "couchDbExposePort": 5120, - "db": { - "type": "LevelDb", - }, - "fullAddress": "peer0.org2.example.com:7061", - "gatewayEnabled": true, - "isAnchorPeer": true, - "name": "peer0", - "port": 7061, - }, - "mspName": "Org2MSP", - "name": "Org2", - "ordererGroups": [], - "peers": [ - { - "address": "peer0.org2.example.com", - "couchDbExposePort": 5120, - "db": { - "type": "LevelDb", - }, - "fullAddress": "peer0.org2.example.com:7061", - "gatewayEnabled": true, - "isAnchorPeer": true, - "name": "peer0", - "port": 7061, - }, - ], - "peersCount": 1, - "tools": {}, - }, - ], - "profileName": "MyChannel2", - }, - ], - "global": { - "capabilities": { - "application": "V2_5", - "channel": "V2_0", - "isV2": true, - "isV3": false, - "orderer": "V2_0", - }, - "engine": "docker", - "fabricBaseosVersion": "2.5.12", - "fabricCaVersion": "1.5.5", - "fabricCcenvVersion": "2.5.12", - "fabricJavaenvVersion": "2.5", - "fabricNodeenvVersion": "2.5", - "fabricRecommendedNodeVersion": "16", - "fabricToolsVersion": "2.5.12", - "fabricVersion": "2.5.12", - "monitoring": { - "loglevel": "info", - }, - "paths": { - "chaincodesBaseDir": "", - "fabloConfig": "", - }, - "tls": false, - "tools": {}, - }, - "hooks": { - "postGenerate": "", - }, - "orderedHeadsDistinct": [ - { - "address": "orderer0.group1.orderer.example.com", - "adminPort": 7053, - "consensus": "solo", - "domain": "orderer.example.com", - "fullAddress": "orderer0.group1.orderer.example.com:7030", - "name": "orderer0.group1", - "orgMspName": "OrdererMSP", - "orgName": "Orderer", - "port": 7030, - }, - ], - "ordererGroups": [ - { - "configtxOrdererDefaults": "Group1Defaults", - "consensus": "solo", - "genesisBlockName": "Group1Genesis.block", - "hostingOrgs": [ - "Orderer", - ], - "name": "group1", - "ordererHead": { - "address": "orderer0.group1.orderer.example.com", - "adminPort": 7053, - "consensus": "solo", - "domain": "orderer.example.com", - "fullAddress": "orderer0.group1.orderer.example.com:7030", - "name": "orderer0.group1", - "orgMspName": "OrdererMSP", - "orgName": "Orderer", - "port": 7030, - }, - "ordererHeads": [ - { - "address": "orderer0.group1.orderer.example.com", - "adminPort": 7053, - "consensus": "solo", - "domain": "orderer.example.com", - "fullAddress": "orderer0.group1.orderer.example.com:7030", - "name": "orderer0.group1", - "orgMspName": "OrdererMSP", - "orgName": "Orderer", - "port": 7030, - }, - ], - "orderers": [ - { - "address": "orderer0.group1.orderer.example.com", - "adminPort": 7053, - "consensus": "solo", - "domain": "orderer.example.com", - "fullAddress": "orderer0.group1.orderer.example.com:7030", - "name": "orderer0.group1", - "orgMspName": "OrdererMSP", - "orgName": "Orderer", - "port": 7030, - }, - ], - "profileName": "Group1Genesis", - }, - ], - "orgs": [ - { - "anchorPeers": [], - "bootstrapPeers": """", - "ca": { - "address": "ca.orderer.example.com", - "caAdminNameVar": "ORDERER_CA_ADMIN_NAME", - "caAdminPassVar": "ORDERER_CA_ADMIN_PASSWORD", - "db": "sqlite", - "exposePort": 7020, - "fullAddress": "ca.orderer.example.com:7054", - "port": 7054, - "prefix": "ca", - }, - "cli": { - "address": "cli.orderer.example.com", - }, - "cryptoConfigFileName": "crypto-config-orderer", - "domain": "orderer.example.com", - "headPeer": undefined, - "mspName": "OrdererMSP", - "name": "Orderer", - "ordererGroups": [ - { - "configtxOrdererDefaults": "Group1Defaults", - "consensus": "solo", - "genesisBlockName": "Group1Genesis.block", - "hostingOrgs": [ - "Orderer", - ], - "name": "group1", - "ordererHeads": [ - { - "address": "orderer0.group1.orderer.example.com", - "adminPort": 7053, - "consensus": "solo", - "domain": "orderer.example.com", - "fullAddress": "orderer0.group1.orderer.example.com:7030", - "name": "orderer0.group1", - "orgMspName": "OrdererMSP", - "orgName": "Orderer", - "port": 7030, - }, - ], - "orderers": [ - { - "address": "orderer0.group1.orderer.example.com", - "adminPort": 7053, - "consensus": "solo", - "domain": "orderer.example.com", - "fullAddress": "orderer0.group1.orderer.example.com:7030", - "name": "orderer0.group1", - "orgMspName": "OrdererMSP", - "orgName": "Orderer", - "port": 7030, - }, - ], - "profileName": "Group1Genesis", - }, - ], - "peers": [], - "peersCount": 0, - "tools": {}, - }, - { - "anchorPeers": [ - { - "address": "peer0.org1.example.com", - "couchDbExposePort": 5100, - "db": { - "type": "LevelDb", - }, - "fullAddress": "peer0.org1.example.com:7041", - "gatewayEnabled": true, - "isAnchorPeer": true, - "name": "peer0", - "port": 7041, - }, - { - "address": "peer1.org1.example.com", - "couchDbExposePort": 5101, - "db": { - "type": "LevelDb", - }, - "fullAddress": "peer1.org1.example.com:7042", - "gatewayEnabled": true, - "isAnchorPeer": true, - "name": "peer1", - "port": 7042, - }, - ], - "bootstrapPeers": ""peer0.org1.example.com:7041 peer1.org1.example.com:7042"", - "ca": { - "address": "ca.org1.example.com", - "caAdminNameVar": "ORG1_CA_ADMIN_NAME", - "caAdminPassVar": "ORG1_CA_ADMIN_PASSWORD", - "db": "sqlite", - "exposePort": 7040, - "fullAddress": "ca.org1.example.com:7054", - "port": 7054, - "prefix": "ca", - }, - "cli": { - "address": "cli.org1.example.com", - }, - "cryptoConfigFileName": "crypto-config-org1", - "domain": "org1.example.com", - "headPeer": { - "address": "peer0.org1.example.com", - "couchDbExposePort": 5100, - "db": { - "type": "LevelDb", - }, - "fullAddress": "peer0.org1.example.com:7041", - "gatewayEnabled": true, - "isAnchorPeer": true, - "name": "peer0", - "port": 7041, - }, - "mspName": "Org1MSP", - "name": "Org1", - "ordererGroups": [], - "peers": [ - { - "address": "peer0.org1.example.com", - "couchDbExposePort": 5100, - "db": { - "type": "LevelDb", - }, - "fullAddress": "peer0.org1.example.com:7041", - "gatewayEnabled": true, - "isAnchorPeer": true, - "name": "peer0", - "port": 7041, - }, - { - "address": "peer1.org1.example.com", - "couchDbExposePort": 5101, - "db": { - "type": "LevelDb", - }, - "fullAddress": "peer1.org1.example.com:7042", - "gatewayEnabled": true, - "isAnchorPeer": true, - "name": "peer1", - "port": 7042, - }, - ], - "peersCount": 2, - "tools": {}, - }, - { - "anchorPeers": [ - { - "address": "peer0.org2.example.com", - "couchDbExposePort": 5120, - "db": { - "type": "LevelDb", - }, - "fullAddress": "peer0.org2.example.com:7061", - "gatewayEnabled": true, - "isAnchorPeer": true, - "name": "peer0", - "port": 7061, - }, - ], - "bootstrapPeers": "peer0.org2.example.com:7061", - "ca": { - "address": "ca.org2.example.com", - "caAdminNameVar": "ORG2_CA_ADMIN_NAME", - "caAdminPassVar": "ORG2_CA_ADMIN_PASSWORD", - "db": "sqlite", - "exposePort": 7060, - "fullAddress": "ca.org2.example.com:7054", - "port": 7054, - "prefix": "ca", - }, - "cli": { - "address": "cli.org2.example.com", - }, - "cryptoConfigFileName": "crypto-config-org2", - "domain": "org2.example.com", - "headPeer": { - "address": "peer0.org2.example.com", - "couchDbExposePort": 5120, - "db": { - "type": "LevelDb", - }, - "fullAddress": "peer0.org2.example.com:7061", - "gatewayEnabled": true, - "isAnchorPeer": true, - "name": "peer0", - "port": 7061, - }, - "mspName": "Org2MSP", - "name": "Org2", - "ordererGroups": [], - "peers": [ - { - "address": "peer0.org2.example.com", - "couchDbExposePort": 5120, - "db": { - "type": "LevelDb", - }, - "fullAddress": "peer0.org2.example.com:7061", - "gatewayEnabled": true, - "isAnchorPeer": true, - "name": "peer0", - "port": 7061, - }, - ], - "peersCount": 1, - "tools": {}, - }, - ], -} -`; - exports[`extend config samples/fablo-config-hlf2-2orgs-2chaincodes-raft.yaml 1`] = ` { "chaincodes": [ diff --git a/e2e/__snapshots__/fablo-config-hlf2-2orgs-2chaincodes-private-data-duplicate.yaml.test.ts.snap b/e2e/__snapshots__/fablo-config-hlf2-2orgs-2chaincodes-private-data-duplicate.yaml.test.ts.snap deleted file mode 100644 index b4aeda952..000000000 --- a/e2e/__snapshots__/fablo-config-hlf2-2orgs-2chaincodes-private-data-duplicate.yaml.test.ts.snap +++ /dev/null @@ -1,3 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`samples/fablo-config-hlf2-2orgs-2chaincodes-private-data-duplicate.yaml should create proper files from samples/fablo-config-hlf2-2orgs-2chaincodes-private-data-duplicate.yaml 1`] = `[]`; diff --git a/e2e/fabloCommands.test.ts b/e2e/fabloCommands.test.ts index 0151f0231..750407ed0 100644 --- a/e2e/fabloCommands.test.ts +++ b/e2e/fabloCommands.test.ts @@ -140,19 +140,6 @@ describe("validate", () => { expect(commands.getFiles()).toEqual([]); }); - // it("should throw an error for duplicate chaincode names across different channels", () => { - // // Given - // commands.fabloExec("init"); - // const fabloConfig = `${commands.relativeRoot}/samples/fablo-config-hlf2-2orgs-2chaincodes-private-data-duplicate.yaml`; - - // // When - // const commandResult = commands.fabloExec(`validate ${fabloConfig}`); - - // // Then - // // expect(commandResult).toEqual(TestCommands.success()); - // expect(commandResult.output).toContain("Chaincode name 'duplicateChaincode' is not unique"); - // }); - }); describe("extend config", () => { @@ -196,6 +183,34 @@ describe("extend config", () => { expect(commandResult).toEqual(TestCommands.failure()); expect(commandResult.output).toContain("commands-tests/fablo-config.json does not exist\n"); }); + + it("should throw an error for duplicate chaincode names across different channels", () => { + // Given + commands.fabloExec("init node"); + const configPath = `${commands.workdir}/fablo-config.json`; + const config = JSON.parse(fs.readFileSync(configPath, 'utf8')) as FabloConfigJson; + + config.channels.push({ + name: "my-channel2", + orgs: [ + { name: "Org1", peers: ["peer0"] } + ] + }); + + const existingChaincode = JSON.parse(JSON.stringify(config.chaincodes[0])); + existingChaincode.channel = "my-channel2"; + config.chaincodes.push(existingChaincode); + + fs.writeFileSync(configPath, JSON.stringify(config, null, 2)); + + // When + const commandResult = commands.fabloExec("validate", true); + + // Then + expect(commandResult.output).toContain("Chaincode name 'chaincode1' is not unique"); + expect(commandResult.output).toContain("Validation errors count: 1"); + + }); }); describe("version", () => { diff --git a/src/extend-config/extendChaincodesConfig.ts b/src/extend-config/extendChaincodesConfig.ts index cbd5b8c68..c99daceda 100644 --- a/src/extend-config/extendChaincodesConfig.ts +++ b/src/extend-config/extendChaincodesConfig.ts @@ -62,7 +62,7 @@ const extendChaincodesConfig = ( network: Global, ): ChaincodeConfig[] => { checkUniqueChaincodeNames(chaincodes); - return chaincodes.map((chaincode) => { + return chaincodes.map((chaincode,index) => { const channel = transformedChannels.find((c) => c.name === chaincode.channel); if (!channel) throw new Error(`No matching channel with name '${chaincode.channel}'`); From 7fafe44ecb057fb7222217cc5f5f3a4bb10ef0f6 Mon Sep 17 00:00:00 2001 From: OsamaRab3 Date: Fri, 29 Aug 2025 11:47:28 +0300 Subject: [PATCH 09/10] fix lint issue Signed-off-by: OsamaRab3 --- e2e/fabloCommands.test.ts | 14 +++++--------- src/extend-config/extendChaincodesConfig.ts | 6 +++--- 2 files changed, 8 insertions(+), 12 deletions(-) diff --git a/e2e/fabloCommands.test.ts b/e2e/fabloCommands.test.ts index 750407ed0..4d5d03c7e 100644 --- a/e2e/fabloCommands.test.ts +++ b/e2e/fabloCommands.test.ts @@ -139,7 +139,6 @@ describe("validate", () => { expect(commandResult.output).toContain(" instance.orgs[0].organization.mspName : does not match pattern"); expect(commands.getFiles()).toEqual([]); }); - }); describe("extend config", () => { @@ -188,19 +187,17 @@ describe("extend config", () => { // Given commands.fabloExec("init node"); const configPath = `${commands.workdir}/fablo-config.json`; - const config = JSON.parse(fs.readFileSync(configPath, 'utf8')) as FabloConfigJson; - + const config = JSON.parse(fs.readFileSync(configPath, "utf8")) as FabloConfigJson; + config.channels.push({ name: "my-channel2", - orgs: [ - { name: "Org1", peers: ["peer0"] } - ] + orgs: [{ name: "Org1", peers: ["peer0"] }], }); - + const existingChaincode = JSON.parse(JSON.stringify(config.chaincodes[0])); existingChaincode.channel = "my-channel2"; config.chaincodes.push(existingChaincode); - + fs.writeFileSync(configPath, JSON.stringify(config, null, 2)); // When @@ -209,7 +206,6 @@ describe("extend config", () => { // Then expect(commandResult.output).toContain("Chaincode name 'chaincode1' is not unique"); expect(commandResult.output).toContain("Validation errors count: 1"); - }); }); diff --git a/src/extend-config/extendChaincodesConfig.ts b/src/extend-config/extendChaincodesConfig.ts index c99daceda..ca850e339 100644 --- a/src/extend-config/extendChaincodesConfig.ts +++ b/src/extend-config/extendChaincodesConfig.ts @@ -39,7 +39,7 @@ const createPrivateCollectionConfig = ( const checkUniqueChaincodeNames = (allChannelsConfig: any): void => { const chaincodeNames = new Set(); - + const allChaincodes: ChaincodeJson[] = []; Object.values(allChannelsConfig.channels || {}).forEach((channel: any) => { @@ -47,7 +47,7 @@ const checkUniqueChaincodeNames = (allChannelsConfig: any): void => { allChaincodes.push(...channel.chaincodes); } }); - + allChaincodes.forEach((chaincode) => { if (chaincodeNames.has(chaincode.name)) { throw new Error(`Chaincode name '${chaincode.name}' is not unique across channels.`); @@ -62,7 +62,7 @@ const extendChaincodesConfig = ( network: Global, ): ChaincodeConfig[] => { checkUniqueChaincodeNames(chaincodes); - return chaincodes.map((chaincode,index) => { + return chaincodes.map((chaincode, index) => { const channel = transformedChannels.find((c) => c.name === chaincode.channel); if (!channel) throw new Error(`No matching channel with name '${chaincode.channel}'`); From 449943d1081c6f13bcaee61bfd122f4ead226b5f Mon Sep 17 00:00:00 2001 From: OsamaRab3 Date: Mon, 8 Sep 2025 07:56:15 +0300 Subject: [PATCH 10/10] fix lint error Signed-off-by: OsamaRab3 --- e2e/fabloCommands.test.ts | 26 +++++++++++++++++++++----- 1 file changed, 21 insertions(+), 5 deletions(-) diff --git a/e2e/fabloCommands.test.ts b/e2e/fabloCommands.test.ts index 4d5d03c7e..0afab0964 100644 --- a/e2e/fabloCommands.test.ts +++ b/e2e/fabloCommands.test.ts @@ -185,18 +185,34 @@ describe("extend config", () => { it("should throw an error for duplicate chaincode names across different channels", () => { // Given - commands.fabloExec("init node"); + commands.fabloExec("init"); const configPath = `${commands.workdir}/fablo-config.json`; - const config = JSON.parse(fs.readFileSync(configPath, "utf8")) as FabloConfigJson; + // const config = JSON.parse(fs.readFileSync(configPath, "utf8")) as FabloConfigJson; + const config = JSON.parse(commands.getFileContent("fablo-config.json")) as FabloConfigJson; config.channels.push({ name: "my-channel2", orgs: [{ name: "Org1", peers: ["peer0"] }], }); - const existingChaincode = JSON.parse(JSON.stringify(config.chaincodes[0])); - existingChaincode.channel = "my-channel2"; - config.chaincodes.push(existingChaincode); + config.chaincodes.push( + { + name: "chaincode1", + version: "1.0", + channel: "my-channel", + lang: "node", + directory: "./samples/chaincodes/chaincode-kv-node", + privateData: [], + }, + { + name: "chaincode1", + version: "1.0", + channel: "my-channel2", + lang: "node", + directory: "./samples/chaincodes/chaincode-kv-node", + privateData: [], + }, + ); fs.writeFileSync(configPath, JSON.stringify(config, null, 2));