async def submit_batches(self, request): """Accepts a binary encoded BatchList and submits it to the validator. Request: body: octet-stream BatchList of one or more Batches Response: status: - 202: Batches submitted and pending link: /batches or /batch_statuses link for submitted batches """ timer_ctx = self._post_batches_total_time.time() self._post_batches_count.inc() # Parse request if request.headers['Content-Type'] != 'application/octet-stream': LOGGER.debug('Submission headers had wrong Content-Type: %s', request.headers['Content-Type']) self._post_batches_error.inc() raise errors.SubmissionWrongContentType() body = await request.read() if not body: LOGGER.debug('Submission contained an empty body') self._post_batches_error.inc() raise errors.NoBatchesSubmitted() try: batch_list = BatchList() batch_list.ParseFromString(body) except DecodeError: LOGGER.debug('Submission body could not be decoded: %s', body) self._post_batches_error.inc() raise errors.BadProtobufSubmitted() # Query validator error_traps = [ error_handlers.BatchInvalidTrap, error_handlers.BatchQueueFullTrap ] validator_query = client_batch_submit_pb2.ClientBatchSubmitRequest( batches=batch_list.batches) with self._post_batches_validator_time.time(): await self._query_validator( Message.CLIENT_BATCH_SUBMIT_REQUEST, client_batch_submit_pb2.ClientBatchSubmitResponse, validator_query, error_traps) # Build response envelope id_string = ','.join(b.header_signature for b in batch_list.batches) status = 202 link = self._build_url(request, path='/batch_statuses', id=id_string) retval = self._wrap_response(request, metadata={'link': link}, status=status) timer_ctx.stop() return retval
async def client_reader(self, request): """Fetches encrypted data from a specific address in the validator's state tree. will forward read request to TP and return encrypted respond Request: query: - encrypted_request: request encrypted with one time key for specific address as define in private ledger crypto documentation Response: data: The data stored at that address, encrypted back with the one time key for requester """ encrypted_request = request.match_info.get('encrypted_request', '') # convert back from url safe base64 encoding to regular base64 encoding try: enc_data_url = base64.urlsafe_b64decode(encrypted_request) encrypted_data = base64.b64encode(enc_data_url) except base64.binascii.Error: LOGGER.error('binascii.Error') raise errors.SubmissionWrongContentType() if (encrypted_data[-1] != b'\x00'): encrypted_data += b'\x00' try: # get the encrypted addres data from TP enc_res = await self._exchange_data_with_TP(encrypted_data) except Exception as e: LOGGER.error('exchange_data_with_TP exception') traceback.print_exc() raise errors.StatusResponseMissing() return self._wrap_response(request, data=enc_res, metadata=None)
async def submit_batches(self, request): """Accepts a binary encoded BatchList and submits it to the validator. Request: body: octet-stream BatchList of one or more Batches query: - wait: Request should not return until all batches committed Response: status: - 200: Batches submitted, but wait timed out before committed - 201: All batches submitted and committed - 202: Batches submitted and pending (not told to wait) data: Status of uncommitted batches (if any, when told to wait) link: /batches or /batch_status link for submitted batches """ # Parse request if request.headers['Content-Type'] != 'application/octet-stream': raise errors.SubmissionWrongContentType() body = await request.read() if not body: raise errors.NoBatchesSubmitted() try: batch_list = BatchList() batch_list.ParseFromString(body) except DecodeError: raise errors.BadProtobufSubmitted() # Query validator error_traps = [error_handlers.BatchInvalidTrap] validator_query = client_pb2.ClientBatchSubmitRequest( batches=batch_list.batches) self._set_wait(request, validator_query) response = await self._query_validator( Message.CLIENT_BATCH_SUBMIT_REQUEST, client_pb2.ClientBatchSubmitResponse, validator_query, error_traps) # Build response envelope data = response['batch_statuses'] or None link = '{}://{}/batch_status?id={}'.format( request.scheme, request.host, ','.join(b.header_signature for b in batch_list.batches)) if data is None: status = 202 elif any(s != 'COMMITTED' for _, s in data.items()): status = 200 else: status = 201 data = None link = link.replace('batch_status', 'batches') return self._wrap_response(data=data, metadata={'link': link}, status=status)
async def submit_batches(self, request): """Accepts a binary encoded BatchList and submits it to the validator. Request: body: octet-stream BatchList of one or more Batches query: - wait: Request should not return until all batches committed Response: status: - 200: Batches submitted, but wait timed out before committed - 201: All batches submitted and committed - 202: Batches submitted and pending (not told to wait) data: Status of uncommitted batches (if any, when told to wait) link: /batches or /batch_status link for submitted batches """ timer_ctx = self._post_batches_total_time.time() self._post_batches_count.inc() # Parse request if request.headers['Content-Type'] != 'application/octet-stream': LOGGER.debug('Submission headers had wrong Content-Type: %s', request.headers['Content-Type']) self._post_batches_error.inc() raise errors.SubmissionWrongContentType() body = await request.read() if not body: LOGGER.debug('Submission contained an empty body') self._post_batches_error.inc() raise errors.NoBatchesSubmitted() try: batch_list = BatchList() batch_list.ParseFromString(body) except DecodeError: LOGGER.debug('Submission body could not be decoded: %s', body) self._post_batches_error.inc() raise errors.BadProtobufSubmitted() # Query validator error_traps = [error_handlers.BatchInvalidTrap] validator_query = client_pb2.ClientBatchSubmitRequest( batches=batch_list.batches) self._set_wait(request, validator_query) with self._post_batches_validator_time.time(): response = await self._query_validator( Message.CLIENT_BATCH_SUBMIT_REQUEST, client_pb2.ClientBatchSubmitResponse, validator_query, error_traps) # Build response envelope data = self._drop_id_prefixes( self._drop_empty_props(response['batch_statuses'])) or None id_string = ','.join(b.header_signature for b in batch_list.batches) if data is None or any(d['status'] != 'COMMITTED' for d in data): status = 202 link = self._build_url(request, path='/batch_status', id=id_string) else: status = 201 data = None link = self._build_url(request, wait=False, id=id_string) retval = self._wrap_response(request, data=data, metadata={'link': link}, status=status) timer_ctx.stop() return retval