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
def make_batch_request(batch_list): """ Make a batch request from a batch list """ batch_request = client_batch_submit_pb2.ClientBatchSubmitRequest() # pylint: disable=no-member batch_request.batches.extend(list(batch_list.batches)) return batch_request
async def send(conn, batch_list, timeout, webhook=False): """Send batch_list to sawtooth.""" batch_request = client_batch_submit_pb2.ClientBatchSubmitRequest() batch_request.batches.extend(list(batch_list.batches)) validator_response = await conn.send( validator_pb2.Message.CLIENT_BATCH_SUBMIT_REQUEST, batch_request.SerializeToString(), timeout, ) client_response = client_batch_submit_pb2.ClientBatchSubmitResponse() client_response.ParseFromString(validator_response.content) status = client_response.status if not webhook: if status == client_batch_submit_pb2.ClientBatchSubmitResponse.INTERNAL_ERROR: raise ApiInternalError("Internal Error") elif status == client_batch_submit_pb2.ClientBatchSubmitResponse.INVALID_BATCH: raise ApiBadRequest("Invalid Batch") elif status == client_batch_submit_pb2.ClientBatchSubmitResponse.QUEUE_FULL: raise ApiInternalError("Queue Full") elif status != client_batch_submit_pb2.ClientBatchSubmitResponse.OK: return None status_request = client_batch_submit_pb2.ClientBatchStatusRequest() status_request.batch_ids.extend( list(b.header_signature for b in batch_list.batches)) status_request.wait = True status_request.timeout = timeout validator_response = await conn.send( validator_pb2.Message.CLIENT_BATCH_STATUS_REQUEST, status_request.SerializeToString(), timeout, ) status_response = client_batch_submit_pb2.ClientBatchStatusResponse() status_response.ParseFromString(validator_response.content) status = status_response.status if not webhook: if status != client_batch_submit_pb2.ClientBatchStatusResponse.OK: raise ApiInternalError("Internal Error") elif status != client_batch_submit_pb2.ClientBatchStatusResponse.OK: return None response = status_response.batch_statuses[0] status = response.status if not webhook: if status == client_batch_submit_pb2.ClientBatchStatus.INVALID: raise ApiBadRequest("Bad Request: {}".format( response.invalid_transactions[0].message)) elif status == client_batch_submit_pb2.ClientBatchStatus.PENDING: raise ApiInternalError("Internal Error: Transaction timed out.") elif status == client_batch_submit_pb2.ClientBatchStatus.UNKNOWN: raise ApiInternalError("Internal Error: Unspecified error.") return status
async def send(conn, batch_list, timeout): batch_request = client_batch_submit_pb2.ClientBatchSubmitRequest() batch_request.batches.extend(list(batch_list.batches)) validator_response = await conn.send( validator_pb2.Message.CLIENT_BATCH_SUBMIT_REQUEST, batch_request.SerializeToString(), timeout, ) client_response = client_batch_submit_pb2.ClientBatchSubmitResponse() client_response.ParseFromString(validator_response.content) if (client_response.status == client_batch_submit_pb2.ClientBatchSubmitResponse.INTERNAL_ERROR): raise ApiInternalError("Internal Error") elif (client_response.status == client_batch_submit_pb2.ClientBatchSubmitResponse.INVALID_BATCH): raise ApiBadRequest("Invalid Batch") elif (client_response.status == client_batch_submit_pb2.ClientBatchSubmitResponse.QUEUE_FULL): raise ApiInternalError("Queue Full") status_request = client_batch_submit_pb2.ClientBatchStatusRequest() status_request.batch_ids.extend( list(b.header_signature for b in batch_list.batches)) status_request.wait = True status_request.timeout = timeout validator_response = await conn.send( validator_pb2.Message.CLIENT_BATCH_STATUS_REQUEST, status_request.SerializeToString(), timeout, ) status_response = client_batch_submit_pb2.ClientBatchStatusResponse() status_response.ParseFromString(validator_response.content) if status_response.status != client_batch_submit_pb2.ClientBatchStatusResponse.OK: raise ApiInternalError("Internal Error") resp = status_response.batch_statuses[0] if resp.status == client_batch_submit_pb2.ClientBatchStatus.COMMITTED: return resp elif resp.status == client_batch_submit_pb2.ClientBatchStatus.INVALID: raise ApiBadRequest("Bad Request: {}".format( resp.invalid_transactions[0].message)) elif resp.status == client_batch_submit_pb2.ClientBatchStatus.PENDING: raise ApiInternalError( "Internal Error: Transaction submitted but timed out.") elif resp.status == client_batch_submit_pb2.ClientBatchStatus.UNKNOWN: raise ApiInternalError( "Internal Error: Something went wrong. Try again later.")
async def _make_token_transfer(self,request,address_from,address_to,num_bgt,coin_code='bgt'): """ Make transfer from wallet to wallet """ payload_bytes = cbor.dumps({ 'Verb' : 'transfer', 'Name' : address_from, 'to_addr': address_to, 'num_bgt': num_bgt, 'group_id' : coin_code }) LOGGER.debug('BgxRouteHandler: _make_token_transfer make payload=%s',payload_bytes) in_address = make_smart_bgt_address(address_from) out_address = make_smart_bgt_address(address_to) inputs =[in_address, out_address] outputs=[in_address, out_address] transaction = self._create_transaction(payload_bytes,inputs,outputs) batch = self._create_batch([transaction]) batch_id = batch.header_signature #batch_list.batches[0].header_signature # Query validator error_traps = [error_handlers.BatchInvalidTrap,error_handlers.BatchQueueFullTrap] validator_query = client_batch_submit_pb2.ClientBatchSubmitRequest(batches=[batch]) LOGGER.debug('BgxRouteHandler: _make_token_transfer send batch_id=%s',batch_id) 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) # Ask validator for batch status while it changes from PENDING pending_status = 'PENDING' status = '' while True: error_traps = [error_handlers.StatusResponseMissing] validator_query = \ client_batch_submit_pb2.ClientBatchStatusRequest( batch_ids=[batch_id]) self._set_wait(request, validator_query) response = await self._query_validator( Message.CLIENT_BATCH_STATUS_REQUEST, client_batch_submit_pb2.ClientBatchStatusResponse, validator_query, error_traps) metadata = self._get_metadata(request, response) data = self._drop_id_prefixes( self._drop_empty_props(response['batch_statuses'])) LOGGER.debug('CLIENT_BATCH_STATUS_REQUEST:metadata:%s', metadata) LOGGER.debug('CLIENT_BATCH_STATUS_REQUEST:data:%s', data) batch = data[0] if batch['status'] != pending_status: status = batch['status'] break time.sleep(5) # Build response envelope # link = self._build_url(request, path='/batch_statuses', id=batch_id) return status
def make_batch_request(self, batch_list): """Make a batch request from a batch list""" batch_request = client_batch_submit_pb2.ClientBatchSubmitRequest() batch_request.batches.extend(list(batch_list.batches)) return batch_request
async def send(conn, timeout, batches): batch_request = client_batch_submit_pb2.ClientBatchSubmitRequest() batch_request.batches.extend(batches) await conn.send(validator_pb2.Message.CLIENT_BATCH_SUBMIT_REQUEST, batch_request.SerializeToString(), timeout)
async def run_transaction(self, request): """ make transfer from wallet to wallet """ family = request.url.query.get('family', None) if family == 'bgt' : cmd = request.url.query.get('cmd', None) arg1 = request.url.query.get('wallet', None) if cmd == 'show': address = make_bgt_address(arg1) error_traps = [error_handlers.InvalidAddressTrap,error_handlers.StateNotFoundTrap] response = await self._query_validator( Message.CLIENT_STATE_GET_REQUEST, client_state_pb2.ClientStateGetResponse, client_state_pb2.ClientStateGetRequest( state_root='', address=address), error_traps) LOGGER.debug('run_transaction: BGT show=%s (%s)!',arg1,response) if response['status'] == 'OK': bgt = loads_bgt_token(response['value'],arg1) LOGGER.debug('run_transaction: BGT[%s]=%s!',arg1,bgt) else: bgt = response['value'] return self._wrap_response( request, data=bgt, metadata=self._get_metadata(request, response)) arg2 = request.url.query.get('amount', None) arg3 = request.url.query.get('to', None) LOGGER.debug('run_transaction family=%s cmd=%s(%s,%s) query=%s!!!',family,cmd,arg1,arg2,request.url.query) transaction = create_bgt_transaction(verb=cmd,name=arg1,value=int(arg2),signer=self._signer,to=arg3) batch = self._create_batch([transaction]) batch_id = batch.header_signature else: # undefined families batch_id = None link = '' if batch_id is not None: error_traps = [error_handlers.BatchInvalidTrap,error_handlers.BatchQueueFullTrap] validator_query = client_batch_submit_pb2.ClientBatchSubmitRequest(batches=[batch]) LOGGER.debug('run_transaction send batch_id=%s',batch_id) 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) link = self._build_url(request, path='/batch_statuses', id=batch_id) return self._wrap_response( request, data=None, metadata={ 'link': link, } )
def make_batch_request(self, batch_list): batch_request = client_batch_submit_pb2.ClientBatchSubmitRequest() batch_request.batches.extend(list(batch_list.batches)) return batch_request