コード例 #1
0
    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
コード例 #2
0
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
コード例 #3
0
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
コード例 #4
0
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.")
コード例 #5
0
    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
コード例 #6
0
 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
コード例 #7
0
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)
コード例 #8
0
    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,
            }
            )
コード例 #9
0
 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