Error: invalid ApplicationArgs when using PyTEAL + Python SDK

Sorry to disturb you, to pass arguments I tried as you have shown me, so through the call: transaction.ApplicationNoOpTxn(sender, params, index, app_args), where app_args is an array in which the values are encoded in bytes; and in Smart Contract as following:
biometric = Txn.application_args[0]
cryptoKey = Txn.application_args[1]
idUtente = Txn.application_args[2]
idUtente_tally = App.globalGet(idUtente)

But I got the following error already in this call transaction.ApplicationCreateTxn(sender, params, on_complete, approval_program, clear_program, global_schema, local_schema): “logic eval error: invalid ApplicationArgs index 2”.

Where is the problem? How can I solve?
Thank you.

Here are some questions to help your debug:

If none of those work, can you paste a minimum working example that exhibits the issue (i.e., the code of an example that you make as short as possible but that exhibits the issue)?

  • Yes, I’m sure I passed 3 arguments from Python program, as following:
    biometric = bytearray(biometric)
    cryptoKey = bytearray(cryptoKey)
    idUtente = hashLib.md5NameAssets("JohnSmith".encode('utf-8'))
    This is my md5NameAssets function:
    def md5NameAssets (data):
    m = hashlib.md5()
    m.update(data)
    return m.hexdigest()
    and I set these three value in app_args = [bio, cry, idUt]
  • For the following points, I didn’t import a Node algorand, so, if I don’t wrong, I can’t use tools like goal or tealdbg. I tried to use dryrun_debug, it gives me an error, but the transaction is null:
    SOURCE Dryrun results...
    { "error": "Dryrun Source[0]: 1 error",
    "protocol-version": "https://github.com/algorandfoundation/specs/tree/ac2255d586c4474d4ebcf3809acccb59b7ef34ff",
    "txns": null}
    Then, in the result, a string like JSON format where “message” is analyzed, but I don’t know how to debug through it.

Can you export the transaction in base64 and post it here (if it’s not confidential)?
Assuming the transaction is tx:


tx_bytes = algosdk.encoding.msgpack_encode(tx)
b64 = base64.b64encode(tx_bytes)
print(b64.decode('ascii'))

[edit: there was a typo b64..decode and actually the Python SDK directly returns base64, so this would have been sufficient:

print(algosdk.encoding.msgpack_encode(tx))

]

no problem to share.
Is it something like this?:
aTZSaGNHRnd4QjRDSUFJQkFDWUJDRWxrVlhSbGJuUmxJa0FBQVFBaktEWWFBbVJtSWtPa1lYQm5jNEdqYm5WcEFhUmhjR3h6Z3FOdVluTUJvMjUxYVFHa1lYQnpkY1FHQWlBQkFTSkRvMlpsWmMwRDZLSm1kczRBMUhod28yZGxicXgwWlhOMGJtVjBMWFl4TGpDaVoyakVJRWhqdFJpa3M4aE95QkR5TFU4UWdjc1BjZkJacDZ3ZzNzWXZmM0RsQ1RvaW9teDJ6Z0RVZkZpamMyNWt4Q0FITmdHNkE5WFk4QnRmd3FPaXlteHM0cm9nb0luRVlUVlhWSzZMWmdvRGVhUjBlWEJscEdGd2NHdz0=
I’m not sure because this didn’t work

with this error: TypeError: a bytes-like object is required, not 'str' for base64.b64encode(…) function

When I decode your transaction I get:

$ base64 -d <<< aTZSaGNHRnd4QjRDSUFJQkFDWUJDRWxrVlhSbGJuUmxJa0FBQVFBaktEWWFBbVJtSWtPa1lYQm5jNEdqYm5WcEFhUmhjR3h6Z3FOdVluTUJvMjUxYVFHa1lYQnpkY1FHQWlBQkFTSkRvMlpsWmMwRDZLSm1kczRBMUhod28yZGxicXgwWlhOMGJtVjBMWFl4TGpDaVoyakVJRWhqdFJpa3M4aE95QkR5TFU4UWdjc1BjZkJacDZ3ZzNzWXZmM0RsQ1RvaW9teDJ6Z0RVZkZpamMyNWt4Q0FITmdHNkE5WFk4QnRmd3FPaXlteHM0cm9nb0luRVlUVlhWSzZMWmdvRGVhUjBlWEJscEdGd2NHdz0=  | base64 -d | msgpacktool -d -b32
{
  "apap:b32": "AIQAEAIAEYAQQSLEKV2GK3TUMUREAAABAARSQNQ2AJSGMISD",
  "apgs": {
    "nui": 1
  },
  "apls": {
    "nbs": 1,
    "nui": 1
  },
  "apsu:b32": "AIQACAJCIM======",
  "fee": 1000,
  "fv": 13924464,
  "gen": "testnet-v1.0",
  "gh:b32": "JBR3KGFEWPEE5SAQ6IWU6EEBZMHXD4CZU6WCBXWGF57XBZIJHIRA====",
  "lv": 13925464,
  "snd:b32": "A43ADOQD2XMPAG27YKR2FSTMNTRLUIFARHCGCNKXKSXIWZQKAN4Q====",
  "type": "appl"
}

(msgpacktool is a tool installed when you install the Algorand software. You can use it inside github.com/algorand/sandbox too)

You see that you you don’t have the field apaa which is the field for the arguments (Transaction Reference - Algorand Developer Portal). This means that somewhere the arguments where not passed correctly.
Can you show your Python code?

PS: I’ve also moved it to a new topic as the previous one was resolved. To make things clearer for people later.

