Exemplo n.º 1
0
async def submit_empty_asset(app, requester, claimed=False):
    """
    claimed : False, Which means this account hasnt been claimed, it doesnt have
            a orgnization_account
            Implies that create_asset_idxs array of float account will be appended
            with key_index rather the orgnization acount create_asset_idxs
    float_accounts cannot create assets, but any other orgnization who have been
    claimed can force float_account to create empty asset, thats why
    for create_asset claimed will be always True.

    Now empty asset can be created by any account, Child, orgnization or
    float_account

    Child account for float_account can't exists

    """

    f = await userapis.SolveAccount(requester, app)
    decrypted_mnemonic = f.decrypted_mnemonic
    org_db_entry = f.org_db

    logging.info(f"THis is the decrypted mnemonic {decrypted_mnemonic}")
    create_asset_idxs = f.org_state.get("create_asset_idxs")
    child_zero_pub = f.child_zero_pub
    child_user_id = f.child_user_id
    zero_pub = f.zero_pub

    if not claimed:  ##these are required so that create_asset_idxs of float account
        ##can be apended with key_index
        flt_account_parent_pub = requester[
            "parent_pub"]  #exists both in users_table
        flt_account_parent_idx = requester["parent_idx"]
    else:
        flt_account_parent_pub = None  #exists both in users_table
        flt_account_parent_idx = None

    key_index = await ledger_utils.generate_key_index(array=create_asset_idxs)

    nth_keys = await remote_calls.key_index_keys(app, decrypted_mnemonic,
                                                 [key_index])

    nth_priv, nth_pub = nth_keys[str(key_index)]["private_key"], \
                        nth_keys[str(key_index)]["public_key"]

    key = encrypted_key = s3_url = encrypted_s3_url = None

    master_key = master_url = None

    ##the transaction will be signed by users nth private key
    create_asset_signer = ledger_utils.create_signer(nth_priv)

    ##we havent included the child_nth_pub in this transaction because it
    ## can be calculated from txn_key on the processor side

    asset_address = addresser.create_asset_address(asset_id=nth_pub,
                                                   index=key_index)

    transaction_data = {
        "config": app.config,
        "txn_key": create_asset_signer,
        "batch_key": app.config.SIGNER,
        "key": None,
        "url": None,
        "time": int(time.time()),
        "indiantime": upload_utils.indian_time_stamp(),
        "file_name": None,
        "file_hash": None,
        "idx": key_index,
        "master_key": None,
        "master_url": None,
        "scope": None,
        "role": requester["role"],
        "zero_pub": zero_pub,
        "is_acc_claimed": claimed,
        "flt_account_parent_pub": flt_account_parent_pub,
        "flt_account_parent_idx": flt_account_parent_idx,
        "child_zero_pub": child_zero_pub,
    }

    logging.info(f"THis is the transaction data {transaction_data}")

    transaction_ids, batch_id = await send_create_asset(**transaction_data)

    if batch_id:

        [
            transaction_data.pop(field) for field in [
                "config", "txn_key", "batch_key", "is_acc_claimed",
                "flt_account_parent_pub", "flt_account_parent_idx"
            ]
        ]
        transaction_data.update({
            "user_id": requester["user_id"],
            "public": nth_pub,
            "transaction_id": transaction_ids[0],
            "batch_id": batch_id,
            "asset_address": asset_address,
            "child_zero_pub": child_zero_pub
        })
        await assets_query.store_assets(app, transaction_data)
        if claimed:
            await accounts_query.update_create_asst_idxs(
                app, org_db_entry["user_id"], key_index)
        else:
            logging.error("Must be a float account")
            await accounts_query.update_create_asst_idxs_pending(
                app, org_db_entry["user_id"], key_index)

        if child_user_id:
            await accounts_query.update_create_asst_idxs(
                app, child_user_id, key_index)

            #await accounts_query.update_create_asst_idxs_pending(app,
            #requester["user_id"], key_index)

        return nth_priv, nth_pub, key_index, asset_address
    else:
        logging.error("Create asset Faied, GO to hell Dude!!!!,\
         Kabhi kabhi lagta hai ki bhagwan hone ka bhi kya fayda")
    return
