keccak3 in SOLIDITY und in WEB3 verschiedene Hashes für ein Adresstypfeld

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);
}
@RichardHorrocks Dies ist kein Problem zwischen sha3 und keccak256, sondern ein Problem mit der Codierung von Eingabeargumenten, daher glaube ich nicht, dass diese bestimmte Frage ein richtiges Duplikat ist
Okay, ja, sieht so aus, als hättest du wahrscheinlich Recht – entschuldige, dass du voreilig bist. +1 :-)

Antworten (4)

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 constantSolidity-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.

Was ist das Problem bei der Verwendung dieser für die Produktion? Es klappt.
Der resultierende Hash könnte geändert werden, bevor er an eine Transaktion übergeben wird. „Vertraue dem Kunden nicht“-Doktrin.

Die neueste Version von web3 hat eine web3.utils.soliditySha3Funktion, die Sie verwenden können, die das Hashing von Solidity nachahmt:

address = '0x407D73d8a49eeb85D32Cf465507dd71d507100c1';
hash = web3.utils.soliditySha3(address); 
Sie können eine Adresse in Solidity 0.5.0 nicht mehr hashen

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());