Keccak256 Hash creation

I want to create a keccak256 for on 4 different arguments that my function will receive:

myFunction((token: TealType.uint64, amount: TealType.uint64, payee: TealType.bytes, salt: TealType.bytes)

- First I want to generate a hash based on this message KECCAK256(BYTES("WithdrawSigned(token,payee,amount,salt)")),

PYTEAL CODE:

       withdrawSignedMethod.store(Bytes("WithdrawSigned(token,payee,amount,salt)")),
            withdraw_signed_method.store(Keccak256(withdrawSignedMethod.load())),

withdraw_signed_method.load() is a hash generated from Bytes("WithdrawSigned(token,payee,amount,salt)")

  • NOW, I want to create hash from the withdraw_signed_method hash and all other function parameters

PYTEAL CODE:

            initialS.store(withdraw_signed_method.load(), token, payee, amount, salt),
            signedMessage.store(Keccak256(initialS.load())),

But it doesn’t work and gives this error message:

  File "full-bridge.py", line 100, in withdraw_token
    initialS.store(withdraw_signed_method.load(), token, payee, amount, salt),
TypeError: store() takes 2 positional arguments but 6 were given

Could you please suggest a way using which I would be able to generate hash for all of my input parameters, I’m stuck on this problem for past 1 week?

Hi salman,

The store method takes a single argument, the value you wish to store in scratch space. Are you trying to hash the concatenated values of all the arguments? If so you can convert the arguments you passed there (if relevant) to bytes with Concat then hash the resulting bytes with Keccack256.

Ben

Can you share a possible syntax for that solution you are suggesting?

I tried the below mentioned solution but I feel it would concat the keys but I want to concat the values of the particular parameters.

            initialS.store(Concat(withdraw_signed_method.load(), Itob(token), payee, Itob(amount), salt)),
            signedMessage.store(Keccak256(initialS.load())),

Such as the input parameters:

token = 183838
payee = "X9JDHAS03...." 
amount = 100
salt = "SOME-HASH"

Now how can I concat the values of these input parameters and then pass it to Keccak256?

That looks approximately correct based on the description of what you want to do.

You can try logging the value with the Log method and inspect the result or call dryrun or use tealdbg to get a better sense of the output

Ben

Also how can I apply EcdsaRecover(App.globalGet(WithdrawSigned), signature),

EcdsaRecover(r, s) isn’t working with pyteal?

https://pyteal.readthedocs.io/en/stable/crypto.html#:~:text=EcdsaRecover

How can I install tealdbg?

This is described in the docs linked above

Also, respond to my question about ecdsaRecover(r,s) its not working for me.

You need to give four arguments to EcdsaRecover.

EcdsaRecover(EcdsaCurve.Secp256k1, d, id, r, s) matches Solidity ecdsa_recover(hash=d, v=id, r, s) in Units and Globally Available Variables — Solidity 0.8.15 documentation

Note also that you need Python3 3.10 and an up to date version of Pyteal to use EcdsaRecover.
Default versions of Python on Ubuntu 20.04 and macOS 12 are not sufficient (nor is the default version of Python for Homebrew).

I tried to execute tealdbg

./sandbox tealdbg debug bridge.teal

However, it cannot locate the bridge.teal file which I have placed in sandbox folder

You need to copy the bridge.teal file into sandbox using ./sandbox copyTo bridge.teal
Sandbox uses docker containers and so files need to be copied there.

1 Like

In my case I’m only aware of the ecdsa.recover(message, signature) function that solidity have and I just wanted to replicate that. However, even if I have to use this function with four arguments, then what would be the first two arguments? Since I know, (r,s) → (message, signarture)

I’ve written an example there:

See the README on how to use the code.

Importantly notice that you need to use Python 3.10 which is not the default on many OSes and which require manual installation.

Disclaimer: Do not use without full audit. The code was not audited.

Now for the details, ecdsa.recovery is a function of OpenZeppelin not a built-in solidity function:

You need to simulate it on Algorand as Algorand essentially only support the pure ecdsa_recover from Solidity (with the default recovery id 0/1/2/3 instead of 27/28/29/30).

In particular, r,s is not (message,signature).

Instead:

  • hash=d is the hash of the message
  • signature is a concatenation of r,s,v=id.

Can you please provide me the following that would work with algorand:

  1. Test message m
  2. Signature of that message
  3. Signer ethereum

The one provided in demo.py doesn’t work, I was able to run the example however, the signer is not recovered using the m, signature provided in demo.py file (b"openzeppeline", signature)

Also, please suggest me the following:

  • How to pass a different smartContract/wallet address to a my withdrawToken function so When I call the withdraw function it should tx tokens to a specified or given wallet address/smartcontract.
    I tried sending the address as an argument to the contract but it doesn’t read it correctly. Could you please suggest a good way to do it?

  • Second, please provide the chain ID of algorand’s testnet and mainnet.

algorand-devrel-demo-avm1.1/demo.py at 365acf147777337003ff535ec279a4255277cddb · fabrice102/algorand-devrel-demo-avm1.1 · GitHub is an example of message / signature / signer that works.
When you run the code, it works.

Note that the sender is an Ethereum address, not an Algorand address because Algorand addresses

What error do you see?
Be careful that in smart contracts, addresses must be written as 32-byte string, not as a base32 string with checksum (which is how you see addresses everywhere). See Overview - Algorand Developer Portal for details.

Also, if you plan to use inner transactions, the receiving address must be in the account list. See Smart contract details - Algorand Developer Portal.

There is no official chainID as Algorand is not an EVM chain.
On WalletConnect, we use:

(but there is no guarantee they’re unique unfortunately)

The code that you have written (demo.py) is in python, however, I’m using the Javascript sdk for interacting with the ECDSA contract. Here is how I’m interacting with the contract for signing the signature. Moreover, once the message is received in the contract, we apply keccak256 on the message to convert it to hash.

Let me know if you think there are few changes required?

let index = 98492040;
let token_address = 81317600;
account = [];
foreignApp = [];
foreignAssets = [];
foreignAssets.push(token_address);

// withdraw_token(_token,_amount, _receiver, salt, signature),
let action = "withdraw";
let amount = 100;
let message = "OpenZeppelin";
let signature = "5d99b6f7f6d1f73d1a26497f2b1c89b24c0993913f86e9a2d02cd69887d9c94f3c880358579d811b21dd1b7fd9bb01c1d81d10e69f0384e675c32b39643be8921b";
let signByte = ByteBuffer.fromHex(signature, undefined, undefined);
let signBuffer = signByte.buffer;

let appArgs = [];
appArgs.push(new Uint8Array(Buffer.from(action)))
appArgs.push(algosdk.encodeUint64(token_address));
appArgs.push(algosdk.encodeUint64(amount));
appArgs.push(new Uint8Array(Buffer.from(message)));
appArgs.push(new Uint8Array(Buffer.from(signBuffer)));

How can we define struct and enum - in Algorand?

such as :

    enum TokenData {
      tokenVal, 
      tokenBalance,
    }
    struct testInfo {
        address sender;
        TokenData data;  // defining enum into another structure
    }

    struct testConfig {
        address testToken;
        testInfo info;  // defining struct into another struct
    }

// defining mapping based on the structs

    mapping(address => testInfo) public testInfo;
    mapping(address => testConfig) public testConfig;

How can we achieve the above mentioned in Algorand? I don’t see anything in Algorand?

Also how can we replicate the Shift operators of Solidity in Algorand?

1 . >>
2 . <<
3 . &

Please provide relevant syntax in algorand

The bitwise operations in pyteal are detailed here: PyTeal Package — PyTeal documentation

for structs, there is nothing built in that will help with that yet