github.com/darrenli6/fabric-sdk-example@v0.0.0-20220109053535-94b13b56df8c/bddtests/steps/bootstrap_impl.py (about) 1 # Copyright IBM Corp. 2016 All Rights Reserved. 2 # 3 # Licensed under the Apache License, Version 2.0 (the "License"); 4 # you may not use this file except in compliance with the License. 5 # You may obtain a copy of the License at 6 # 7 # http://www.apache.org/licenses/LICENSE-2.0 8 # 9 # Unless required by applicable law or agreed to in writing, software 10 # distributed under the License is distributed on an "AS IS" BASIS, 11 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 # See the License for the specific language governing permissions and 13 # limitations under the License. 14 # 15 16 from behave import * 17 import endorser_util 18 import bootstrap_util 19 import orderer_util 20 import compose 21 import time 22 23 @given(u'the orderer network has organizations') 24 def step_impl(context): 25 assert 'table' in context, "Expected table of orderer organizations" 26 directory = bootstrap_util.getDirectory(context) 27 for row in context.table.rows: 28 org = directory.getOrganization(row['Organization'], shouldCreate = True) 29 org.addToNetwork(bootstrap_util.Network.Orderer) 30 31 32 @given(u'user requests role of orderer admin by creating a key and csr for orderer and acquires signed certificate from organization') 33 def step_impl(context): 34 assert 'table' in context, "Expected table with triplet of User/Orderer/Organization" 35 directory = bootstrap_util.getDirectory(context) 36 for row in context.table.rows: 37 nodeAdminTuple = directory.registerOrdererAdminTuple(row['User'], row['Orderer'], row['Organization']) 38 aliasToSaveUnder = row['AliasSavedUnder'] 39 if aliasToSaveUnder != "": 40 directory.getUser(row['User']).setTagValue(aliasToSaveUnder, nodeAdminTuple) 41 42 @given(u'user requests role for peer by creating a key and csr for peer and acquires signed certificate from organization') 43 def step_impl(context): 44 assert 'table' in context, "Expected table with triplet of User/Peer/Organization" 45 directory = bootstrap_util.getDirectory(context) 46 for row in context.table.rows: 47 nodeAdminTuple = directory.registerOrdererAdminTuple(row['User'], row['Peer'], row['Organization']) 48 aliasToSaveUnder = row['AliasSavedUnder'] 49 if aliasToSaveUnder != "": 50 directory.getUser(row['User']).setTagValue(aliasToSaveUnder, nodeAdminTuple) 51 52 53 @given(u'the peer network has organizations') 54 def step_impl(context): 55 assert 'table' in context, "Expected table of peer network organizations" 56 directory = bootstrap_util.getDirectory(context) 57 for row in context.table.rows: 58 org = directory.getOrganization(row['Organization'], shouldCreate = True) 59 org.addToNetwork(bootstrap_util.Network.Peer) 60 61 @given(u'a ordererBootstrapAdmin is identified and given access to all public certificates and orderer node info') 62 def step_impl(context): 63 directory = bootstrap_util.getDirectory(context) 64 assert len(directory.ordererAdminTuples) > 0, "No orderer admin tuples defined!!!" 65 # Simply create the user 66 bootstrap_util.getOrdererBootstrapAdmin(context, shouldCreate=True) 67 68 @given(u'the ordererBootstrapAdmin using cert alias "{certAlias}" creates the genesis block "{ordererGenesisBlockName}" for chain "{ordererSystemChainIdName}" for composition "{composeFile}" and consensus "{consensusType}" with consortiums modification policy "{consortiumsModPolicy}" using consortiums') 69 def step_impl(context, certAlias, ordererGenesisBlockName, ordererSystemChainIdName, composeFile, consensusType, consortiumsModPolicy): 70 directory = bootstrap_util.getDirectory(context=context) 71 ordererBootstrapAdmin = bootstrap_util.getOrdererBootstrapAdmin(context) 72 ordererSystemChainIdGUUID = ordererBootstrapAdmin.tags[ordererSystemChainIdName] 73 # Now collect the named signed config items 74 configGroups =[bootstrap_util.getDefaultConsortiumGroup(consortiumsModPolicy)] 75 for row in context.table.rows: 76 configGroupName = row['Consortium'] 77 configGroups += ordererBootstrapAdmin.tags[configGroupName] 78 # Concatenate signedConfigItems 79 80 service_names = compose.Composition(context, composeFilesYaml=composeFile, register_and_up=False).getServiceNames() 81 82 # Construct block 83 nodeAdminTuple = ordererBootstrapAdmin.tags[certAlias] 84 bootstrapCert = directory.findCertForNodeAdminTuple(nodeAdminTuple=nodeAdminTuple) 85 (genesisBlock, envelope, genesis_block_channel_config) = bootstrap_util.createGenesisBlock(context=context, 86 service_names=service_names, 87 chainId=ordererSystemChainIdGUUID, 88 consensusType=consensusType, 89 nodeAdminTuple=nodeAdminTuple, 90 signedConfigItems=configGroups) 91 ordererBootstrapAdmin.setTagValue(ordererGenesisBlockName + "_genesis_channel_config", genesis_block_channel_config) 92 ordererBootstrapAdmin.setTagValue(ordererGenesisBlockName, genesisBlock) 93 ordererBootstrapAdmin.setTagValue("ConsensusType", consensusType) 94 bootstrap_util.OrdererGensisBlockCompositionCallback(context, genesisBlock) 95 bootstrap_util.PeerCompositionCallback(context) 96 97 @given(u'the orderer admins inspect and approve the genesis block for chain "{chainId}"') 98 def step_impl(context, chainId): 99 pass 100 101 @given(u'the orderer admins use the genesis block for chain "{chainId}" to configure orderers') 102 def step_impl(context, chainId): 103 pass 104 #raise NotImplementedError(u'STEP: Given the orderer admins use the genesis block for chain "testchainid" to configure orderers') 105 106 @given(u'the ordererBootstrapAdmin generates a GUUID to identify the orderer system chain and refer to it by name as "{ordererSystemChainId}"') 107 def step_impl(context, ordererSystemChainId): 108 directory = bootstrap_util.getDirectory(context) 109 ordererBootstrapAdmin = bootstrap_util.getOrdererBootstrapAdmin(context) 110 chaind_id = bootstrap_util.GetUniqueChannelName() 111 ordererBootstrapAdmin.setTagValue(ordererSystemChainId, chaind_id) 112 113 114 @given(u'the orderer config admin "{ordererConfigAdmin}" creates a consortium "{consortiumName}" with modification policy "{modPolicy}" for peer orgs who wish to form a network') 115 def step_impl(context, ordererConfigAdmin, consortiumName, modPolicy): 116 directory = bootstrap_util.getDirectory(context) 117 ordererConfigAdmin = directory.getUser(ordererConfigAdmin) 118 119 # Collect the orgs from the table 120 orgNames = [row['Organization'] for row in context.table.rows] 121 bootstrap_util.addOrdererBootstrapAdminOrgReferences(context, consortiumName, orgNames) 122 123 consortium = bootstrap_util.createConsortium(context=context, consortium_name=consortiumName, org_names=orgNames, mod_policy=modPolicy) 124 ordererConfigAdmin.setTagValue(consortiumName, consortium) 125 126 @given(u'the orderer config admin "{ordererConfigAdmin}" creates a consortiums config update "{consortiumsConfigUpdateName}" using config "{configName}" using orderer system channel ID "{ordererSystemChainIdName}" to add consortiums') 127 def step_impl(context, ordererConfigAdmin, consortiumsConfigUpdateName, configName, ordererSystemChainIdName): 128 ''' 129 channel group/Consortiums/ 130 Read the consortiums Group from existing genesis block. 131 ''' 132 directory = bootstrap_util.getDirectory(context) 133 ordererConfigAdmin = directory.getUser(ordererConfigAdmin) 134 channel_group = ordererConfigAdmin.getTagValue(configName) 135 orderer_system_chain_id = ordererConfigAdmin.getTagValue(ordererSystemChainIdName) 136 config_groups = [] 137 # Now collect the consortiums 138 for row in context.table.rows: 139 config_groups.append(ordererConfigAdmin.getTagValue(row['Consortium'])) 140 config_update = bootstrap_util.create_orderer_consortium_config_update(orderer_system_chain_id, channel_group, config_groups) 141 ordererConfigAdmin.setTagValue(tagKey=consortiumsConfigUpdateName, tagValue=config_update) 142 143 @given(u'the user "{userName}" creates a peer organization set "{peerOrgSetName}" with peer organizations') 144 def step_impl(context, userName, peerOrgSetName): 145 ' At the moment, only really defining MSP Config Items (NOT SIGNED)' 146 directory = bootstrap_util.getDirectory(context) 147 user = directory.getUser(userName) 148 user.setTagValue(peerOrgSetName, [directory.getOrganization(row['Organization']).name for row in context.table.rows]) 149 150 @given(u'the user "{userName}" creates a configUpdateEnvelope "{configUpdateEnvelopeName}" using configUpdate "{configUpdateName}"') 151 def step_impl(context, userName, configUpdateEnvelopeName, configUpdateName): 152 directory = bootstrap_util.getDirectory(context) 153 user = directory.getUser(userName) 154 config_update_envelope = bootstrap_util.create_config_update_envelope(config_update=user.getTagValue(configUpdateName)) 155 user.setTagValue(tagKey=configUpdateEnvelopeName, tagValue=config_update_envelope) 156 157 @given(u'the user "{userName}" creates a new channel ConfigUpdate "{create_channel_config_update_name}" using consortium "{consortium_name}"') 158 def step_impl(context, userName, create_channel_config_update_name, consortium_name): 159 directory = bootstrap_util.getDirectory(context) 160 user = directory.getUser(userName) 161 consortium_config_group = user.getTagValue(tagKey=consortium_name) 162 163 peer_org_set = user.getTagValue(tagKey=context.table.rows[0]["PeerOrgSet"]) 164 peer_anchor_set_tag_key = context.table.rows[0]["[PeerAnchorSet]"] 165 peer_anchor_config_group = None 166 if peer_anchor_set_tag_key != "": 167 peer_anchor_config_group = user.getTagValue(tagKey=peer_anchor_set_tag_key) 168 169 channel_id = context.table.rows[0]["ChannelID"] 170 # Loop through templates referenced orgs 171 # mspOrgNames = [org.name for org in user.tags[templateName]] 172 #TODO: Where does the system_channel_version come from? 173 system_channel_version = 0 174 channel_config_update = bootstrap_util.create_channel_config_update(system_channel_version, channel_id, consortium_config_group) 175 176 # Add the anchors config group 177 if peer_anchor_config_group: 178 bootstrap_util.mergeConfigGroups(channel_config_update.write_set, peer_anchor_config_group) 179 180 #Make sure orgs exist in consortium 181 for orgName in peer_org_set: 182 assert orgName in channel_config_update.write_set.groups['Application'].groups.keys(), "PeerOrgSet entry {0} not found in consortium".format(orgName) 183 184 # Strip out any organizations that are NOT referenced in peerOrgSet 185 for orgName in channel_config_update.write_set.groups['Application'].groups.keys(): 186 if not orgName in peer_org_set: 187 del(channel_config_update.read_set.groups['Application'].groups[orgName]) 188 del(channel_config_update.write_set.groups['Application'].groups[orgName]) 189 190 user.setTagValue(create_channel_config_update_name, channel_config_update) 191 192 @Given(u'the user "{user_name}" creates an existing channel config update "{existing_channel_config_update_name}" using config update "{input_config_update_name}"') 193 def step_impl(context, user_name, existing_channel_config_update_name, input_config_update_name): 194 directory = bootstrap_util.getDirectory(context) 195 user = directory.getUser(user_name) 196 197 input_config_update = user.getTagValue(tagKey=input_config_update_name) 198 199 channel_id = context.table.rows[0]["ChannelID"] 200 201 peer_anchor_set_tag_key = context.table.rows[0]["[PeerAnchorSet]"] 202 peer_anchor_config_group = None 203 if peer_anchor_set_tag_key != "": 204 peer_anchor_config_group = user.getTagValue(tagKey=peer_anchor_set_tag_key) 205 206 207 assert peer_anchor_config_group != None, "Required to specify a PeerAnchorSet for now" 208 #TODO: Where does the system_channel_version come from? 209 system_channel_version = 0 210 channel_config_update = bootstrap_util.create_existing_channel_config_update(system_channel_version=system_channel_version, 211 channel_id=channel_id, 212 input_config_update=input_config_update, 213 config_groups=[peer_anchor_config_group]) 214 215 user.setTagValue(existing_channel_config_update_name, channel_config_update) 216 217 @given(u'the following application developers are defined for peer organizations and each saves their cert as alias') 218 def step_impl(context): 219 assert 'table' in context, "Expected table with triplet of Developer/Consortium/Organization" 220 directory = bootstrap_util.getDirectory(context) 221 for row in context.table.rows: 222 userName = row['Developer'] 223 nodeAdminNamedTuple = directory.registerOrdererAdminTuple(userName, row['Consortium'], row['Organization']) 224 user = directory.getUser(userName) 225 user.setTagValue(row['AliasSavedUnder'], nodeAdminNamedTuple) 226 227 @given(u'the user "{userName}" collects signatures for ConfigUpdateEnvelope "{createChannelSignedConfigEnvelopeName}" from developers') 228 def step_impl(context, userName, createChannelSignedConfigEnvelopeName): 229 assert 'table' in context, "Expected table of peer organizations" 230 directory = bootstrap_util.getDirectory(context) 231 user = directory.getUser(userName=userName) 232 config_update_envelope = user.tags[createChannelSignedConfigEnvelopeName] 233 for row in context.table.rows: 234 user = directory.getUser(row['Developer']) 235 namedAdminTuple = user.tags[row['Cert Alias']] 236 cert = directory.findCertForNodeAdminTuple(namedAdminTuple) 237 # assert bootstrap_util.Network.Peer in org.networks, "Organization '{0}' not in Peer network".format(org.name) 238 bootstrap_util.BootstrapHelper.addSignatureToSignedConfigItem(config_update_envelope, (user, namedAdminTuple.organization, cert)) 239 # print("Signatures for signedConfigEnvelope:\n {0}\n".format(signedConfigEnvelope.Items[0])) 240 241 @given(u'the user "{userName}" creates a ConfigUpdate Tx "{configUpdateTxName}" using cert alias "{certAlias}" using signed ConfigUpdateEnvelope "{createChannelSignedConfigEnvelopeName}"') 242 def step_impl(context, userName, certAlias, configUpdateTxName, createChannelSignedConfigEnvelopeName): 243 directory = bootstrap_util.getDirectory(context) 244 user = directory.getUser(userName=userName) 245 namedAdminTuple = user.tags[certAlias] 246 cert = directory.findCertForNodeAdminTuple(namedAdminTuple) 247 config_update_envelope = user.tags[createChannelSignedConfigEnvelopeName] 248 config_update = bootstrap_util.getChannelIdFromConfigUpdateEnvelope(config_update_envelope) 249 envelope_for_config_update = bootstrap_util.createEnvelopeForMsg(directory=directory, 250 nodeAdminTuple=namedAdminTuple, 251 chainId=config_update.channel_id, 252 msg=config_update_envelope, 253 typeAsString="CONFIG_UPDATE") 254 user.setTagValue(configUpdateTxName, envelope_for_config_update) 255 256 @given(u'the user "{userName}" using cert alias "{certAlias}" broadcasts ConfigUpdate Tx "{configTxName}" to orderer "{orderer}"') 257 def step_impl(context, userName, certAlias, configTxName, orderer): 258 directory = bootstrap_util.getDirectory(context) 259 user = directory.getUser(userName=userName) 260 configTxEnvelope = user.tags[configTxName] 261 bootstrap_util.broadcastCreateChannelConfigTx(context=context,certAlias=certAlias, composeService=orderer, user=user, configTxEnvelope=configTxEnvelope) 262 263 @when(u'the user "{userName}" broadcasts transaction "{transactionAlias}" to orderer "{orderer}"') 264 def step_impl(context, userName, transactionAlias, orderer): 265 directory = bootstrap_util.getDirectory(context) 266 user = directory.getUser(userName=userName) 267 transaction = user.tags[transactionAlias] 268 bootstrap_util.broadcastCreateChannelConfigTx(context=context, certAlias=None, composeService=orderer, user=user, configTxEnvelope=transaction) 269 270 271 @when(u'user "{userName}" using cert alias "{certAlias}" connects to deliver function on orderer "{composeService}"') 272 @Given(u'user "{userName}" using cert alias "{certAlias}" connects to deliver function on orderer "{composeService}"') 273 def step_impl(context, userName, certAlias, composeService): 274 directory = bootstrap_util.getDirectory(context) 275 user = directory.getUser(userName=userName) 276 user.connectToDeliverFunction(context, composeService, nodeAdminTuple=user.tags[certAlias]) 277 278 @when(u'user "{userName}" sends deliver a seek request on orderer "{composeService}" with properties') 279 def step_impl(context, userName, composeService): 280 directory = bootstrap_util.getDirectory(context) 281 user = directory.getUser(userName=userName) 282 row = context.table.rows[0] 283 chainID = row['ChainId'] 284 start, end, = orderer_util.convertSeek(row['Start']), orderer_util.convertSeek(row['End']) 285 print("Start and end = {0}/{1}".format(start, end)) 286 print("") 287 streamHelper = user.getDelivererStreamHelper(context, composeService) 288 streamHelper.seekToRange(chainID=chainID, start = start, end = end) 289 290 @given(u'user "{userName}" retrieves the latest config update "{latest_config_name}" from orderer "{service_name}" for channel "{channel_id_or_ref}"') 291 def step_impl(context, userName, latest_config_name, service_name, channel_id_or_ref): 292 293 294 directory = bootstrap_util.getDirectory(context) 295 user = directory.getUser(userName=userName) 296 (channel_id,) = bootstrap_util.get_args_for_user([channel_id_or_ref], user) 297 streamHelper = user.getDelivererStreamHelper(context, service_name) 298 latest_config_block = bootstrap_util.get_latest_configuration_block(deliverer_stream_helper=streamHelper, channel_id=channel_id) 299 channel_group = bootstrap_util.get_channel_group_from_config_block(latest_config_block) 300 user.setTagValue(tagKey=latest_config_name, tagValue=channel_group) 301 # raise NotImplementedError(u'STEP: Given user "configAdminOrdererOrg0" retrieves the latest configuration "latestOrdererConfig" from orderer "orderer0" for channel "OrdererSystemChainId"') 302 303 @then(u'user "{userName}" should get a delivery "{deliveryName}" from "{composeService}" of "{expectedBlocks}" blocks with "{numMsgsToBroadcast}" messages within "{batchTimeout}" seconds') 304 def step_impl(context, userName, deliveryName, composeService, expectedBlocks, numMsgsToBroadcast, batchTimeout): 305 directory = bootstrap_util.getDirectory(context) 306 user = directory.getUser(userName=userName) 307 streamHelper = user.getDelivererStreamHelper(context, composeService) 308 309 blocks = streamHelper.getBlocks() 310 311 # Verify block count 312 assert len(blocks) == int(expectedBlocks), "Expected {0} blocks, received {1}".format(expectedBlocks, len(blocks)) 313 user.setTagValue(deliveryName, blocks) 314 315 @when(u'user "{userName}" using cert alias "{certAlias}" requests to join channel using genesis block "{genisisBlockName}" on peers with result "{joinChannelResult}"') 316 def step_impl(context, userName, certAlias, genisisBlockName, joinChannelResult): 317 timeout = 10 318 directory = bootstrap_util.getDirectory(context) 319 user = directory.getUser(userName) 320 nodeAdminTuple = user.tags[certAlias] 321 # Find the cert using the cert tuple information saved for the user under certAlias 322 signersCert = directory.findCertForNodeAdminTuple(nodeAdminTuple) 323 324 # Retrieve the genesis block from the returned value of deliver (Will be list with first block as genesis block) 325 genesisBlock = user.tags[genisisBlockName][0] 326 ccSpec = endorser_util.getChaincodeSpec("GOLANG", "", "cscc", ["JoinChain", genesisBlock.SerializeToString()]) 327 proposal = endorser_util.createInvokeProposalForBDD(context, ccSpec=ccSpec, chainID="",signersCert=signersCert, Mspid=user.tags[certAlias].organization, type="CONFIG") 328 signedProposal = endorser_util.signProposal(proposal=proposal, entity=user, signersCert=signersCert) 329 330 # Send proposal to each specified endorser, waiting 'timeout' seconds for response/error 331 endorsers = [row['Peer'] for row in context.table.rows] 332 proposalResponseFutures = [endorserStub.ProcessProposal.future(signedProposal, int(timeout)) for endorserStub in endorser_util.getEndorserStubs(context,composeServices=endorsers, directory=directory, nodeAdminTuple=nodeAdminTuple)] 333 resultsDict = dict(zip(endorsers, [respFuture.result() for respFuture in proposalResponseFutures])) 334 user.setTagValue(joinChannelResult, resultsDict) 335 336 337 @then(u'user "{userName}" expects result code for "{proposalResponseName}" of "{proposalResponseResultCode}" from peers') 338 def step_impl(context, userName, proposalResponseName, proposalResponseResultCode): 339 directory = bootstrap_util.getDirectory(context) 340 user = directory.getUser(userName=userName) 341 peerToProposalResponseDict = user.tags[proposalResponseName] 342 unexpectedResponses = [(composeService,proposalResponse) for composeService, proposalResponse in peerToProposalResponseDict.items() if proposalResponse.response.payload != proposalResponseResultCode] 343 print("ProposalResponse: \n{0}\n".format(proposalResponse)) 344 print("") 345 346 @given(u'the user "{userName}" creates an peer anchor set "{anchorSetName}" for orgs') 347 def step_impl(context, userName, anchorSetName): 348 directory = bootstrap_util.getDirectory(context) 349 user = directory.getUser(userName=userName) 350 nodeAdminTuples = [directory.findNodeAdminTuple(row['User'], row['Peer'], row['Organization']) for row in context.table.rows] 351 user.setTagValue(anchorSetName, bootstrap_util.getAnchorPeersConfigGroup(context=context, nodeAdminTuples=nodeAdminTuples)) 352 353 @given(u'we compose "{composeYamlFile}"') 354 def step_impl(context, composeYamlFile): 355 # time.sleep(10) # Should be replaced with a definitive interlock guaranteeing that all peers/membersrvc are ready 356 composition = compose.Composition(context, composeYamlFile) 357 context.compose_containers = composition.containerDataList 358 context.composition = composition 359 360 @given(u'I wait "{seconds}" seconds') 361 def step_impl(context, seconds): 362 time.sleep(float(seconds)) 363 364 @when(u'I wait "{seconds}" seconds') 365 def step_impl(context, seconds): 366 time.sleep(float(seconds)) 367 368 @then(u'I wait "{seconds}" seconds') 369 def step_impl(context, seconds): 370 time.sleep(float(seconds)) 371 372 @given(u'user "{userNameSource}" gives "{objectAlias}" to user "{userNameTarget}"') 373 def step_impl(context, userNameSource, objectAlias, userNameTarget): 374 directory = bootstrap_util.getDirectory(context) 375 userSource = directory.getUser(userName=userNameSource) 376 userTarget = directory.getUser(userName=userNameTarget) 377 userTarget.setTagValue(objectAlias, userSource.tags[objectAlias]) 378 379 @given(u'the ordererBootstrapAdmin creates a cert alias "{certAlias}" for orderer network bootstrap purposes for organizations') 380 def step_impl(context, certAlias): 381 assert "table" in context, "Expected table of Organizations" 382 directory = bootstrap_util.getDirectory(context) 383 ordererBootstrapAdmin = bootstrap_util.getOrdererBootstrapAdmin(context) 384 assert len(context.table.rows) == 1, "Only support single orderer orgnaization at moment" 385 for row in context.table.rows: 386 nodeAdminNamedTuple = directory.registerOrdererAdminTuple(ordererBootstrapAdmin.name, "ordererBootstrapAdmin", row['Organization']) 387 ordererBootstrapAdmin.setTagValue(certAlias, nodeAdminNamedTuple) 388 389 @given(u'we "{command}" service "{service_name}"') 390 def step_impl(context, command, service_name): 391 assert "composition" in context, "No composition found in context" 392 composition = context.composition 393 composition.issueCommand([command], [service_name])