Skip to content

Commit 73fc186

Browse files
committed
update backend logic for chaincode commit
Signed-off-by: YoungHypo <[email protected]>
1 parent ae81505 commit 73fc186

File tree

3 files changed

+180
-104
lines changed

3 files changed

+180
-104
lines changed

src/api-engine/api/lib/peer/chaincode.py

Lines changed: 89 additions & 67 deletions
Original file line numberDiff line numberDiff line change
@@ -118,7 +118,6 @@ def lifecycle_approve_for_my_org(self, orderer_url, channel_name, cc_name,
118118
The administrator can use the peer lifecycle chaincode approveformyorg subcommand to approve the chain code on
119119
behalf of the organization.
120120
:param orderer_url: orderer accessable url
121-
:param orderer_tls_rootcert: orderer tls certificate
122121
:param channel_name: channel name
123122
:param cc_name: chaincode name
124123
:param chaincode_version: chaincode version
@@ -215,96 +214,113 @@ def lifecycle_query_approved(self, channel_name, cc_name):
215214

216215
return return_code, chaincodes_info
217216

218-
def lifecycle_check_commit_readiness(self, orderer_url, orderer_tls_rootcert, channel_name, cc_name, cc_version,
219-
policy, sequence=1):
217+
def lifecycle_check_commit_readiness(self, channel_name, cc_name, cc_version, sequence=1):
220218
"""
221-
222-
:param orderer_url:orderer accessable url
223-
:param orderer_tls_rootcert:orderer tls certificate
224219
:param channel_name:channel name
225220
:param cc_name: chaincode name
226221
:param cc_version: chaincode version
227-
:param policy:chaincode policy
228222
:param sequence:The channel chain code defines the serial number. The default value is 1
229223
:return:
230224
"""
231225
try:
226+
ORDERER_CA = os.getenv("ORDERER_CA")
227+
command = []
232228
if os.getenv("CORE_PEER_TLS_ENABLED") == "false" or os.getenv("CORE_PEER_TLS_ENABLED") is None:
233-
res = subprocess.Popen("{} lifecycle chaincode checkcommitreadiness --output json "
234-
" --channelID {} --name {} --version {} --init-required --sequence {} "
235-
"--signature-policy {}"
236-
.format(self.peer, channel_name, cc_name, cc_version, sequence, policy),
237-
shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
238-
stdout, stderr = res.communicate()
239-
return_code = res.returncode
240-
if return_code == 0:
241-
content = str(stdout, encoding="utf-8")
242-
chaincodes_info = json.loads(content)
243-
return return_code, chaincodes_info
244-
else:
245-
stderr = str(stderr, encoding="utf-8")
246-
return return_code, stderr
229+
command = [
230+
self.peer,
231+
"lifecycle", "chaincode", "checkcommitreadiness",
232+
"--channelID", channel_name,
233+
"--name", cc_name,
234+
"--version", cc_version,
235+
"--sequence", str(sequence),
236+
"--output", "json",
237+
]
247238
else:
248-
res = subprocess.Popen("{} lifecycle chaincode checkcommitreadiness --output json "
249-
"-o {} --tls --cafile {} --channelID {} --name {} --version {} "
250-
"--signature-policy {} --init-required --sequence {}"
251-
.format(self.peer, orderer_url, orderer_tls_rootcert, channel_name, cc_name,
252-
cc_version, policy, sequence),
253-
shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
254-
stdout, stderr = res.communicate()
255-
return_code = res.returncode
256-
if return_code == 0:
257-
content = str(stdout, encoding="utf-8")
258-
chaincodes_info = json.loads(content)
259-
return return_code, chaincodes_info
260-
else:
261-
stderr = str(stderr, encoding="utf-8")
262-
return return_code, stderr
239+
command = [
240+
self.peer,
241+
"lifecycle", "chaincode", "checkcommitreadiness",
242+
"--channelID", channel_name,
243+
"--name", cc_name,
244+
"--version", cc_version,
245+
"--sequence", str(sequence),
246+
"--tls",
247+
"--cafile", ORDERER_CA,
248+
"--output", "json",
249+
]
250+
251+
LOG.info(" ".join(command))
252+
253+
res = subprocess.Popen(command, shell=False,
254+
stdout=subprocess.PIPE, stderr=subprocess.PIPE)
255+
stdout, stderr = res.communicate()
256+
return_code = res.returncode
257+
if return_code == 0:
258+
content = str(stdout, encoding="utf-8")
259+
chaincodes_info = json.loads(content)
260+
return return_code, chaincodes_info
261+
else:
262+
stderr = str(stderr, encoding="utf-8")
263+
return return_code, stderr
263264
except Exception as e:
264-
err_msg = "lifecycle_check_commit_readiness failed for {}!".format(
265-
e)
265+
err_msg = "lifecycle_check_commit_readiness failed for {}!".format(e)
266266
raise Exception(err_msg)
267267

268-
def lifecycle_commit(self, orderer_url, orderer_tls_rootcert, channel_name, cc_name, chaincode_version,
269-
policy, peerlist, peer_root_certs, sequency=1):
268+
def lifecycle_commit(self, orderer_url, channel_name, cc_name, chaincode_version, sequence, policy, peer_list=[], peer_root_certs=[], init_flag=False):
270269
"""
271270
The administrator can submit the chain code definition to the specified channel by using the peer lifecycle
272271
chain code commit subcommand
273272
:param orderer_url: orderer accessable url
274-
:param orderer_tls_rootcert:orderer tls certificate
275273
:param channel_name:channel name
276274
:param cc_name:chaincode name
277275
:param chaincode_version:chaincode version
276+
:param sequence:The channel chain code defines the serial number. The default value is 1
278277
:param policy:chaincode policy
279-
:param peerlist: the list of peerAddress
278+
:param peer_list: the list of peerAddress
280279
:param peer_root_certs: the list of peer_root_certs, the orderer should be same as peerlist's.
281-
:param sequency:The channel chain code defines the serial number. The default value is 1
280+
:param init_flag:if the chaincode is first init.
282281
:return:
283282
"""
284283
try:
285-
peer_addresses_format = " --peerAddresses {} --tlsRootCertFiles {}"
286-
command_str_with_tls = "{} lifecycle chaincode commit -o {} --tls --cafile {} " \
287-
"--channelID {} --name {} --version {} --init-required --sequence {} " \
288-
"--signature-policy {}"
289-
command_str_without_tls = "{} lifecycle chaincode commit -o {} --channelID {} --name {} " \
290-
"--version {} --init-required --sequence {} --signature-policy {}"
291-
292-
peer_addressed = []
293-
for i in range(len(peerlist)):
294-
peer_addressed.append(peerlist[i])
295-
peer_addressed.append(peer_root_certs[i])
284+
command = []
296285
if os.getenv("CORE_PEER_TLS_ENABLED") == "false" or os.getenv("CORE_PEER_TLS_ENABLED") is None:
297-
for i in range(len(peerlist)):
298-
command_str_without_tls = command_str_without_tls + peer_addresses_format
299-
res = os.system(command_str_without_tls.format(self.peer, orderer_url, channel_name, cc_name,
300-
chaincode_version, sequency, policy, *peer_addressed)) # --collections-config {}
286+
command = [
287+
self.peer,
288+
"lifecycle", "chaincode", "commit",
289+
"-o", orderer_url,
290+
"--channelID", channel_name,
291+
"--name", cc_name,
292+
"--version", chaincode_version,
293+
"--sequence", str(sequence),
294+
]
301295
else:
302-
for i in range(len(peerlist)):
303-
command_str_with_tls = command_str_with_tls + peer_addresses_format
304-
305-
res = os.system(command_str_with_tls.format(self.peer, orderer_url, orderer_tls_rootcert, channel_name,
306-
cc_name, chaincode_version, sequency, policy, *peer_addressed))
296+
ORDERER_CA = os.getenv("ORDERER_CA")
297+
command = [
298+
self.peer,
299+
"lifecycle", "chaincode", "commit",
300+
"-o", orderer_url,
301+
"--ordererTLSHostnameOverride", orderer_url.split(":")[0],
302+
"--channelID", channel_name,
303+
"--name", cc_name,
304+
"--version", chaincode_version,
305+
"--sequence", str(sequence),
306+
"--tls",
307+
"--cafile", ORDERER_CA,
308+
]
307309

310+
for i in range(len(peer_list)):
311+
command.append("--peerAddresses")
312+
command.append(peer_list[i])
313+
command.append("--tlsRootCertFiles")
314+
command.append(peer_root_certs[i])
315+
316+
if init_flag:
317+
command.append("--init-required")
318+
if policy:
319+
command.append("--signature-policy")
320+
command.append(policy)
321+
322+
LOG.info(" ".join(command))
323+
res = os.system(" ".join(command))
308324
res = res >> 8
309325
return res
310326

@@ -320,10 +336,16 @@ def lifecycle_query_committed(self, channel_name, cc_name):
320336
:return: chaincodes info has commited in channel of the cc_name
321337
"""
322338
try:
323-
res = subprocess.Popen("{} lifecycle chaincode querycommitted --channelID {} "
324-
"--output json --name {}".format(
325-
self.peer, channel_name, cc_name),
326-
shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
339+
command = [
340+
self.peer,
341+
"lifecycle", "chaincode", "querycommitted",
342+
"--channelID", channel_name,
343+
"--output", "json",
344+
"--name", cc_name,
345+
]
346+
LOG.info(" ".join(command))
347+
res = subprocess.Popen(command, shell=False,
348+
stdout=subprocess.PIPE, stderr=subprocess.PIPE)
327349
stdout, stderr = res.communicate()
328350
return_code = res.returncode
329351
if return_code == 0:

src/api-engine/api/routes/chaincode/serializers.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -68,4 +68,4 @@ class ChainCodeApproveForMyOrgBody(serializers.Serializer):
6868

6969

7070
class ChainCodeCommitBody(ChainCodeApproveForMyOrgBody):
71-
peer_list = serializers.ListField(allow_empty=False, required=True)
71+
pass

src/api-engine/api/routes/chaincode/views.py

Lines changed: 90 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,8 @@
1313
from api.config import CELLO_HOME
1414
from api.models import (
1515
Node,
16-
ChainCode
16+
ChainCode,
17+
Channel
1718
)
1819
from api.utils.common import make_uuid
1920
from django.core.paginator import Paginator
@@ -460,61 +461,114 @@ def commit(self, request):
460461
try:
461462
channel_name = serializer.validated_data.get("channel_name")
462463
chaincode_name = serializer.validated_data.get("chaincode_name")
463-
chaincode_version = serializer.validated_data.get(
464-
"chaincode_version")
464+
chaincode_version = serializer.validated_data.get("chaincode_version")
465465
policy = serializer.validated_data.get("policy")
466-
# Perhaps the orderer's port is best stored in the database
467-
orderer_url = serializer.validated_data.get("orderer_url")
468466
sequence = serializer.validated_data.get("sequence")
469-
peer_list = serializer.validated_data.get("peer_list")
467+
init_flag = serializer.validated_data.get("init_flag", False)
468+
470469
org = request.user.organization
471470
qs = Node.objects.filter(type="orderer", organization=org)
472471
if not qs.exists():
473472
raise ResourceNotFound
474473
orderer_node = qs.first()
474+
orderer_url = orderer_node.name + "." + org.name.split(".", 1)[1] + ":" + str(7050)
475475

476-
orderer_tls_dir = "{}/{}/crypto-config/ordererOrganizations/{}/orderers/{}/msp/tlscacerts" \
477-
.format(CELLO_HOME, org.name, org.name.split(".", 1)[1], orderer_node.name + "." +
478-
org.name.split(".", 1)[1])
479-
orderer_tls_root_cert = ""
480-
for _, _, files in os.walk(orderer_tls_dir):
481-
orderer_tls_root_cert = orderer_tls_dir + "/" + files[0]
482-
break
483-
476+
# Step 1: Check commit readiness, find all approved organizations
484477
qs = Node.objects.filter(type="peer", organization=org)
485478
if not qs.exists():
486479
raise ResourceNotFound
487480
peer_node = qs.first()
488481
envs = init_env_vars(peer_node, org)
489-
490-
peer_root_certs = []
482+
483+
peer_channel_cli = PeerChainCode(**envs)
484+
code, readiness_result = peer_channel_cli.lifecycle_check_commit_readiness(
485+
channel_name, chaincode_name, chaincode_version, sequence)
486+
if code != 0:
487+
return Response(err(f"Check commit readiness failed: {readiness_result}"),
488+
status=status.HTTP_400_BAD_REQUEST)
489+
490+
# Check approved status
491+
approvals = readiness_result.get("approvals", {})
492+
approved_orgs = [org_msp for org_msp, approved in approvals.items() if approved]
493+
if not approved_orgs:
494+
return Response(err("No organizations have approved this chaincode"),
495+
status=status.HTTP_400_BAD_REQUEST)
496+
497+
LOG.info(f"Approved organizations: {approved_orgs}")
498+
499+
# Step 2: Get channel organizations and peer nodes
500+
try:
501+
channel = Channel.objects.get(name=channel_name)
502+
channel_orgs = channel.organizations.all()
503+
except Channel.DoesNotExist:
504+
return Response(err(f"Channel {channel_name} not found"),
505+
status=status.HTTP_400_BAD_REQUEST)
506+
507+
# find the corresponding organization by MSP ID
508+
# MSP ID format: Org1MSP, Org2MSP -> organization name format: org1.xxx, org2.xxx
509+
approved_organizations = []
510+
for msp_id in approved_orgs:
511+
if msp_id.endswith("MSP"):
512+
org_prefix = msp_id[:-3].lower() # remove "MSP" and convert to lowercase
513+
# find the corresponding organization in the channel
514+
for channel_org in channel_orgs:
515+
if channel_org.name.split(".")[0] == org_prefix:
516+
approved_organizations.append(channel_org)
517+
LOG.info(f"Found approved organization: {channel_org.name} (MSP: {msp_id})")
518+
break
519+
520+
if not approved_organizations:
521+
return Response(err("No approved organizations found in this channel"),
522+
status=status.HTTP_400_BAD_REQUEST)
523+
524+
# get peer nodes and root certs
491525
peer_address_list = []
492-
for each in peer_list:
493-
peer_node = Node.objects.get(id=each)
494-
peer_tls_cert = "{}/{}/crypto-config/peerOrganizations/{}/peers/{}/tls/ca.crt" \
495-
.format(CELLO_HOME, org.name, org.name, peer_node.name + "." + org.name)
496-
print(peer_node.port)
497-
# port = peer_node.port.all()[0].internal
498-
# port = ports[0].internal
499-
peer_address = peer_node.name + \
500-
"." + org.name + ":" + str(7051)
501-
peer_address_list.append(peer_address)
502-
peer_root_certs.append(peer_tls_cert)
526+
peer_root_certs = []
527+
528+
for approved_org in approved_organizations:
529+
org_peer_nodes = Node.objects.filter(type="peer", organization=approved_org)
530+
if org_peer_nodes.exists():
531+
# select the first peer node for each organization
532+
peer = org_peer_nodes.first()
533+
peer_tls_cert = "{}/{}/crypto-config/peerOrganizations/{}/peers/{}/tls/ca.crt" \
534+
.format(CELLO_HOME, approved_org.name, approved_org.name,
535+
peer.name + "." + approved_org.name)
536+
peer_address = peer.name + "." + approved_org.name + ":" + str(7051)
537+
peer_address_list.append(peer_address)
538+
peer_root_certs.append(peer_tls_cert)
539+
LOG.info(f"Added peer from approved org {approved_org.name}: {peer_address}")
540+
else:
541+
LOG.warning(f"No peer nodes found for approved organization: {approved_org.name}")
503542

504-
peer_channel_cli = PeerChainCode(**envs)
505-
code = peer_channel_cli.lifecycle_commit(orderer_url, orderer_tls_root_cert, channel_name,
506-
chaincode_name, chaincode_version, policy,
507-
peer_address_list, peer_root_certs, sequence)
543+
if not peer_address_list:
544+
return Response(err("No peer nodes found for approved organizations"),
545+
status=status.HTTP_400_BAD_REQUEST)
546+
547+
# Step 3: Commit chaincode
548+
code = peer_channel_cli.lifecycle_commit(
549+
orderer_url, channel_name, chaincode_name, chaincode_version,
550+
sequence, policy, peer_address_list, peer_root_certs, init_flag)
508551
if code != 0:
509-
return Response(err("commit failed."), status=status.HTTP_400_BAD_REQUEST)
552+
return Response(err("Commit chaincode failed"),
553+
status=status.HTTP_400_BAD_REQUEST)
554+
555+
LOG.info(f"Chaincode {chaincode_name} committed successfully")
556+
557+
# Step 4: Query committed chaincode
558+
code, committed_result = peer_channel_cli.lifecycle_query_committed(
559+
channel_name, chaincode_name)
560+
if code == 0:
561+
LOG.info(committed_result)
562+
return Response(ok(committed_result), status=status.HTTP_200_OK)
563+
else:
564+
return Response(err("Query committed failed."), status=status.HTTP_400_BAD_REQUEST)
510565

511566
except Exception as e:
567+
LOG.error(f"Commit chaincode failed: {str(e)}")
512568
return Response(
513-
err(e.args), status=status.HTTP_400_BAD_REQUEST
569+
err(f"Commit chaincode failed: {str(e)}"),
570+
status=status.HTTP_400_BAD_REQUEST
514571
)
515-
return Response(
516-
ok("commit success."), status=status.HTTP_200_OK
517-
)
518572

519573
@swagger_auto_schema(
520574
method="get",

0 commit comments

Comments
 (0)