6

I am working on implementing a smart contract application in which, on and off-chain calculations will exist. I will have to calculate the Hash Function of multiple integers with Python and Solidity. But Solidity and Python give different results respectively as shown below.

Solidity Code:

The Output for (a=1, b=2, c=3) is: 49776295142305522338649292811956300178326541500117443588869412604416814650524

Python Code:

The Output for (a=1, b=2, c=3) is: 45637690538541992090000098772847886457082422231295691457910964509567538102535

I need to understand how Solidity encodes the input integers and passes them to the hash function, How this could be done in Python?

Yilmaz
  • 1,580
  • 10
  • 24
Omnia Mahmoud
  • 63
  • 1
  • 3
  • Related: https://ethereum.stackexchange.com/questions/2632/how-does-soliditys-sha3-keccak256-hash-uints – eth Nov 17 '17 at 09:45

3 Answers3

4

I would check out the Web3.py library, specifically the function Web3.soliditySha3

This will work for computing the hash you need:

from web3 import Web3

print(int(Web3.soliditySha3(['uint256', 'uint256', 'uint256'], [1 ,2, 3]), 16))
natewelch_
  • 12,021
  • 1
  • 29
  • 43
  • 2
    Note that this will change in v4, which is now released in beta. soliditySha3 will return a bytes-like object, so you would do: print(Web3.toInt(Web3.soliditySha3(...))) – carver Nov 16 '17 at 18:33
  • It gives the following error, it seems I have to instantiate the Web3 class and there is no empty constructor option there. TypeError: unbound method soliditySha3() must be called with Web3 instance as first argument (got list instance instead) – Omnia Mahmoud Nov 17 '17 at 11:16
  • I created an instance by: w3 = Web3(TestRPCProvider()). and after that everything works now. Thank you all so much. – Omnia Mahmoud Nov 17 '17 at 12:03
  • seems like breaking changes between versions. Like @carver said, you'll also have to switch to using Web3.toInt instead of int() because soliditySha3 returns a bytes-like object in v4 – natewelch_ Nov 17 '17 at 13:25
2

As of v5 of the Web3.py library, you would do:

from web3 import Web3, EthereumTesterProvider

w3 = Web3(EthereumTesterProvider()) print(w3.toInt(w3.solidityKeccak(['uint256', 'uint256', 'uint256'], [1, 2, 3])))

49776295142305522338649292811956300178326541500117443588869412604416814650524

There's also this:

print(w3.toInt(w3.keccak(
    b'\x00'*31 + b'\x01' +
    b'\x00'*31 + b'\x02' +
    b'\x00'*31 + b'\x03')))

49776295142305522338649292811956300178326541500117443588869412604416814650524

1
from web3 import Web3
w3 = Web3(Web3.HTTPProvider('your network endpoints'))
w3.keccak(text='text_you_want_to_hash')