Esta no es una pregunta sobre el problema con Ethereum usando un sha3 no estándar . Encontré la biblioteca de hashing JS correcta y puedo obtener hashes coincidentes en JS y Solidity en cadenas de bytes. Lo que me pregunto es cómo representar un uint al pasarlo a JS hash lib para que resulte en el mismo hash creado por Solidity sha3.
JS
'0x' + keccak(
1
)
// 0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470
Solidity
sha3(
1
);
// 0x5fe7f977e71dba2ea1a68e21057beebb9be2ac30c6410aa38d4f3fbe41dcffd2
La respuesta de Jehan es excelente, pero debemos explicar una cosa más: ¿Por qué produce sha3(1)
in solidity b10e2d...fa0cf6
?
Esto se debe a que la función sha3 de solidity codifica sus entradas en función de los tipos de argumento . Por lo tanto, el valor 1
generará un hash diferente si se almacena como bytes8
, bytes16
, bytes32
, etc. Dado sha3(1)
que se pasa 1
como un número literal, se convierte en el tipo necesario más pequeño, uint8
1 .
8 bits caben en 2 caracteres hexadecimales, por lo que si rellena su entrada con 2 caracteres, obtendrá el mismo resultado en web3:
JavaScript:
web3.sha3(leftPad((1).toString(16), 2, 0), { encoding: 'hex' })
// 5fe7f977e71dba2ea1a68e21057beebb9be2ac30c6410aa38d4f3fbe41dcffd2
Del mismo modo, puedes lanzar el número en el lado de la solidez:
Solidez:
// 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
tipos:No funcionan automáticamente con web3.sha3
. Tienes que convertirlos a hexadecimal primero.
Solidez:
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
Escribí una pequeña biblioteca que proporciona una versión web3.sha3
que coincide exactamente con el comportamiento de sha3
Solidity. Esperemos que esto aclare todos sus problemas de hash :). https://github.com/raineorshine/solidity-sha3
Solidity usa valores HEX internamente.
> web3.sha3(web3.toHex(1))
"5fe7f977e71dba2ea1a68e21057beebb9be2ac30c6410aa38d4f3fbe41dcffd2"
La función sha3 de Solidity codifica la representación de bytes de un uint. Es decir, el número en hexadecimal (base 16), rellenado a 32 bytes. 32 bytes vacíos en representación hexadecimal son 64 ceros.
Para hacer esto en JS, podemos utilizar el infame paquete del panel izquierdo:
const jsHashWeb3 = web3.sha3(leftPad((1).toString(16), 64, 0), { encoding: 'hex' })
// b10e2d527612073b26eecdfd717e6a320cf44b4afac2b0732d9fcbe2b7fa0cf6
sha3(1)
produce 0x5fe7f9...dcffd2
, no b10e2d...fa0cf6
como produce su código. ¿Podrías explicar?
ética
keccak256
produce resultados idénticos a los suyos,sha3
por lo que todo en este hilo se aplica akeccak256
.