Exemplo n.º 2
0
async def submit_create_asset(app, requester, file_data):
    """

    Creates an empty asset or asset with data,

    Process:
        Get user Mnemonic
            If user is child,
                    then get the mnemonic of the parent orgnization
            This can be done by getting by fetching org account present on the
            blokchchain constructing org_address from child["parent_pub"]

            Checks:
                1.check if child is actually a valid child by checking if child
                parent_idx is in org_account["child_account_idxs"]
                2. Check child org_name is same is orgnization org_name

            Fecth org entry in the dabase corresponding to the user_id of the
            org in orgnization entry on blokchchain

            NOw decrypt the org menmonic with Admin public key if org is not admin

            Now, get the create_asset_idxs array of the organization from the
            blockchain
        if requester is orgnization:
            Fecth org entry in the dabase corresponding to the user_id of the
            org in orgnization entry on blokchchain

            NOw decrypt the org menmonic with Admin public key if org is not admin

            Now, get the create_asset_idxs array of the organization from the
            blockchain

    A new key_index will be generated at create_asset_idxs,
    From the decrypted_nemonic, Public/Private key pair will be generated at this
    key_index, this will be a asset_address

    NOw, Check if file_Data is there or not, if yes, Encrypt the file data with
    random AES key, and post it on S3,
    Now encrypt both AES key and s3_url with the public key generated at random index

    Now there are two main conditions which needs attention,
        The user who still dont have an orgnization account but only a float_account
        In this case,
            is_claimed
            "flt_account_parent_pub": requester["parent_pub"],
            "flt_account_parent_idx": requester["parent_idx"],
            THese are required because since this is a float_account, on the
            processor side, the key_index will be appended to float_account which
            will be calculated from these two keys

        Th user does have an orgnization account

    The user whom is floating this transaction
    if claimed=False, user havent claimed his/her account


    if claimed=False, the requester["role"] cant be child, as float
    accounts arent allowed to create child roles,
    ADMIN doesnt have float accounts



    "flt_account_parent_pub": None,
    "flt_account_parent_idx": None,
    THese keys are required if the account is float_account, Now since this orgnization
    doesnt have any real account or the account has not been claimed, the create_asset_idxs
    will be appended to create_asset_idxs of float account

    Now since float account can not create new assets, only assets being transffered to them,
    Float account cannot run this function as credentials of float account are debarred from
    accessing this api or this function

    so, only CHILD, AQDMIN or any other orgnixzation who already have alimed their account
    can access this API, which means they have orgnization account, which means
    key_index will be appende to their orgnization account not float_account_idxs,
    Hence these two keys will be none for this function
    """
    logging.info("Enterintosubmitcreateasset")
    f = await userapis.SolveAccount(requester, app)
    decrypted_mnemonic = f.decrypted_mnemonic
    org_state = f.org_state
    logging.info(f"THis is the decrypted mnemonic {decrypted_mnemonic}")
    create_asset_idxs = f.org_state.get("create_asset_idxs")
    child_zero_pub = f.child_zero_pub
    child_user_id = f.child_user_id
    zero_pub = f.zero_pub
    flt_account_parent_pub = None  #exists both in users_table
    flt_account_parent_idx = None

    ##generate a new random index key which is not present in the
    ## create_asset_idxs
    key_index = await ledger_utils.generate_key_index(array=create_asset_idxs)

    logging.info(f"User key index create_asset_idxs for user {key_index}")
    ##retrieve pub/priv key pair corresponding to the random index just
    ##generated
    nth_keys = await remote_calls.key_index_keys(app, decrypted_mnemonic,
                                                 [key_index])

    nth_priv, nth_pub = nth_keys[str(key_index)]["private_key"], \
                        nth_keys[str(key_index)]["public_key"]

    ## all the data being encrypted with user nth public key
    key, encrypted_key, s3_url, encrypted_s3_url = \
            await asset_utils.encrypt_file_data(requester["user_id"], nth_pub, app.config,
            file_data)

    master_key, master_url = await asset_utils.master_url_n_key(
        app.config.ADMIN_ZERO_PUB, key, s3_url)

    ##the transaction will be signed by users nth private key
    create_asset_signer = ledger_utils.create_signer(nth_priv)

    ##we havent included the child_nth_pub in this transaction because it
    ## can be calculated from txn_key on the processor side

    asset_address = addresser.create_asset_address(asset_id=nth_pub,
                                                   index=key_index)

    transaction_data = {
        "config": app.config,
        "txn_key": create_asset_signer,
        "batch_key": app.config.SIGNER,
        "key": encrypted_key,
        "url": encrypted_s3_url,
        "time": int(time.time()),
        "indiantime": upload_utils.indian_time_stamp(),
        "file_name": file_data["file_name"],
        "file_hash": file_data["file_hash"],
        "idx": key_index,
        "master_key": master_key,
        "master_url": master_url,
        "role": requester["role"],
        "scope": file_data["scope"],
        "zero_pub": zero_pub,
        "is_acc_claimed": True,
        "flt_account_parent_pub": None,
        "flt_account_parent_idx": None,
        "child_zero_pub": child_zero_pub,
    }

    logging.info(f"THis is the transaction data {transaction_data}")
    transaction_ids, batch_id = await send_create_asset(**transaction_data)

    if batch_id:
        logging.info("Create Transaction has been created successfully")
        ##which imlies the transaction has been submitted successfully,
        ##now all the changes that are required to be done on the databse can
        ##be done
        ##Update users create_asset_idxs key on users entry will be updated by
        ## whomever will call this, because update can happend on pending_users
        ## table or users table depending upon user has been claimed or not.

        ##if transaction was submitted successfully
        ##Update user entry in the pending_users table of uer_table with the new
        ##new asset_index in creat_asset_idxs

        ##insert in asests with new asset created
        [
            transaction_data.pop(field) for field in [
                "config", "txn_key", "batch_key", "is_acc_claimed",
                "flt_account_parent_pub", "flt_account_parent_idx"
            ]
        ]
        transaction_data.update({
            "user_id": requester["user_id"],
            "public": nth_pub,
            "transaction_id": transaction_ids[0],
            "batch_id": batch_id,
            "asset_address": asset_address,
            "child_zero_pub": child_zero_pub
        })
        ##updating assets table with this new asset
        await assets_query.store_assets(app, transaction_data)

        ##updating org_state user_id in users table with new index of asset
        await accounts_query.update_create_asst_idxs(app, org_state["user_id"],
                                                     key_index)

        if child_user_id:
            ##updating child_user_id user_id in users table with new index of asset
            await accounts_query.update_create_asst_idxs(
                app, child_user_id, key_index)

            #await accounts_query.update_create_asst_idxs_pending(app,
            #requester["user_id"], key_index)

        return nth_priv, nth_pub, key_index, asset_address
    else:
        logging.error("Create asset Faied, GO to hell Dude!!!!,\
         Kabhi kabhi lagta hai ki bhagwan hone ka bhi kya fayda")
    return
