La función Python y Solidity keccak256 da resultados diferentes

Estoy trabajando en la implementación de una aplicación de contrato inteligente en la que existirán cálculos dentro y fuera de la cadena. Tendré que calcular la función Hash de varios enteros con Python y Solidity. Pero Solidity y Python dan resultados diferentes respectivamente, como se muestra a continuación.

Código de solidez:

La salida para (a=1, b=2, c=3) es: 49776295142305522338649292811956300178326541500117443588869412604416814650524

Código Python:

La salida para (a=1, b=2, c=3) es: 45637690538541992090000098772847886457082422231295691457910964509567538102535

Necesito entender cómo Solidity codifica los enteros de entrada y los pasa a la función hash. ¿Cómo se podría hacer esto en Python?

Respuestas (2)

Verificaría la biblioteca Web3.py, específicamente la funciónWeb3.soliditySha3

Esto funcionará para calcular el hash que necesita:

from web3 import Web3

print(int(Web3.soliditySha3(['uint256', 'uint256', 'uint256'], [1 ,2, 3]), 16))
Tenga en cuenta que esto cambiará en v4, que ahora se lanza en versión beta. soliditySha3devolverá un objeto similar a bytes, por lo que haría:print(Web3.toInt(Web3.soliditySha3(...)))
Da el siguiente error, parece que tengo que instanciar la clase Web3 y no hay una opción de constructor vacía allí. TypeError: se debe llamar al método no vinculado soliditySha3() con la instancia Web3 como primer argumento (en su lugar, se obtuvo la instancia de la lista)
Creé una instancia por: w3 = Web3 (TestRPCPProvider()). y después de eso todo funciona ahora. Muchas gracias a todos.
parece romper cambios entre versiones. Como dijo @carver, también tendrá que cambiar a usar Web3.toInt en lugar de int() porque soliditySha3 devuelve un objeto similar a bytes en v4

A partir de la v5 de la biblioteca Web3.py, haría:

from web3 import Web3, EthereumTesterProvider

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

49776295142305522338649292811956300178326541500117443588869412604416814650524

También está esto:

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

49776295142305522338649292811956300178326541500117443588869412604416814650524