Skip to content

Commit 9ff202a

Browse files
committed
Make chaincode installation and approvement as separate APIs
Signed-off-by: dodo920306 <dodo920306@gmail.com>
1 parent 8f627bb commit 9ff202a

File tree

3 files changed

+197
-105
lines changed

3 files changed

+197
-105
lines changed

src/api-engine/chaincode/serializers.py

Lines changed: 26 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,14 @@
11
import tarfile
2-
from typing import List
2+
from typing import List, Dict, Any
33

44
from django.core.validators import MinValueValidator
55
from rest_framework import serializers
66
from chaincode.models import Chaincode
7-
from chaincode.service import create_chaincode, get_metadata
7+
from chaincode.service import create_chaincode, get_metadata, install_chaincode, approve_chaincode, commit_chaincode
88
from channel.models import Channel
99
from channel.serializers import ChannelID
1010
from common.serializers import ListResponseSerializer
1111
from node.models import Node
12-
from node.serializers import NodeID
1312
from user.serializers import UserID
1413

1514

@@ -107,7 +106,30 @@ def validate_peers(self, value: List[Node]):
107106
)
108107
return value
109108

110-
def create(self, validated_data) -> ChaincodeID:
109+
def create(self, validated_data: Dict[str, Any]) -> ChaincodeID:
111110
validated_data["user"] = self.context["user"]
112111
validated_data["organization"] = self.context["organization"]
113112
return ChaincodeID({"id": create_chaincode(**validated_data).id})
113+
114+
115+
class ChaincodeInstallBody(ChaincodeID):
116+
def update(self, instance: Chaincode, validated_data: Dict[str, Any]):
117+
install_chaincode(
118+
self.context["organization"],
119+
instance
120+
)
121+
122+
123+
class ChaincodeApproveBody(ChaincodeID):
124+
def update(self, instance: Chaincode, validated_data: Dict[str, Any]):
125+
approve_chaincode(
126+
self.context["organization"],
127+
instance
128+
)
129+
130+
class ChaincodeCommitBody(ChaincodeID):
131+
def update(self, instance: Chaincode, validated_data: Dict[str, Any]):
132+
commit_chaincode(
133+
self.context["organization"],
134+
instance
135+
)

src/api-engine/chaincode/service.py

Lines changed: 140 additions & 99 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
import os
55
import subprocess
66
import tarfile
7-
from typing import Optional, List, Any, Dict
7+
from typing import Optional, List, Any, Dict, Tuple
88

99
from django.db import transaction
1010

