5

I am trying to derive the Method ID, the Keccak (SHA-3) hash, in Python so that I may call the functions of my contracts once they are deployed as detailed in the ABI documentation: https://github.com/ethereum/wiki/wiki/Ethereum-Contract-ABI

This details that 0xcdcd77c0 should be the ID derived for the function with the signature baz(uint32,bool)

I have tried to replicate this using the python sha3 module (https://pypi.python.org/pypi/pysha3):

>>> import sys
>>> import hashlib
>>> import sha3
>>> s = hashlib.sha3_512()
>>> s.update(b"baz(uint32,bool)")
>>>s.hexdigest()
'f1bb0cbc152d49505684ee7d2a37a860af1820ff8052ed6b32eddd3d82f97e89b24aac5ef334f94474264795cb7672339aecfc2cd2dc1cd0b87adccada2e7bc1'

How can I get the first four bytes from this in the correct format to use as a method signature in a transaction? Converting this digest to hex doesn't seem to give the correct signature.

eth
  • 85,679
  • 53
  • 285
  • 406
Samuel Barnes
  • 881
  • 10
  • 26
  • Ethereum uses 256-bit. Had Python hashlib's sha3 been the same as Ethereum's Keccak, the call should have been: s = hashlib.sha3_256(). If you consider updating your post to focus on the wrong library issue (not the wrong use of it at the same time), then s.hexgiest() of your message is 'af54f249a9bc75430f5d7fcc6a2154e9f76ac500e4094c7a2167e43ff7fc53f7' – Tankman六四 Feb 17 '18 at 10:17

1 Answers1

6

With a recent (>=1.0) version of pysha3 you can recreate the method ID with:

from sha3 import keccak_256
sha3_hash = keccak_256("baz(uint32,bool)").hexdigest()
method_id = "0x"+sha3_hash[:8]
print method_id

If your pysha3 is old (eg pinned atpysha3==0.3) you need:

from sha3 import sha3_256
sha3_hash = sha3_256("baz(uint32,bool)").hexdigest()
method_id = "0x"+sha3_hash[:8]
print method_id

Explanation: After Ethereum adopted what was then the most recent candidate for SHA3, the standard was changed. What Ethereum uses is now called Keccak instead of SHA3.

Edmund Edgar
  • 16,897
  • 1
  • 29
  • 58
  • Thanks! My PC had the older version. Bit of a pain that this is the case, I suppose I will eventually have to implement a check to see which version to use. – Samuel Barnes Jan 25 '17 at 09:49
  • 1
    Yes, I guess you could do: try: from sha3 import keccak_256 except ImportError: from sha3 import sha3_256 as keccak_256 – Edmund Edgar Jan 25 '17 at 09:56
  • Something along those lines, just need to rework my normal dependency checking code methinks – Samuel Barnes Jan 25 '17 at 16:07
  • 2
    Just to note upon executing the above I did experience the following: TypeError: Unicode-objects must be encoded before hashing , solved simply by "baz(uint32,bool)".encode('utf-8'). keccak_256("baz(uint32,bool)".encode('utf-8')).hexdigest() – Adam Lemmon Sep 27 '17 at 16:29