Return custom error on hyperledger sawtooth transaction processor

209 Views Asked by At

I'm using the python sdk to develop a custom transaction processor por hyperledger sawtooth.

Is it possible to return a custom error to the client that requested the transaction? How is the client supposed to know the reason that a transaction has not been processed?

I need to return an error from within the apply() method when the transaction cannot be completed due to any validation error, so the client that made the request can have some feedback about the error to show it to the user.

def apply(self, transaction, context):

In the examples I've checked the code raises an exception, but this ends the processor execution.

Any idea how can I do it?

3

There are 3 best solutions below

0
Red On

You can try something like this:

def apply(self, transaction, context):
    try:
        pass
        # your code
    except Exception as e:
        print(e)

Where instead of the print() call, send the e string to the client as it will contain the reason for the error.

0
Charalarg On

This can't be done by using the validator image as it is. You have to fork the https://github.com/hyperledger/sawtooth-core repo and implement your own logic in order to make the validator reply to the client in any custom case.

If you want to do that in order to avoid the infinite loop of the InvalidTransaction exceptions, you can build and use the validator from my fork https://github.com/charalarg/sawtooth-core instead of using the sawtooth validator docker image. Its the latest version of sawtooth (1.2.6) with a fix on the infinite loop bug.

I had the same problem and I was also trying to find a way to avoid transaction execution because of this bug but I ended up applying this fix. https://github.com/Remmeauth/sawtooth-core/pull/5.

0
Enoch On

You could define your own custom error to let the client know exactly what went wrong:

class ValidationError(Exception):
    """Exception raised for validation errors.

    Attributes:
        reason -- reason of the error
        message -- explanation of the error
    """

    def __init__(self, reason, message="Validation failed"):
        self.reason = reason
        self.message = message
        super().__init__(self.message)

    def __str__(self):
        # the return value of this function will be the error message
        return f'{self.reason} -> {self.message}'

Then you can integrate that Error into your code like so for example:

def apply(self, transaction, context):
    try:
        if network_connection is False:
            raise ValidationError("Missing Network Connection")

        # your code here

        if success is False:
            raise ValidationError("Unknown reason")

    except Exception as e:
        print(e)

If, for example, network_connection is set to False before the execution of the apply() function, the message printed out with e will be:

ValidationError: Missing Network Connection -> Validation failed

This message can then be sent to the client.