@@ -50,35 +50,14 @@ def create_chaincode(
5050
chaincode.save()
5151
chaincode.peers.add(*peers)
5252

53-
peer_root_certs: list[str] = []
54-
peer_addresses: list[str] = []
55-
peer_envs: list[map[str, str]] = []
56-
for peer in peers:
57-
peer_root_cert, peer_address, peer_env = get_peer_root_cert_and_address_and_envs(organization.name, peer.name)
58-
peer_root_certs.append(peer_root_cert)
59-
peer_addresses.append(peer_address)
60-
peer_envs.append(peer_env)
53+
peer_root_certs, peer_addresses, peer_envs = get_peers_root_certs_and_addresses_and_envs(
54+
organization.name,
55+
peers
56+
)
6157

6258
set_chaincode_package_id(peer_envs[0], chaincode)
6359
install_chaincode_with_envs(peer_envs, chaincode)
64-
65-
command[3] = "commit"
66-
# Remove package ID
67-
del command[14:16]
68-
for i in range(len(peers)):
69-
command.extend(["--peerAddresses", peer_addresses[i], "--tlsRootCertFiles", peer_root_certs[i]])
70-
71-
LOG.info(" ".join(command))
72-
for peer_env in peer_envs:
73-
subprocess.run(
74-
command,
75-
env=peer_env,
76-
check=True)
77-
78-
with transaction.atomic():
79-
chaincode.status = Chaincode.Status.COMMITTED
80-
chaincode.save()
81-
60+
approve_chaincode_with_envs(peer_envs[0], organization, chaincode)
8261
return chaincode
8362

8463
def get_metadata(file) -> Optional[Dict[str, Any]]:
@@ -96,21 +75,73 @@ def get_metadata(file) -> Optional[Dict[str, Any]]:
9675
file.seek(0)
9776
return res
9877

99-
def install_chaincode(organization: Organization, chaincode: Chaincode):
100-
peer_envs: list[map[str, str]] = []
101-
for peer in chaincode.peers:
102-
peer_envs.append(get_peer_root_cert_and_address_and_envs(organization.name, peer.name)[2])
78+
def install_chaincode(organization: Organization, chaincode: Chaincode) -> None:
79+
peer_envs: List[Dict[str, str]] = get_peers_root_certs_and_addresses_and_envs(
80+
organization.name,
81+
chaincode.peers
82+
)[2]
10383

10484
if chaincode.package_id is None:
10585
set_chaincode_package_id(peer_envs[0], chaincode)
10686

10787
install_chaincode_with_envs(peer_envs, chaincode)
10888

89+
def set_chaincode_package_id(peer_env: Dict[str, str], chaincode: Chaincode) -> None:
90+
command: List[str] = [
91+
peer_command,
92+
"lifecycle",
93+
"chaincode",
94+
"calculatepackageid",
95+
chaincode.package.path
96+
]
97+
LOG.info(" ".join(command))
98+
with transaction.atomic():
99+
chaincode.package_id = subprocess.run(
100+
command,
101+
env=peer_env,
102+
check=True,
103+
capture_output=True,
104+
text=True
105+
).stdout
106+
chaincode.save()
107+
108+
def install_chaincode_with_envs(peer_envs: List[Dict[str, str]], chaincode: Chaincode) -> None:
109+
command = [
110+
peer_command,
111+
"lifecycle",
112+
"chaincode",
113+
"install",
114+
chaincode.package.path,
115+
]
116+
LOG.info(" ".join(command))
117+
for peer_env in peer_envs:
118+
subprocess.run(
119+
command,
120+
env=peer_env,
121+
check=True)
122+
123+
with transaction.atomic():
124+
chaincode.status = Chaincode.Status.INSTALLED
125+
chaincode.save()
126+
109127
def approve_chaincode(
110-
peer_envs: list[dict[str, str]],
111-
channel_name: str,
112-
organization: Organization,
113-
chaincode: Chaincode):
128+
organization: Organization,
129+
chaincode: Chaincode) -> None:
130+
approve_chaincode_with_envs(
131+
get_peers_root_certs_and_addresses_and_envs(
132+
organization.name,
133+
[chaincode.peers[0]] # type: ignore
134+
)[2][0],
135+
organization,
136+
chaincode
137+
)
138+
139+
def approve_chaincode_with_envs(
140+
peer_env: Dict[str, str],
141+
organization: Organization,
142+
chaincode: Chaincode) -> None:
143+
# Chaincode is approved at the organization level,
144+
# so the command only needs to target one peer.
114145
orderer_domain_name = get_domain_name(
115146
organization.name,
116147
Node.Type.ORDERER,
@@ -126,7 +157,7 @@ def approve_chaincode(
126157
"--ordererTLSHostnameOverride",
127158
orderer_domain_name,
128159
"--channelID",
129-
channel_name,
160+
chaincode.channel.name,
130161
"--name",
131162
chaincode.name,
132163
"--version",
@@ -148,69 +179,63 @@ def approve_chaincode(
148179
command.extend(["--signature-policy", chaincode.signature_policy])
149180

150181
LOG.info(" ".join(command))
151-
for peer_env in peer_envs:
152-
subprocess.run(
153-
command,
154-
env=peer_env,
155-
check=True)
182+
subprocess.run(
183+
command,
184+
env=peer_env,
185+
check=True)
156186

157187
with transaction.atomic():
158188
chaincode.status = Chaincode.Status.APPROVED
159189
chaincode.save()
160190

161-
def get_peer_root_cert_and_address_and_envs(organization_name: str, peer_name: str) -> tuple[str, str, map[str, str]]:
162-
peer_domain_name: str = get_domain_name(organization_name, Node.Type.PEER, peer_name)
163-
peer_dir: str = get_peer_directory(organization_name, peer_domain_name)
164-
peer_root_cert: str = os.path.join(peer_dir, "tls/ca.crt")
165-
peer_address: str = "{}:7051".format(peer_domain_name)
166-
return peer_root_cert, peer_address, {
167-
"CORE_PEER_TLS_ENABLED": "true",
168-
"CORE_PEER_LOCALMSPID": "{}MSP".format(organization_name.split(".", 1)[0].capitalize()),
169-
"CORE_PEER_TLS_ROOTCERT_FILE": peer_root_cert,
170-
"CORE_PEER_MSPCONFIGPATH": "{}/users/Admin@{}/msp".format(
171-
get_org_directory(organization_name, Node.Type.PEER),
172-
organization_name
173-
),
174-
"CORE_PEER_ADDRESS": peer_address,
175-
"FABRIC_CFG_PATH": peer_dir,
176-
}
177-
178-
def set_chaincode_package_id(peer_env: dict[str, str], chaincode: Chaincode):
179-
command: list[str] = [
180-
peer_command,
181-
"lifecycle",
182-
"chaincode",
183-
"calculatepackageid",
184-
chaincode.package.path
185-
]
186-
LOG.info(" ".join(command))
187-
with transaction.atomic():
188-
chaincode.package_id = subprocess.run(
189-
command,
190-
env=peer_env,
191-
check=True,
192-
capture_output=True,
193-
text=True
194-
).stdout
195-
chaincode.save()
196191

197-
def install_chaincode_with_envs(peer_envs: list[dict[str, str]], chaincode: Chaincode):
192+
def commit_chaincode(
193+
organization: Organization,
194+
chaincode: Chaincode) -> None:
195+
peer_root_certs, peer_addresses, peer_envs = get_peers_root_certs_and_addresses_and_envs(
196+
organization.name,
197+
chaincode.peers
198+
)
199+
orderer_domain_name = get_domain_name(
200+
organization.name,
201+
Node.Type.ORDERER,
202+
Node.objects.filter(type=Node.Type.ORDERER, organization=organization).first().name
203+
)
198204
command = [
199205
peer_command,
200206
"lifecycle",
201207
"chaincode",
202-
"install",
203-
chaincode.package.path,
208+
"commit",
209+
"-o",
210+
"{}:7050".format(orderer_domain_name),
211+
"--ordererTLSHostnameOverride",
212+
orderer_domain_name,
213+
"--channelID",
214+
chaincode.channel.name,
215+
"--name",
216+
chaincode.name,
217+
"--version",
218+
chaincode.version,
219+
"--sequence",
220+
str(chaincode.sequence),
221+
"--tls",
222+
"--cafile",
223+
"{}/msp/tlscacerts/tlsca.{}-cert.pem".format(
224+
get_orderer_directory(organization.name, orderer_domain_name),
225+
organization.name.split(".", 1)[1],
226+
)
204227
]
228+
for i in range(len(chaincode.peers)):
229+
command.extend(["--peerAddresses", peer_addresses[i], "--tlsRootCertFiles", peer_root_certs[i]])
230+
205231
LOG.info(" ".join(command))
206-
for peer_env in peer_envs:
207-
subprocess.run(
208-
command,
209-
env=peer_env,
210-
check=True)
232+
subprocess.run(
233+
command,
234+
env=peer_envs[0],
235+
check=True)
211236

212237
with transaction.atomic():
213-
chaincode.status = Chaincode.Status.INSTALLED
238+
chaincode.status = Chaincode.Status.COMMITTED
214239
chaincode.save()
215240

216241
class ChaincodeAction(Enum):
@@ -225,14 +250,12 @@ def send_chaincode_request(
225250
action: ChaincodeAction,
226251
function: str,
227252
*args: str):
228-
peer_organization_name = organization.name.split(".", 1)[0].capitalize()
229-
peer_msp = "{}MSP".format(peer_organization_name)
230-
peer_domain_name = get_domain_name(organization.name, Node.Type.PEER, peer.name)
231-
peer_dir = get_peer_directory(organization.name, peer_domain_name)
232-
peer_root_cert = os.path.join(peer_dir, "tls/ca.crt")
233-
peer_address = "{}:7051".format(peer_domain_name)
253+
peer_env: Dict[str, str] = get_peers_root_certs_and_addresses_and_envs(
254+
organization.name,
255+
[peer] # type: ignore
256+
)[2][0]
234257
command = [
235-
"go",
258+
"go",
236259
"run",
237260
os.path.join(CELLO_HOME, "chaincode", "application-gateway", "main.go"),
238261
action.name,
@@ -243,16 +266,34 @@ def send_chaincode_request(
243266
subprocess.run(
244267
command,
245268
env={
269+
**peer_env,
270+
"CHANNEL_NAME": channel.name,
271+
"CHAINCODE_NAME": chaincode.name
272+
},
273+
check=True)
274+
275+
def get_peers_root_certs_and_addresses_and_envs(
276+
organization_name: str,
277+
peers: List[Node]) -> Tuple[List[str], List[str], List[Dict[str, str]]]:
278+
peer_root_certs: List[str] = []
279+
peer_addresses: List[str] = []
280+
peer_envs: List[Dict[str, str]] = []
281+
for peer_name in [peer.name for peer in peers]:
282+
peer_domain_name: str = get_domain_name(organization_name, Node.Type.PEER, peer_name)
283+
peer_dir: str = get_peer_directory(organization_name, peer_domain_name)
284+
peer_root_cert: str = os.path.join(peer_dir, "tls/ca.crt")
285+
peer_address: str = "{}:7051".format(peer_domain_name)
286+
peer_root_certs.append(peer_root_cert)
287+
peer_addresses.append(peer_address)
288+
peer_envs.append({
246289
"CORE_PEER_TLS_ENABLED": "true",
247-
"CORE_PEER_LOCALMSPID": peer_msp,
290+
"CORE_PEER_LOCALMSPID": "{}MSP".format(organization_name.split(".", 1)[0].capitalize()),
248291
"CORE_PEER_TLS_ROOTCERT_FILE": peer_root_cert,
249292
"CORE_PEER_MSPCONFIGPATH": "{}/users/Admin@{}/msp".format(
250-
get_org_directory(organization.name, Node.Type.PEER),
251-
organization.name
293+
get_org_directory(organization_name, Node.Type.PEER),
294+
organization_name
252295
),
253296
"CORE_PEER_ADDRESS": peer_address,
254297
"FABRIC_CFG_PATH": peer_dir,
255-
"CHANNEL_NAME": channel.name,
256-
"CHAINCODE_NAME": chaincode.name
257-
},
258-
check=True)
298+
})
299+
return peer_root_certs, peer_addresses, peer_envs

0 commit comments

Comments
 (0)