Exemplo n.º 3
0
async def submit_share_asset(app, requester, asset_address,
                             receive_asset_address, unique_code, revoked_on,
                             comments):
    """

        1.check whether asset_address is valid asset address or not
        2. check whether the asset is empty or not
        3.check whether the asset has been transsefred the ownership to someother  empty asset
        4.check whether the requester is the owner of this asset or not
        5.check whether the receiver_asset_address is a valid receive_asset_address or not
        6.check whether at_which_asset_expires is stil valid or hasnt expired
        7.cheque whether the sha_2224 hash of unique code matches with receiver_asset

    """

    f = await userapis.SolveAccount(requester, app)
    decrypted_mnemonic = f.decrypted_mnemonic
    org_state = f.org_state
    logging.info(f"THis is the decrypted mnemonic {decrypted_mnemonic}")
    share_asset_idxs = f.org_state.get("share_asset_idxs")
    child_user_id = f.child_user_id
    child_zero_pub = f.child_zero_pub
    account_zero_pub = f.zero_pub

    unique_code_hash = hashlib.sha224(str(unique_code).encode()).hexdigest()
    if await share_assets_query.find_share_asset(app, asset_address,
                                                 receive_asset_address):
        raise ApiInternalError("This shared asset has already been done")
    ##checking point 5
    receive_asset_instance = await userapis.SolveAddress(
        receive_asset_address, app.config.REST_API_URL)

    if receive_asset_instance.type != "RECEIVE_ASSET":
        raise AssetError("receive_asset_address is notreceive asset address")

    if not receive_asset_instance.data[
            "at_which_asset_expires"] > upload_utils.now_time_stamp():
        raise errors.InvalidValidityPeriod("The time to share asset with this \
                    address has been expired")

    if receive_asset_instance.data["unique_code_hash"] !=\
            unique_code_hash:
        raise AssetError(
            "Unique code provided is either wrong or meant for different receiver_address"
        )

    asset_instance = await userapis.SolveAddress(asset_address,
                                                 app.config.REST_API_URL)
    if asset_instance.type != "CREATE_ASSET":
        raise AssetError("asset_address is not asset address")

    ##check point 2
    if not asset_instance.data["file_name"] or not asset_instance.data[
            "file_hash"]:
        raise AssetError("Empty assets cannot be shared")

    ##decrypting issuer mnemonic

    requester_account_address = addresser.create_organization_account_address(
        account_id=org_state["public"], index=0)

    ##Check if the asset had been transffered to the issuer i.e issets which were
    ###not created by the issuer cant be transffered to other users
    if asset_instance.data.get("ownership_transfer"):
        message = f"This asset which already have been transffered to \
                {issuer_asset.get('ownership_transfer')} can be shared"

        logging.error(message)
        raise AssetError(message)

    key_index = await ledger_utils.generate_key_index(share_asset_idxs)
    logging.info(f"THis is the key index for issuer {key_index}")

    ##at which the asset was created
    asset_index = asset_instance.data["idx"]

    nth_keys = await remote_calls.key_index_keys(app, decrypted_mnemonic,
                                                 [0, key_index, asset_index])

    ##account kets for the issuer
    requester_zeroth_priv, requester_zeroth_pub = \
                    nth_keys[str(0)]["private_key"], \
                        nth_keys[str(0)]["public_key"]

    ##keys at which teh asset which needs to be shared was floated
    create_asset_priv, create_asset_pub = nth_keys[str(asset_index)]["private_key"], \
                            nth_keys[str(asset_index)]["public_key"]

    ##keys at which the shared asset index will be floated
    share_asset_priv, share_asset_pub = nth_keys[str(key_index)]["private_key"], \
                            nth_keys[str(key_index)]["public_key"]

    ##check if issuer n th public key is exactly the public key mentioned in the
    ##asset transaction present on the blockchain, this also checks whether
    ##the requester is actually the owner of the asset
    if create_asset_pub != asset_instance.data.get("public"):
        logging.error("This asset address is not owned by the issuer")
        raise AssetError("This asset address is not owned by the issuer")

    ##decrypting file data stored ob the issuer asset address, this can be
    ##done by issuer private key present on the nth index
    data = await asset_utils.decrypt_file_data(
        asset_instance.data["key"], asset_instance.data["url"],
        asset_instance.data["file_hash"], create_asset_priv)

    ##TODO: check file_hash
    file_data = {
        "data": data,
        "file_name": asset_instance.data["file_name"],
        "file_hash": asset_instance.data["file_hash"]
    }

    ##encrypting again with the public key present at the receiver_asset_address
    key, encrypted_key, s3_url, encrypted_s3_url = \
        await asset_utils.encrypt_file_data(None, receive_asset_instance.data["public"], app.config,
            file_data)

    logging.info(f"This is the key {key} , encrypted_key{encrypted_key} \
                and the s3_url {s3_url}")
    master_key, master_url = await asset_utils.master_url_n_key(
        app.config.ADMIN_ZERO_PUB, key, s3_url)

    ##Now this transaction should be signed by user

    create_asset_signer = ledger_utils.create_signer(share_asset_priv)

    ##for added security we will send a nonce signed by issuer account
    ##private key
    nonce = random.randint(2**20, 2**30)
    nonce_hash = hashlib.sha224(str(nonce).encode()).hexdigest()
    account_hex_signature = signatures.ecdsa_signature(requester_zeroth_priv,
                                                       nonce)

    ##nonce must also be signed with the private key at random index at which
    ##create asset is present
    asset_hex_signature = signatures.ecdsa_signature(create_asset_priv, nonce)

    transaction_data = {
        "config": app.config,
        "txn_key": create_asset_signer,
        "batch_key": app.config.SIGNER,
        "key": encrypted_key,
        "url": encrypted_s3_url,
        "master_key": master_key,
        "master_url": master_url,
        "time": int(time.time()),
        "indiantime": upload_utils.indian_time_stamp(),
        "file_name": asset_instance.data["file_name"],
        "file_hash": asset_instance.data["file_hash"],
        "original_asset_address": asset_address,
        "revoked_on": revoked_on,
        "comments": comments,
        "idx": key_index,
        "account_signature": account_hex_signature,
        "asset_signature": asset_hex_signature,
        "nonce": nonce,
        "nonce_hash": nonce_hash,
        "to_org_name": receive_asset_instance.data["org_name"],
        "to_org_address": receive_asset_instance.data["org_address"],
        "issuer_account_address": requester_account_address,
        "receive_asset_address": receive_asset_address,
        "child_zero_pub": child_zero_pub,
        "unique_code_hash": unique_code_hash,
    }

    transaction_ids, batch_id = await send_share_asset(**transaction_data)

    if transaction_ids:
        logging.info("Share Transaction has been created successfully")
        ##which imlies the transaction has been submitted successfully,
        ##now all the changes that are required to be done on the databse can
        ##be done
        ##Update users create_asset_idxs key on users entry will be updated by
        ## whomever will call this, because update can happend on pending_users
        share_asset_address = addresser.share_asset_address(
            share_asset_pub, key_index)
        account_signature = account_hex_signature.decode()
        asset_signature = asset_hex_signature.decode()
        transaction_data.update({
            "transaction_id": transaction_ids[0],
            "batch_id": batch_id,
            "account_signature": account_signature,
            "asset_signature": asset_signature,
            "address": share_asset_address
        })

        [
            transaction_data.pop(field)
            for field in ["config", "txn_key", "batch_key"]
        ]
        await share_assets_query.store_share_asset(app, transaction_data)

        ##now asset must be update with share_with key
        await assets_query.update_issuer_asset_shared(app, asset_address,
                                                      key_index)
        ##TOFO update receiver_address asset and issuer_asset_Address in DB

        await accounts_query.update_share_asset_idxs(app, org_state["user_id"],
                                                     key_index)

        if child_user_id:
            await accounts_query.update_share_asset_idxs(
                app, child_user_id, key_index)

        return share_asset_address

    else:
        return False
    return
