Wie kann ich den gleichen resultierenden Hash von Keccak-256 () in solidity und web3.sha3() in web3 erhalten?
IN solidity mit keccak256 ( address ) und mit web3.sha3 ( address ) ergibt unterschiedliche Ergebnisse.
In web3 ist das Adressfeld eine Zeichenfolge, während es sich in Solidity um eine Adresse handelt.
Wie kann ich eine Web3-Zeichenfolge in ein Adresstypfeld konvertieren?
Ich habe versucht, das Feld für den Adresstyp solide in eine Zeichenfolge zu konvertieren, und ich habe immer noch unterschiedliche Ergebnisse in Hashes erhalten.
Für die Adresse, um in der Solidität zu stechen, habe ich verwendet
function toString(address x) returns (string) {
bytes memory b = new bytes(20);
for (uint i = 0; i < 20; i++)
b[i] = byte(uint8(uint(x) / (2**(8*(19 - i)))));
return string(b);
}
web3.sha3()
verwendet einen Codierungsparameter, um anzugeben, dass Sie eine Hex-Adresse übergeben:
address_string = '0x5b2063246f2191f18f2675cedb8b28102e957458';
web3.sha3(address_string, {encoding: 'hex'});
Als allgemeine Randnotiz: Sie müssen Gaskosten bezahlen, um in Solidity kundenspezifische Arbeiten durchzuführen, also arbeiten Sie, wenn möglich, am besten auf der Javascript-Seite.
Sie können auch lokal keccak256( address )
eine constant
Solidity-Funktion ausführen und das Ergebnis dann an eine Transaktion übergeben. Natürlich ist dies für die Produktion nicht sicher, wenn Sie dies den Benutzern in ihrem Browser überlassen.
Die neueste Version von web3 hat eine web3.utils.soliditySha3
Funktion, die Sie verwenden können, die das Hashing von Solidity nachahmt:
address = '0x407D73d8a49eeb85D32Cf465507dd71d507100c1';
hash = web3.utils.soliditySha3(address);
Es ist oft einfach, das ABI-Codierungs-Toolkit zu verwenden, das sogenanntes "Tight Packing" oder gegebene Argumente durchführt. Sie können dies mit einer integrierten Funktion durchführen.
In Solidität
/**
* A test method exposed to be called from clients to compare that ABI packing and hashing
* is same across different programming languages.
*
* Does ABI encoding for an address and then calculates KECCAK-256 hash over the bytes.
*
* https://web3js.readthedocs.io/en/v1.2.0/web3-utils.html#soliditysha3
*
*/
function calculateAddressHash(address a) public pure returns (bytes32 hash, bytes memory data) {
// First we ABI encode the address to bytes.
// This is so called "tight packing"
// https://web3js.readthedocs.io/en/v1.2.0/web3-utils.html#soliditysha3
bytes memory packed = abi.encodePacked(a);
// Then we calculate keccak256 over the resulting bytes
bytes32 hashResult = keccak256(packed);
return(hashResult, packed);
}
In JavaScript/TypeScript
import { soliditySha3 } from 'web3-utils';
// Sign address
const { signature, v, r, s } = signAddress(user2);
// This is an address is a hexadecimal format
const ourData = user2.toLowerCase();
// https://web3js.readthedocs.io/en/v1.2.0/web3-utils.html#id23
// Convert address to bytes using "tight packing"
// and them calculates keccak-256 over the resulting bytes
const ourHash = soliditySha3({t: 'address', v: user2 });
// We hash data in similar in TypeScript and Solidity
const { hash, data } = await tokenSwap.calculateAddressHash(user2);
assert(ourData.toLowerCase() == data.toLowerCase());
assert(ourHash.toLowerCase() == hash.toLowerCase());
Schnitzer
Richard Horrocks