Dies ist keine Frage zu dem Problem, dass Ethereum einen nicht standardmäßigen sha3 verwendet . Ich habe die richtige JS-Hashing-Bibliothek gefunden und kann übereinstimmende Hashes in JS und Solidity für Byte-Strings erhalten. Was ich mich frage, ist, wie man ein uint darstellt, wenn man es an die JS-Hash-Bibliothek übergibt, damit es zu demselben Hash führt, der von Solidity sha3 erstellt wird.
JS
'0x' + keccak(
1
)
// 0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470
Solidity
sha3(
1
);
// 0x5fe7f977e71dba2ea1a68e21057beebb9be2ac30c6410aa38d4f3fbe41dcffd2
Jehans Antwort ist großartig, aber wir müssen noch etwas erklären: Warum sha3(1)
produziert Solidity b10e2d...fa0cf6
?
Dies liegt daran, dass die sha3-Funktion von solidity ihre Eingaben basierend auf den Argumenttypen hasht . Daher erzeugt der Wert 1
einen anderen Hash, wenn er als bytes8
, bytes16
, bytes32
, usw. gespeichert wird. Da sha3(1)
er 1
als Zahlenliteral übergeben wird, wird er in den kleinsten erforderlichen Typ uint8
1 konvertiert .
8 Bit passen in 2 Hex-Zeichen, wenn Sie also Ihre Eingabe auf 2 Zeichen auffüllen, erhalten Sie das gleiche Ergebnis in web3:
Javascript:
web3.sha3(leftPad((1).toString(16), 2, 0), { encoding: 'hex' })
// 5fe7f977e71dba2ea1a68e21057beebb9be2ac30c6410aa38d4f3fbe41dcffd2
Ebenso können Sie die Zahl auf die Soliditätsseite werfen:
Solidität:
// uint is equivalent to uint256
sha3(uint(1))
// b10e2d527612073b26eecdfd717e6a320cf44b4afac2b0732d9fcbe2b7fa0cf6
Javascript:
// note that the value is padded by 64 characters to fit 256 bits
web3.sha3(leftPad((1).toString(16), 64, 0), { encoding: 'hex' })
// b10e2d527612073b26eecdfd717e6a320cf44b4afac2b0732d9fcbe2b7fa0cf6
BigNumber
Typen:Sie funktionieren nicht automatisch mit web3.sha3
. Sie müssen sie zuerst in Hex umwandeln.
Solidität:
sha3(uint(100 ether))
// c7cc234d21c9cfbd4632749fd77669e7ae72f5241ce5895e410c45185a469273
Javascript:
// the .slice is to remove the leading '0x'
web3.sha3(leftPad(web3.toHex(web3.toWei(100)).slice(2).toString(16), 64, 0), { encoding: 'hex' })
// c7cc234d21c9cfbd4632749fd77669e7ae72f5241ce5895e410c45185a469273
Ich habe eine kleine Bibliothek geschrieben, die eine Version davon bereitstellt web3.sha3
, die genau dem Verhalten von sha3
in Solidity entspricht. Hoffentlich klärt das all Ihre Hashing-Probleme :). https://github.com/raineorshine/solidity-sha3
Solidity verwendet intern HEX-Werte.
> web3.sha3(web3.toHex(1))
"5fe7f977e71dba2ea1a68e21057beebb9be2ac30c6410aa38d4f3fbe41dcffd2"
Die sha3-Funktion von Solidity hasht die Byte-Darstellung eines uint. Das heißt, die Zahl in Hex (Basis 16), aufgefüllt auf 32 Bytes. 32 leere Bytes in Hex-Darstellung sind 64 Nullen.
Um dies in JS zu tun, können wir das berüchtigte Left-Pad-Paket verwenden:
const jsHashWeb3 = web3.sha3(leftPad((1).toString(16), 64, 0), { encoding: 'hex' })
// b10e2d527612073b26eecdfd717e6a320cf44b4afac2b0732d9fcbe2b7fa0cf6
sha3(1)
. Könntest du erklären?
0x5fe7f9...dcffd2
b10e2d...fa0cf6
eth
keccak256
liefert identische Ergebnisse wie Solidity,sha3
daher gilt alles in diesem Thread fürkeccak256
.