async def submit_receive_asset(app, requester, _id_, name, description,
                               at_which_asset_expires):
    """
    """
    f = await userapis.SolveAccount(requester, app)
    decrypted_mnemonic = f.decrypted_mnemonic
    logging.info(f"THis is the decrypted mnemonic {decrypted_mnemonic}")
    org_db_entry = f.org_db
    receive_asset_idxs = f.org_state.get("receive_asset_idxs")
    child_user_id = f.child_user_id
    child_zero_pub = f.child_zero_pub
    account_zero_pub = f.zero_pub

    key_index = await ledger_utils.generate_key_index(array=receive_asset_idxs)

    nth_keys = await remote_calls.key_index_keys(app, decrypted_mnemonic,
                                                 [key_index, 0])

    nth_priv, nth_pub = nth_keys[str(key_index)]["private_key"], \
                        nth_keys[str(key_index)]["public_key"]

    org_priv, org_pub = nth_keys[str(0)]["private_key"], \
                        nth_keys[str(0)]["public_key"]

    org_account_address = addresser.create_organization_account_address(
        account_id=account_zero_pub, index=0)

    instance = await userapis.SolveAddress(org_account_address,
                                           app.config.REST_API_URL)
    org_state = instance.data

    ##the transaction will be signed by users nth private key
    create_asset_signer = ledger_utils.create_signer(nth_priv)

    ##we havent included the child_nth_pub in this transaction because it
    ## can be calculated from txn_key on the processor side

    ##for added security we will send a nonce signed by issuer account
    ##private key
    nonce = random.randint(2**20, 2**30)
    nonce_hash = hashlib.sha224(str(nonce).encode()).hexdigest()
    ##nonce signed by zerothprivate key and in hex format
    hex_signatures = signatures.ecdsa_signature(org_priv, nonce)

    receive_asset_address = addresser.receive_asset_address(asset_id=nth_pub,
                                                            index=key_index)

    unique_code = int("".join(map(str, random.choices(list(range(1, 10)),
                                                      k=5))))
    unique_code_hash = hashlib.sha224(str(unique_code).encode()).hexdigest()
    encrypted_unique_code = encryption_utils.encrypt_w_pubkey(
        str(unique_code).encode(), nth_pub)
    encrypted_admin_unique_code = encryption_utils.encrypt_w_pubkey(
        str(unique_code).encode(), app.config.ADMIN_ZERO_PUB)

    transaction_data = {
        "config": app.config,
        "txn_key": create_asset_signer,
        "batch_key": app.config.SIGNER,
        "_id_": _id_,
        "time": int(time.time()),
        "indiantime": upload_utils.indian_time_stamp(),
        "idx": key_index,
        "at_which_asset_expires": at_which_asset_expires,
        "org_name": org_state["org_name"],
        "org_address": org_account_address,
        "org_zero_pub": org_pub,
        "org_role": org_state["role"],
        "receive_asset_details": {
            "name": name,
            "description": description
        },
        "child_zero_pub": child_zero_pub,
        "signed_nonce": hex_signatures,
        "nonce": nonce,
        "nonce_hash": nonce_hash,
        "unique_code_hash": unique_code_hash,
        "encrypted_unique_code": encrypted_unique_code,
        "encrypted_admin_unique_code": encrypted_admin_unique_code
    }

    logging.info(f"THis is the transaction data in receive_asset")
    logging.info(pprint(transaction_data))

    transaction_ids, batch_id = await send_receive_asset(**transaction_data)

    if batch_id:
        [
            transaction_data.pop(field)
            for field in ["config", "txn_key", "batch_key"]
        ]
        signed_nonce = transaction_data["signed_nonce"].decode()

        transaction_data.update({
            "user_id": requester["user_id"],
            "public": nth_pub,
            "transaction_id": transaction_ids[0],
            "batch_id": batch_id,
            "signed_nonce": signed_nonce,
            "unique_code": unique_code
        })

        await receive_assets_query.store_receive_assets(app, transaction_data)
        await accounts_query.update_receive_assets_idxs(
            app, org_db_entry["user_id"], key_index)
        ##if this receive_asset is created by child of the organization
        ##then update the child account receive_asset_idxs array also
        if child_user_id:
            await accounts_query.update_receive_assets_idxs(
                app, child_user_id, key_index)

            #await accounts_query.update_create_asst_idxs_pending(app,
            #requester["user_id"], key_index)

        return nth_pub, key_index, receive_asset_address
    else:
        logging.error("Create asset Faied, GO to hell Dude!!!!,\
         Kabhi kabhi lagta hai ki bhagwan hone ka bhi kya fayda")
    return
