Obtener ID de método "hash de Keccak" en Python

Estoy tratando de derivar el ID del método, el hash Keccak (SHA-3), en Python para poder llamar a las funciones de mis contratos una vez que se implementen como se detalla en la documentación de ABI: https://github.com/ethereum /wiki/wiki/Ethereum-Contrato-ABI

Esto detalla cuál 0xcdcd77c0debería ser el ID derivado para la función con la firmabaz(uint32,bool)

He intentado replicar esto usando el módulo python sha3 ( 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'

¿Cómo puedo obtener los primeros cuatro bytes de esto en el formato correcto para usarlos como firma de método en una transacción? Convertir este resumen a hexadecimal no parece dar la firma correcta.

Ethereum utiliza 256 bits. Si el sha3 de Python hashlib hubiera sido el mismo que el Keccak de Ethereum, la llamada debería haber sido: s = hashlib.sha3_256(). Si considera actualizar su publicación para enfocarse en el problema de la biblioteca incorrecta (no en el uso incorrecto de la misma al mismo tiempo), entonces s.hexgiest() de su mensaje es'af54f249a9bc75430f5d7fcc6a2154e9f76ac500e4094c7a2167e43ff7fc53f7'

Respuestas (1)

Con una versión reciente (> = 1.0) de pysha3, puede recrear la ID del método con:

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

Si su pysha3 es antiguo (p. ej., anclado en pysha3==0.3), necesita:

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

Explicación: después de que Ethereum adoptara lo que entonces era el candidato más reciente para SHA3, se cambió el estándar. Lo que usa Ethereum ahora se llama Keccak en lugar de SHA3.

¡Gracias! Mi PC tenía la versión anterior. Un poco molesto que este sea el caso, supongo que eventualmente tendré que implementar una verificación para ver qué versión usar.
Sí, supongo que podrías hacer:try: from sha3 import keccak_256 except ImportError: from sha3 import sha3_256 as keccak_256
Algo por el estilo, solo necesito volver a trabajar en mi código de verificación de dependencia normal, creo.
Solo para notar que al ejecutar lo anterior experimenté lo siguiente: TypeError: Unicode-objects must be encoded before hashing, resuelto simplemente con "baz(uint32,bool)".encode('utf-8').keccak_256("baz(uint32,bool)".encode('utf-8')).hexdigest()