github.com/muhammedhassanm/blockchain@v0.0.0-20200120143007-697261defd4d/sawtooth-core-master/validator/sawtooth_validator/consensus/handlers.py (about) 1 # Copyright 2017 Intel Corporation 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 17 import logging 18 19 from google.protobuf.message import DecodeError 20 21 from sawtooth_validator.consensus.proxy import UnknownBlock 22 23 from sawtooth_validator.protobuf import consensus_pb2 24 from sawtooth_validator.protobuf import validator_pb2 25 26 from sawtooth_validator.networking.dispatch import Handler 27 from sawtooth_validator.networking.dispatch import HandlerResult 28 from sawtooth_validator.networking.dispatch import HandlerStatus 29 30 from sawtooth_validator.protobuf.consensus_pb2 import ConsensusSettingsEntry 31 from sawtooth_validator.protobuf.consensus_pb2 import ConsensusStateEntry 32 33 34 LOGGER = logging.getLogger(__name__) 35 36 37 class BlockEmpty(Exception): 38 """There are no batches in the block.""" 39 40 41 class BlockInProgress(Exception): 42 """There is already a block in progress.""" 43 44 45 class BlockNotInitialized(Exception): 46 """There is no block in progress to finalize.""" 47 48 49 class ConsensusServiceHandler(Handler): 50 def __init__( 51 self, 52 request_class, 53 request_type, 54 response_class, 55 response_type, 56 ): 57 self._request_class = request_class 58 self._request_type = request_type 59 self._response_class = response_class 60 self._response_type = response_type 61 62 def handle_request(self, request, response): 63 raise NotImplementedError() 64 65 @property 66 def request_class(self): 67 return self._request_class 68 69 @property 70 def response_class(self): 71 return self._response_class 72 73 @property 74 def response_type(self): 75 return self._response_type 76 77 @property 78 def request_type(self): 79 return self._request_type 80 81 def handle(self, connection_id, message_content): 82 request = self._request_class() 83 response = self._response_class() 84 response.status = response.OK 85 86 try: 87 request.ParseFromString(message_content) 88 except DecodeError: 89 response.status = response.BAD_REQUEST 90 else: 91 self.handle_request(request, response) 92 93 return HandlerResult( 94 status=HandlerStatus.RETURN, 95 message_out=response, 96 message_type=self._response_type) 97 98 99 class ConsensusRegisterHandler(ConsensusServiceHandler): 100 def __init__(self, proxy): 101 super().__init__( 102 consensus_pb2.ConsensusRegisterRequest, 103 validator_pb2.Message.CONSENSUS_REGISTER_REQUEST, 104 consensus_pb2.ConsensusRegisterResponse, 105 validator_pb2.Message.CONSENSUS_REGISTER_RESPONSE) 106 107 self._proxy = proxy 108 109 def handle_request(self, request, response): 110 chain_head, peers = self._proxy.register() 111 112 if chain_head is None: 113 response.status = consensus_pb2.ConsensusRegisterResponse.NOT_READY 114 return 115 116 response.chain_head.block_id = bytes.fromhex(chain_head.identifier) 117 response.chain_head.previous_id =\ 118 bytes.fromhex(chain_head.previous_block_id) 119 response.chain_head.signer_id =\ 120 bytes.fromhex(chain_head.signer_public_key) 121 response.chain_head.block_num = chain_head.block_num 122 response.chain_head.payload = chain_head.consensus 123 124 response.peers.extend(peers) 125 126 LOGGER.info( 127 "Consensus engine registered: %s %s", 128 request.name, 129 request.version) 130 131 132 class ConsensusSendToHandler(ConsensusServiceHandler): 133 def __init__(self, proxy): 134 super().__init__( 135 consensus_pb2.ConsensusSendToRequest, 136 validator_pb2.Message.CONSENSUS_SEND_TO_REQUEST, 137 consensus_pb2.ConsensusSendToResponse, 138 validator_pb2.Message.CONSENSUS_SEND_TO_RESPONSE) 139 self._proxy = proxy 140 141 def handle_request(self, request, response): 142 try: 143 self._proxy.send_to( 144 request.peer_id, 145 request.message.SerializeToString()) 146 except Exception: # pylint: disable=broad-except 147 LOGGER.exception("ConsensusSendTo") 148 response.status =\ 149 consensus_pb2.ConsensusSendToResponse.SERVICE_ERROR 150 151 152 class ConsensusBroadcastHandler(ConsensusServiceHandler): 153 def __init__(self, proxy): 154 super().__init__( 155 consensus_pb2.ConsensusBroadcastRequest, 156 validator_pb2.Message.CONSENSUS_BROADCAST_REQUEST, 157 consensus_pb2.ConsensusBroadcastResponse, 158 validator_pb2.Message.CONSENSUS_BROADCAST_RESPONSE) 159 160 self._proxy = proxy 161 162 def handle_request(self, request, response): 163 try: 164 self._proxy.broadcast(request.message.SerializeToString()) 165 except Exception: # pylint: disable=broad-except 166 LOGGER.exception("ConsensusBroadcast") 167 response.status =\ 168 consensus_pb2.ConsensusBroadcastResponse.SERVICE_ERROR 169 170 171 class ConsensusInitializeBlockHandler(ConsensusServiceHandler): 172 def __init__(self, proxy): 173 super().__init__( 174 consensus_pb2.ConsensusInitializeBlockRequest, 175 validator_pb2.Message.CONSENSUS_INITIALIZE_BLOCK_REQUEST, 176 consensus_pb2.ConsensusInitializeBlockResponse, 177 validator_pb2.Message.CONSENSUS_INITIALIZE_BLOCK_RESPONSE) 178 179 self._proxy = proxy 180 181 def handle_request(self, request, response): 182 try: 183 self._proxy.initialize_block(request.previous_id) 184 except BlockInProgress: 185 response.status =\ 186 consensus_pb2.ConsensusInitializeBlockResponse.INVALID_STATE 187 except Exception: # pylint: disable=broad-except 188 LOGGER.exception("ConsensusInitializeBlock") 189 response.status =\ 190 consensus_pb2.ConsensusInitializeBlockResponse.SERVICE_ERROR 191 192 193 class ConsensusSummarizeBlockHandler(ConsensusServiceHandler): 194 def __init__(self, proxy): 195 super().__init__( 196 consensus_pb2.ConsensusSummarizeBlockRequest, 197 validator_pb2.Message.CONSENSUS_SUMMARIZE_BLOCK_REQUEST, 198 consensus_pb2.ConsensusSummarizeBlockResponse, 199 validator_pb2.Message.CONSENSUS_SUMMARIZE_BLOCK_RESPONSE) 200 201 self._proxy = proxy 202 203 def handle_request(self, request, response): 204 try: 205 summary = self._proxy.summarize_block() 206 response.summary = summary 207 except BlockNotInitialized: 208 response.status =\ 209 consensus_pb2.ConsensusSummarizeBlockResponse.INVALID_STATE 210 except BlockEmpty: 211 response.status =\ 212 consensus_pb2.ConsensusSummarizeBlockResponse.BLOCK_NOT_READY 213 except Exception: # pylint: disable=broad-except 214 LOGGER.exception("ConsensusSummarizeBlock") 215 response.status =\ 216 consensus_pb2.ConsensusSummarizeBlockResponse.SERVICE_ERROR 217 218 219 class ConsensusFinalizeBlockHandler(ConsensusServiceHandler): 220 def __init__(self, proxy): 221 super().__init__( 222 consensus_pb2.ConsensusFinalizeBlockRequest, 223 validator_pb2.Message.CONSENSUS_FINALIZE_BLOCK_REQUEST, 224 consensus_pb2.ConsensusFinalizeBlockResponse, 225 validator_pb2.Message.CONSENSUS_FINALIZE_BLOCK_RESPONSE) 226 227 self._proxy = proxy 228 229 def handle_request(self, request, response): 230 try: 231 response.block_id = self._proxy.finalize_block(request.data) 232 except BlockNotInitialized: 233 response.status =\ 234 consensus_pb2.ConsensusFinalizeBlockResponse.INVALID_STATE 235 except BlockEmpty: 236 response.status =\ 237 consensus_pb2.ConsensusFinalizeBlockResponse.BLOCK_NOT_READY 238 except Exception: # pylint: disable=broad-except 239 LOGGER.exception("ConsensusFinalizeBlock") 240 response.status =\ 241 consensus_pb2.ConsensusFinalizeBlockResponse.SERVICE_ERROR 242 243 244 class ConsensusCancelBlockHandler(ConsensusServiceHandler): 245 def __init__(self, proxy): 246 super().__init__( 247 consensus_pb2.ConsensusCancelBlockRequest, 248 validator_pb2.Message.CONSENSUS_CANCEL_BLOCK_REQUEST, 249 consensus_pb2.ConsensusCancelBlockResponse, 250 validator_pb2.Message.CONSENSUS_CANCEL_BLOCK_RESPONSE) 251 252 self._proxy = proxy 253 254 def handle_request(self, request, response): 255 try: 256 self._proxy.cancel_block() 257 except BlockNotInitialized: 258 response.status =\ 259 consensus_pb2.ConsensusCancelBlockResponse.INVALID_STATE 260 except Exception: # pylint: disable=broad-except 261 LOGGER.exception("ConsensusCancelBlock") 262 response.status =\ 263 consensus_pb2.ConsensusCancelBlockResponse.SERVICE_ERROR 264 265 266 class ConsensusCheckBlocksHandler(ConsensusServiceHandler): 267 def __init__(self, proxy): 268 super().__init__( 269 consensus_pb2.ConsensusCheckBlocksRequest, 270 validator_pb2.Message.CONSENSUS_CHECK_BLOCKS_REQUEST, 271 consensus_pb2.ConsensusCheckBlocksResponse, 272 validator_pb2.Message.CONSENSUS_CHECK_BLOCKS_RESPONSE) 273 274 self._proxy = proxy 275 276 def handle_request(self, request, response): 277 try: 278 self._proxy.check_blocks(request.block_ids) 279 except UnknownBlock: 280 response.status =\ 281 consensus_pb2.ConsensusCheckBlocksResponse.UNKNOWN_BLOCK 282 except Exception: # pylint: disable=broad-except 283 LOGGER.exception("ConsensusCheckBlocks") 284 response.status =\ 285 consensus_pb2.ConsensusCheckBlocksResponse.SERVICE_ERROR 286 287 288 class ConsensusCommitBlockHandler(ConsensusServiceHandler): 289 def __init__(self, proxy): 290 super().__init__( 291 consensus_pb2.ConsensusCommitBlockRequest, 292 validator_pb2.Message.CONSENSUS_COMMIT_BLOCK_REQUEST, 293 consensus_pb2.ConsensusCommitBlockResponse, 294 validator_pb2.Message.CONSENSUS_COMMIT_BLOCK_RESPONSE) 295 296 self._proxy = proxy 297 298 def handle_request(self, request, response): 299 try: 300 self._proxy.commit_block(request.block_id) 301 except UnknownBlock: 302 response.status =\ 303 consensus_pb2.ConsensusCommitBlockResponse.UNKNOWN_BLOCK 304 except Exception: # pylint: disable=broad-except 305 LOGGER.exception("ConsensusCommitBlock") 306 response.status =\ 307 consensus_pb2.ConsensusCommitBlockResponse.SERVICE_ERROR 308 309 310 class ConsensusIgnoreBlockHandler(ConsensusServiceHandler): 311 def __init__(self, proxy): 312 super().__init__( 313 consensus_pb2.ConsensusIgnoreBlockRequest, 314 validator_pb2.Message.CONSENSUS_IGNORE_BLOCK_REQUEST, 315 consensus_pb2.ConsensusIgnoreBlockResponse, 316 validator_pb2.Message.CONSENSUS_IGNORE_BLOCK_RESPONSE) 317 318 self._proxy = proxy 319 320 def handle_request(self, request, response): 321 try: 322 self._proxy.ignore_block(request.block_id) 323 except UnknownBlock: 324 response.status =\ 325 consensus_pb2.ConsensusIgnoreBlockResponse.UNKNOWN_BLOCK 326 except Exception: # pylint: disable=broad-except 327 LOGGER.exception("ConsensusIgnoreBlock") 328 response.status =\ 329 consensus_pb2.ConsensusIgnoreBlockResponse.SERVICE_ERROR 330 331 332 class ConsensusFailBlockHandler(ConsensusServiceHandler): 333 def __init__(self, proxy): 334 super().__init__( 335 consensus_pb2.ConsensusFailBlockRequest, 336 validator_pb2.Message.CONSENSUS_FAIL_BLOCK_REQUEST, 337 consensus_pb2.ConsensusFailBlockResponse, 338 validator_pb2.Message.CONSENSUS_FAIL_BLOCK_RESPONSE) 339 340 self._proxy = proxy 341 342 def handle_request(self, request, response): 343 try: 344 self._proxy.fail_block(request.block_id) 345 except UnknownBlock: 346 response.status =\ 347 consensus_pb2.ConsensusFailBlockResponse.UNKNOWN_BLOCK 348 except Exception: # pylint: disable=broad-except 349 LOGGER.exception("ConsensusFailBlock") 350 response.status =\ 351 consensus_pb2.ConsensusFailBlockResponse.SERVICE_ERROR 352 353 354 class ConsensusBlocksGetHandler(ConsensusServiceHandler): 355 def __init__(self, proxy): 356 super().__init__( 357 consensus_pb2.ConsensusBlocksGetRequest, 358 validator_pb2.Message.CONSENSUS_BLOCKS_GET_REQUEST, 359 consensus_pb2.ConsensusBlocksGetResponse, 360 validator_pb2.Message.CONSENSUS_BLOCKS_GET_RESPONSE) 361 362 self._proxy = proxy 363 364 def handle_request(self, request, response): 365 try: 366 response.blocks.extend([ 367 consensus_pb2.ConsensusBlock( 368 block_id=bytes.fromhex(block.identifier), 369 previous_id=bytes.fromhex(block.previous_block_id), 370 signer_id=bytes.fromhex(block.signer_public_key), 371 block_num=block.block_num, 372 payload=block.consensus) 373 for block in self._proxy.blocks_get(request.block_ids) 374 ]) 375 except UnknownBlock: 376 response.status =\ 377 consensus_pb2.ConsensusBlocksGetResponse.UNKNOWN_BLOCK 378 except Exception: # pylint: disable=broad-except 379 LOGGER.exception("ConsensusBlocksGet") 380 response.status =\ 381 consensus_pb2.ConsensusBlocksGetResponse.SERVICE_ERROR 382 383 384 class ConsensusChainHeadGetHandler(ConsensusServiceHandler): 385 def __init__(self, proxy): 386 super().__init__( 387 consensus_pb2.ConsensusChainHeadGetRequest, 388 validator_pb2.Message.CONSENSUS_CHAIN_HEAD_GET_REQUEST, 389 consensus_pb2.ConsensusChainHeadGetResponse, 390 validator_pb2.Message.CONSENSUS_CHAIN_HEAD_GET_RESPONSE) 391 392 self._proxy = proxy 393 394 def handle_request(self, request, response): 395 try: 396 chain_head = self._proxy.chain_head_get() 397 response.block.block_id = bytes.fromhex(chain_head.identifier) 398 response.block.previous_id =\ 399 bytes.fromhex(chain_head.previous_block_id) 400 response.block.signer_id =\ 401 bytes.fromhex(chain_head.signer_public_key) 402 response.block.block_num = chain_head.block_num 403 response.block.payload = chain_head.consensus 404 except UnknownBlock: 405 response.status =\ 406 consensus_pb2.ConsensusChainHeadGetResponse.NO_CHAIN_HEAD 407 except Exception: # pylint: disable=broad-except 408 LOGGER.exception("ConsensusChainHeadGet") 409 response.status =\ 410 consensus_pb2.ConsensusChainHeadGetResponse.SERVICE_ERROR 411 412 413 class ConsensusSettingsGetHandler(ConsensusServiceHandler): 414 def __init__(self, proxy): 415 super().__init__( 416 consensus_pb2.ConsensusSettingsGetRequest, 417 validator_pb2.Message.CONSENSUS_SETTINGS_GET_REQUEST, 418 consensus_pb2.ConsensusSettingsGetResponse, 419 validator_pb2.Message.CONSENSUS_SETTINGS_GET_RESPONSE) 420 421 self._proxy = proxy 422 423 def handle_request(self, request, response): 424 try: 425 response.entries.extend([ 426 ConsensusSettingsEntry( 427 key=key, 428 value=value) 429 for key, value in self._proxy.settings_get( 430 request.block_id, request.keys) 431 ]) 432 except UnknownBlock: 433 response.status = \ 434 consensus_pb2.ConsensusSettingsGetResponse.UNKNOWN_BLOCK 435 except Exception: # pylint: disable=broad-except 436 LOGGER.exception("ConsensusSettingsGet") 437 response.status =\ 438 consensus_pb2.ConsensusSettingsGetResponse.SERVICE_ERROR 439 440 441 class ConsensusStateGetHandler(ConsensusServiceHandler): 442 def __init__(self, proxy): 443 super().__init__( 444 consensus_pb2.ConsensusStateGetRequest, 445 validator_pb2.Message.CONSENSUS_STATE_GET_REQUEST, 446 consensus_pb2.ConsensusStateGetResponse, 447 validator_pb2.Message.CONSENSUS_STATE_GET_RESPONSE) 448 449 self._proxy = proxy 450 451 def handle_request(self, request, response): 452 try: 453 response.entries.extend([ 454 ConsensusStateEntry( 455 address=address, 456 data=data) 457 for address, data in self._proxy.state_get( 458 request.block_id, request.addresses) 459 ]) 460 except UnknownBlock: 461 response.status = \ 462 consensus_pb2.ConsensusStateGetResponse.UNKNOWN_BLOCK 463 except Exception: # pylint: disable=broad-except 464 LOGGER.exception("ConsensusStateGet") 465 response.status =\ 466 consensus_pb2.ConsensusStateGetResponse.SERVICE_ERROR