Die Python- und Solidity-Funktion keccak256 liefert unterschiedliche Ergebnisse

Ich arbeite an der Implementierung einer intelligenten Vertragsanwendung, in der On- und Off-Chain-Berechnungen vorhanden sein werden. Ich muss die Hash-Funktion mehrerer Ganzzahlen mit Python und Solidity berechnen. Aber Solidity und Python liefern jeweils unterschiedliche Ergebnisse, wie unten gezeigt.

Soliditätscode:

Die Ausgabe für (a=1, b=2, c=3) ist: 49776295142305522338649292811956300178326541500117443588869412604416814650524

Python-Code:

Die Ausgabe für (a=1, b=2, c=3) ist: 45637690538541992090000098772847886457082422231295691457910964509567538102535

Ich muss verstehen, wie Solidity die Eingabe-Ganzzahlen codiert und an die Hash-Funktion weitergibt. Wie könnte dies in Python geschehen?

Antworten (2)

Ich würde mir die Web3.py-Bibliothek ansehen, insbesondere die FunktionWeb3.soliditySha3

Dies funktioniert zum Berechnen des benötigten Hashs:

from web3 import Web3

print(int(Web3.soliditySha3(['uint256', 'uint256', 'uint256'], [1 ,2, 3]), 16))
Beachten Sie, dass sich dies in v4 ändern wird, das jetzt als Beta veröffentlicht wird. soliditySha3gibt ein Byte-ähnliches Objekt zurück, also würden Sie Folgendes tun:print(Web3.toInt(Web3.soliditySha3(...)))
Es gibt den folgenden Fehler, es scheint, dass ich die Web3-Klasse instanziieren muss und es dort keine leere Konstruktoroption gibt. TypeError: ungebundene Methode soliditySha3() muss mit Web3-Instanz als erstes Argument aufgerufen werden (stattdessen Listeninstanz erhalten)
Ich habe eine Instanz erstellt mit: w3 = Web3(TestRPCProvider()). und danach funktioniert jetzt alles. Vielen Dank an alle.
scheint wie Breaking Changes zwischen den Versionen. Wie @carver sagte, müssen Sie auch auf die Verwendung von Web3.toInt anstelle von int() umsteigen, da soliditySha3 in v4 ein Byte-ähnliches Objekt zurückgibt

Ab v5 der Web3.py-Bibliothek würden Sie Folgendes tun:

from web3 import Web3, EthereumTesterProvider

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

49776295142305522338649292811956300178326541500117443588869412604416814650524

Das gibt's auch:

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

49776295142305522338649292811956300178326541500117443588869412604416814650524