pythonhyperledgerblockchainhyperledger-sawtooth

Sawtooth Transaction error: "Tried to set unauthorized address"


I am trying to write my custom Transaction processor. I am writing for simple Account class

class Account:
    def __init__(self, name, ac_number, balance):
        self.name = name 
        self.ac_number = ac_number
        self.balance = balance 

My TP is working fine for a single account. Now I want to improve it for multiple accounts. To get a different state for each account number I have changed _'_get_account_address_' function. I am following @danintel 's Cookiejar and XO_python projects. I am following xo code to get the address.

AC_NAMESPACE = hashlib.sha512('account'.encode("utf-8")).hexdigest()[0:6]

def _make_account_address(name):
    return AC_NAMESPACE + \
        hashlib.sha512(name.encode('utf-8')).hexdigest()[:64]  

_get_account_address is working fine but _make_account_address showing error in cli

Tried to set unauthorized address

enter image description here

My state code is

import logging
import hashlib
from sawtooth_sdk.processor.exceptions import InternalError

LOGGER = logging.getLogger(__name__)


FAMILY_NAME = "account"
# TF Prefix is first 6 characters of SHA-512("cookiejar"), a4d219

AC_NAMESPACE = hashlib.sha512('account'.encode("utf-8")).hexdigest()[0:6]


def _make_account_address(name):
    return AC_NAMESPACE + \
        hashlib.sha512(name.encode('utf-8')).hexdigest()[:64]

def _hash(data):
    '''Compute the SHA-512 hash and return the result as hex characters.'''
    return hashlib.sha512(data).hexdigest()

def _get_account_address(from_key):
    '''
    Return the address of a cookiejar object from the cookiejar TF.

    The address is the first 6 hex characters from the hash SHA-512(TF name),
    plus the result of the hash SHA-512(cookiejar public key).
    '''
    return _hash(FAMILY_NAME.encode('utf-8'))[0:6] + \
                 _hash(from_key.encode('utf-8'))[0:64]

class Account:
    def __init__(self, name, ac_number, balance):
        self.name = name 
        self.ac_number = ac_number
        self.balance = balance 


class AccountState:
    def __init__(self, context):
        self._context = context 

    def make_account(self, account_obj, from_key):
        '''Bake (add) "amount" cookies.'''
        account_address = _make_account_address(account_obj.name) # not working 
        #account_address = _get_account_address(from_key) # working fine
        LOGGER.info('Got the key %s and the account address %s.',
                    from_key, account_address)

        state_str = ",".join([str(account_obj.name), str(account_obj.ac_number), str(account_obj.balance)])
        state_data = state_str.encode('utf-8')
        addresses = self._context.set_state({account_address: state_data})

        if len(addresses) < 1:
            raise InternalError("State Error")

Solution

  • This probably has been answered already, but I've lesser credits to add a comment.

    The error you see "Tried to set unauthorized address: " is because client did not include these addresses in TransactionHeader's "outputs" addresses field.

    It is possible for client to give prefix instead of complete address in "outputs" addresses field, but make use of this feature cautiously because it'll impact parallel transaction scheduling.

    Please refer to https://sawtooth.hyperledger.org/docs/core/nightly/master/architecture/transactions_and_batches.html#dependencies-and-input-output-addresses for detailed understanding on different fields when composing TransactionHeader.