class UpdateStateResponse(ContractResponse): def __init__(self, request, response, **kwargs): super().__init__(request, response, **kwargs) self.state_changed = True self.request_number = request.request_number self.operation = 'update' self.signature = response['Signature'] # we have another mismatch between the field names in the enclave # and the field names expected in the transaction; this needs to # be fixed at some point for dependency in response['Dependencies']: contract_id = dependency['ContractID'] state_hash = dependency['StateHash'] self.dependencies.append({ 'contract_id': contract_id, 'state_hash': state_hash }) # save the information we will need for the transaction state_hash_b64 = response['StateHash'] self.new_state_hash = crypto.base64_to_byte_array(state_hash_b64) self.old_state_hash = ContractState.compute_state_hash( request.contract_state.raw_state) message = self.serialize_for_signing() if not self.verify_enclave_signature(message, request.enclave_keys): raise Exception('failed to verify enclave signature') self.raw_state = self.enclave_service.get_block(state_hash_b64) self.new_state_object = ContractState(self.contract_id, self.raw_state) self.new_state_object.pull_state_from_eservice(self.enclave_service) # compute ids of blocks in the change set (used for replication) self.new_state_object.compute_new_block_ids( request.contract_state.component_block_ids) self.replication_params = request.replication_params # ------------------------------------------------------- def serialize_for_signing(self): """serialize the response for enclave signature verification""" message = super().serialize_for_signing() message += self.old_state_hash message += self.new_state_hash for dependency in self.dependencies: message += crypto.string_to_byte_array(dependency['contract_id']) message += crypto.string_to_byte_array(dependency['state_hash']) return message
class InitializeStateResponse(ContractResponse): def __init__(self, request, response, **kwargs): super().__init__(request, response, **kwargs) self.state_changed = True self.request_number = request.request_number self.operation = 'initialize' self.metadata_hash = crypto.base64_to_byte_array( response['MetadataHash']) self.signature = response['Signature'] # save the information we will need for the transaction state_hash_b64 = response['StateHash'] self.new_state_hash = crypto.base64_to_byte_array(state_hash_b64) message = self.serialize_for_signing() if not self.verify_enclave_signature(message, request.enclave_keys): raise InvocationException('failed to verify enclave signature') self.raw_state = self.enclave_service.get_block(state_hash_b64) self.new_state_object = ContractState(self.contract_id, self.raw_state) self.new_state_object.pull_state_from_eservice(self.enclave_service) # compute ids of blocks in the change set (used for replication) self.new_state_object.compute_new_block_ids( request.contract_state.component_block_ids) self.replication_params = request.replication_params # ------------------------------------------------------- def serialize_for_signing(self): """serialize the response for enclave signature verification""" message = super().serialize_for_signing() message += crypto.string_to_byte_array(self.creator_id) message += self.metadata_hash message += self.new_state_hash return message