Exemplo n.º 5
0
async def submit_transfer_asset(app, requester, issuer_address,
                                receiver_address, expired_on):

    ##decrypting issuer mnemonic
    logging.info("Enter into Transfer asset")
    f = await userapis.SolveAccount(requester, app)
    decrypted_mnemonic = f.decrypted_mnemonic

    logging.info(f"Requester Mnemonic is {decrypted_mnemonic}")
    instance = await userapis.SolveAddress(issuer_address,
                                           app.config.REST_API_URL)

    ##getting issuer public key and the index at which this asset was created
    if instance.type != "CREATE_ASSET":
        raise AssetError("Not a valid issuer address")

    issuer_asset = instance.data
    issuer_asset_public_key, issuer_asset_idx = \
                issuer_asset["public"], issuer_asset["idx"]

    instance = await userapis.SolveAddress(receiver_address,
                                           app.config.REST_API_URL)

    if instance.type != "CREATE_ASSET":
        raise AssetError("Not a valid receiver address")
    receiver_asset = instance.data

    logging.info(f"Deserialized receiver asset <<{issuer_asset}>>")

    ##checking is issuer asset is empty or not, empty assets cant be transffered
    if not issuer_asset["file_name"] or not issuer_asset["file_hash"]:
        logging.error("Empty assets cannot be transffered")
        raise AssetError("Empty assets cannot be transffered")

    ##Check if the asset had been transffered to the issuer i.e issets which were
    ###not created by the issuer cant be transffered to other users
    if issuer_asset.get("ownership_received"):
        message = f"This asset is not owned by the user but \
                        received from {issuer_asset['parent_address']}"

        logging.error(message)
        raise AssetError(message)

    ##checking if receiver_asset is empty or not, non empty assets couldnt receive
    ##assets
    if receiver_asset.get("file_name") or receiver_asset.get("file_hash"):
        logging.error("Non empty assets cannot be a receiver")
        raise AssetError("Non empty assets cannot be a receiver")

    ##get issuer keys from the GOAPI_URL, private key corresponding to the
    ##random index public key at which the asset was floated
    issuer_keys = await remote_calls.key_index_keys(app, decrypted_mnemonic,
                                                    [issuer_asset_idx, 0])


    issuer_zeroth_priv, issuer_zeroth_pub = \
                    issuer_keys[str(0)]["private_key"], \
                        issuer_keys[str(0)]["public_key"]


    issuer_nth_priv, issuer_nth_pub = issuer_keys[str(issuer_asset_idx)]["private_key"], \
                            issuer_keys[str(issuer_asset_idx)]["public_key"]

    ##check if issuer n th public key is exactly the public key mentioned in the
    ##asset transaction present on the blockchain, this also checks whether
    ##the requester is actually the owner of the asset
    if issuer_nth_pub != issuer_asset_public_key:
        logging.error("This asset address is not owned by the issuer")
        raise AssetError("This asset address is not owned by the issuer")

    ##decrypting file data stored ob the issuer asset address, this can be
    ##done by issuer private key present on the nth index
    data = await asset_utils.decrypt_file_data(issuer_asset["key"],
                                               issuer_asset["url"],
                                               issuer_asset["file_hash"],
                                               issuer_nth_priv)

    ##TODO: check file_hash
    file_data = {
        "data": data,
        "file_name": issuer_asset["file_name"],
        "file_hash": issuer_asset["file_hash"]
    }

    ##encrypting again with the public key present at the receiver_asset_address
    key, encrypted_key, s3_url, encrypted_s3_url = \
        await asset_utils.encrypt_file_data(None, receiver_asset["public"], app.config,
            file_data)

    logging.info(f"This is the key {key} , encrypted_key{encrypted_key} \
                and the s3_url {s3_url}")
    master_key, master_url = await asset_utils.master_url_n_key(
        app.config.ADMIN_ZERO_PUB, key, s3_url)

    ##Now this transaction should be signed by user

    create_asset_signer = ledger_utils.create_signer(issuer_nth_priv)

    ##for added security we will send a nonce signed by issuer account
    ##private key
    nonce = random.randint(2**20, 2**30)
    ##nonce signed by zerothprivate key and in hex format
    hex_signatures = signatures.ecdsa_signature(issuer_zeroth_priv, nonce)

    transaction_data = {
        "config": app.config,
        "txn_key": create_asset_signer,
        "batch_key": app.config.SIGNER,
        "key": encrypted_key,
        "url": encrypted_s3_url,
        "time": int(time.time()),
        "indiantime": upload_utils.indian_time_stamp(),
        "file_name": issuer_asset["file_name"],
        "file_hash": issuer_asset["file_hash"],
        "expired_on": expired_on,
        "master_key": master_key,
        "master_url": master_url,
        "scope": issuer_asset["scope"],
        "receiver_address": receiver_address,
        "issuer_address": issuer_address,
        "issuer_pub": issuer_nth_pub,
        "issuer_zero_pub": issuer_zeroth_pub,
        "signed_nonce": hex_signatures,
        "nonce": nonce,
        "issuer_child_zero_pub": issuer_asset.get("child_zero_pub"),
    }

    logging.info(transaction_data)
    transaction_ids, batch_id = await send_transfer_asset(**transaction_data)

    if transaction_ids:
        ##just because signatures are in bytes
        signed_nonce = transaction_data["signed_nonce"].decode()
        logging.info("Create Transaction has been created successfully")
        ##which imlies the transaction has been submitted successfully,
        ##now all the changes that are required to be done on the databse can
        ##be done
        ##Update users create_asset_idxs key on users entry will be updated by
        ## whomever will call this, because update can happend on pending_users
        transaction_data.update({
            "transaction_id": transaction_ids[0],
            "batch_id": batch_id,
            "signed_nonce": signed_nonce
        })

        [
            transaction_data.pop(field)
            for field in ["config", "txn_key", "batch_key"]
        ]
        await transfer_assets_query.store_transfer_assets(
            app, transaction_data)
        await assets_query.update_issuer_asset(app, issuer_address,
                                               transaction_data)
        await assets_query.update_receiver_asset(app, receiver_address,
                                                 transaction_data)
        ##TOFO update receiver_address asset and issuer_asset_Address in DB
        return True

    else:
        return False
    return