Yes I can show.
How can I show this with you? Do I copy main functions here?

If the functions are relatively short, copy them here between triplebackquotes like:

```py
print(“hello”)
```

which renders as:

print("hello")

If they are very long, you can use github gists.

Okay, perfect:
main function:

    # initialize an algodClient
    headers = {
        "X-API-Key": algod_token,
    }
    # Initialize an algod client
    algod_client = algod.AlgodClient(algod_token, algod_address, headers)

    creator_private_key = get_private_key_from_mnemonic(creator_mnemonic)
    user_private_key = get_private_key_from_mnemonic(user_mnemonic)

    # read teal program
    program_source = open(approval_program_source_initial, 'r').read()
    clear_state = open(clear_program_source, 'r').read()

    approval_program = compile_program(algod_client, program_source)
    clear_program = compile_program(algod_client, clear_state)

    # In this function I get biometrics from image (return array of value) 
    # and an array of random value
    biometric, cryptoKey = helper.bindBioCryptoKey()

    biometric = bytearray(biometric)
    cryptoKey = bytearray(cryptoKey)
    idUtente = hashLib.md5NameAssets("JohnSmith".encode('utf-8'))

    app_id = create_app(algod_client, creator_private_key, approval_program, clear_program, global_schema, local_schema)

    opt_in_app (algod_client, user_private_key, app_id)
    call_app (algod_client, user_private_key, app_id, [biometric, cryptoKey, idUtente])

Next, create_app function:

    def create_app(client, private_key, approval_program, clear_program, global_schema, local_schema):
    # define sender as creator
    sender = account.address_from_private_key(private_key)

    # declare on_complete as NoOp
    on_complete = transaction.OnComplete.NoOpOC.real

    # get node suggested parameters
    params = client.suggested_params()
    # comment out the next two (2) lines to use suggested fees
    params.flat_fee = True
    params.fee = 1000

    # create unsigned transaction
    txn = transaction.ApplicationCreateTxn(sender, params, on_complete, approval_program, clear_program, global_schema, local_schema)

    # sign transaction
    signed_txn = txn.sign(private_key)
    tx_id = signed_txn.transaction.get_txid()

    # send transaction
    client.send_transactions([signed_txn])    # HERE THE ERROR

    # await confirmation
    wait_for_confirmation(client, tx_id)

    # display results
    transaction_response = client.pending_transaction_info(tx_id)
    app_id = transaction_response['application-index']
    print("Created new app-id: ", app_id)

Rewrite here the error:
logic eval error: invalid ApplicationArgs index 2

Here Smart Contract code (in PyTeal)

from pyteal import *
def approval_program():

    biometric = Txn.application_args[0]
    cryptoKey = Txn.application_args[1]
    idUtente = Txn.application_args[2]
    idUtente_tally = App.globalGet(idUtente)

    on_creation = Seq ([
        App.localPut((Int(0)), Bytes("IdUtente"), idUtente_tally),
        Return(Int(1))
    ])
   

    program = Cond(
        [Int(1), on_creation]
    )

    return program

def clear_state_program():
    program = Seq([
        Return(Int(1))
    ])
    return program

if __name__ == "__main__":
    with open('mySmartContract_approval.teal', 'w') as f:
        compiled = compileTeal(approval_program(), Mode.Application)
        f.write(compiled)

    with open('mySmartContract_clearstate.teal', 'w') as f:
        compiled = compileTeal(clear_state_program(), Mode.Application)
        f.write(compiled)

are also application calls and do not have any arguments.

Ok, so I tried to add app_args in all calls and it occurred a new error: application args total length too long, max len 2048 bytes.
I think the problem is in biometric’s or cryptoKey’s or idUtente’s dimension.

Yes, the total size of all arguments should be less than 2048 bytes.

1 Like

I solved dimension problems, but I get error invalid : signature validation failed always in this call.

Which could be the problem?

Did you change the code above?
If yes, are you sure the transaction is signed with the private key of the sender/creator?

If it is the case:

  1. can you check whether you’re using the latest version of algosdk (python3 -m pip install py-algorand-sdk)?
  2. can you verify the arguments are bytes?
  3. can you copy the base64 of msgpack encoding of signed_txn here?

Maybe that problem is due to idUtente variable that wasn’t in bytes format.
Actually this problem occurres: logic eval error: cannot set key, A43ADOQD2XMPAG27YKR2FSTMNTRLUIFARHCGCNKXKSXIWZQKAN42W45FAI has not opted in to app 15770110, where that address is the creator/sender’s address.

For a stateful contract even the account that creates it, has to opt into the contract to use local storage. You are trying to store a value in local state in your contract. Do an opt in transaction before you set values in local state.

When you first create the contract check the app id which will be 0 on the first run (ie create tx) of the contract and the app id is == to 0. You can check this in the contract and just return 1 to let it create without setting any local state. Next do the opt in txn and set your local state.

The reason for this error is that in Python 3, strings are Unicode, but when transmitting on the network, the data needs to be bytes instead. We can convert bytes to string using bytes class decode() instance method, So you need to decode the bytes object to produce a string. In Python 3 , the default encoding is “utf-8” , so you can use directly:

b"python byte to string".decode("utf-8")

Python makes a clear distinction between bytes and strings . Bytes objects contain raw data — a sequence of octets — whereas strings are Unicode sequences . Conversion between these two types is explicit: you encode a string to get bytes, specifying an encoding (which defaults to UTF-8); and you decode bytes to get a string. Clients of these functions should be aware that such conversions may fail, and should consider how failures are handled.