keccak3 en SOLIDITY y en WEB3 diferentes hashes para un campo de tipo de dirección

¿Cómo puedo obtener el mismo hash resultante de Keccak-256 () en solidity y web3.sha3() en web3?

IN solidity usando keccak256 (dirección) y usando web3.sha3 (dirección) da resultados diferentes.

En web3, el campo de dirección es una cadena, mientras que en Solidity es una dirección.

¿Cómo puedo convertir una cadena web3 en un campo de tipo de dirección?

Intenté convertir el campo de tipo de dirección en una cadena en solidez y aún recibí diferentes resultados en hashes.

Para la dirección de picar en la solidez que usé

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 este no es un problema de sha3 vs keccak256, es un problema de codificación de argumento de entrada, por lo que no creo que esa pregunta en particular sea un duplicado adecuado
De acuerdo, sí, parece que probablemente tengas razón, disculpas por adelantarte. +1 :-)

Respuestas (4)

web3.sha3()toma un parámetro de codificación para especificar que está pasando una dirección hexadecimal:

address_string = '0x5b2063246f2191f18f2675cedb8b28102e957458';
web3.sha3(address_string, {encoding: 'hex'});

Como nota al margen general: debe pagar los costos de la gasolina para realizar cualquier trabajo personalizado en Solidity, por lo que, cuando sea posible, es mejor que trabaje en el lado de JavaScript.

Además, puede realizar keccak256( address )una constantfunción de solidez localmente y luego pasar el resultado a una transacción. Por supuesto, esto no es seguro para la producción, si permite que los usuarios lo hagan en su navegador.

¿Cuál es el problema con el uso de esto para la producción? funciona.
el hash resultante podría modificarse antes de pasar a una transacción. Doctrina de "no confiar en el cliente".

La última versión de web3 tiene una web3.utils.soliditySha3función que puede usar que imita el hashing de Solidity:

address = '0x407D73d8a49eeb85D32Cf465507dd71d507100c1';
hash = web3.utils.soliditySha3(address); 
Ya no puede codificar una dirección en Solidity 0.5.0

A menudo es fácil de usar el kit de herramientas de codificación ABI que hace lo que se denomina "empaquetado ajustado" o argumentos dados. Puede realizar esto con una función integrada.

en solidez


 /**
   * 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);
  }


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