Функция Python и Solidity keccak256 дает разные результаты

Я работаю над реализацией приложения смарт-контракта, в котором будут существовать расчеты по цепочке и вне ее. Мне нужно будет вычислить хеш-функцию нескольких целых чисел с помощью Python и Solidity. Но Solidity и Python дают разные результаты соответственно, как показано ниже.

Код прочности:

Результат для (a=1, b=2, c=3): 49776295142305522338649292811956300178326541500117443588869412604416814650524

Код Python:

Результат для (a=1, b=2, c=3): 45637690538541992090000098772847886457082422231295691457910964509567538102535

Мне нужно понять, как Solidity кодирует входные целые числа и передает их хэш-функции. Как это можно сделать в Python?

Ответы (2)

Я бы проверил библиотеку Web3.py, в частности функциюWeb3.soliditySha3

Это будет работать для вычисления нужного вам хеша:

from web3 import Web3

print(int(Web3.soliditySha3(['uint256', 'uint256', 'uint256'], [1 ,2, 3]), 16))
Обратите внимание, что это изменится в версии 4, которая сейчас выпущена в виде бета-версии. soliditySha3вернет байтовый объект, поэтому вы должны сделать:print(Web3.toInt(Web3.soliditySha3(...)))
Это дает следующую ошибку, кажется, мне нужно создать экземпляр класса Web3, и там нет пустой опции конструктора. TypeError: несвязанный метод soliditySha3() должен вызываться с экземпляром Web3 в качестве первого аргумента (вместо этого получен экземпляр списка)
Я создал экземпляр: w3 = Web3 (TestRPCProvider()). и после этого все работает сейчас. Большое спасибо всем вам.
похоже на нарушение изменений между версиями. Как сказал @carver, вам также придется переключиться на использование Web3.toInt вместо int(), потому что soliditySha3 возвращает байтовый объект в версии 4.

Начиная с v5 библиотеки Web3.py вы должны сделать:

from web3 import Web3, EthereumTesterProvider

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

49776295142305522338649292811956300178326541500117443588869412604416814650524

Есть еще вот это:

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

49776295142305522338649292811956300178326541500117443588869412604416814650524