Python Web3 – Get Non-Packed SolidityKeccak Hash

keccaksha3web3.pyweb3js

For

Web3.solidityKeccak(['bool'], [True])

, Python Web3 yields: 0x5fe7f977e71dba2ea1a68e21057beebb9be2ac30c6410aa38d4f3fbe41dcffd2

This matches the output of keccak256(abi.encodePacked(true)) in Solidity. However, I want the output of keccak256(abi.encode(true)) because my contract has to deal with variably-sized data structures.

In Web3 JS, I could get the correct output (0xb10e2d527612073b26eecdfd717e6a320cf44b4afac2b0732d9fcbe2b7fa0cf6) using:

web3.utils.soliditySha3(web3.eth.abi.encodeParameters(['bool'], [true]))

How do I get it from Python Web3?

Of course I don't need the hash of a boolean. This just serves as an example for easy verification that the correct encoding was used.

Best Answer

I just found out how it can be done: There is a python library for Solidity ABI encoding and we can abuse the fact that compact ABI encoding of bytes is the identity.

The library can be installed with:

pip install eth_abi

Its documentation is found here: https://eth-abi.readthedocs.io/en/latest/

After importing the library via

import eth_abi

, the hash can be computed as follows:

abiEncoded = eth_abi.encode_abi(['bytes', 'bytes32'], [input1, input2])
hash = w3.solidityKeccak(['bytes'], ['0x' + abiEncoded.hex()])