4

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.

  • 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
5

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.

  • 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 9: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 9:56
  • Something along those lines, just need to rework my normal dependency checking code methinks – Samuel Barnes Jan 25 '17 at 16:07
  • 1
    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

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.