¿Es posible crear un hash único dentro de geth?

Cuando hacemos una llamada de transacción, obtenemos el hash de la transacción de inmediato. Como se mencionó aquí , no pudimos obtener el hash de la transacción dentro de la función del contrato. ¿Sería buena idea establecer una variable del contrato con el valor hash de la transacción justo después de que se haya generado?

 > myContract.hello();
"0x41f6c6fbdfd4184172d61b390922270db087519137c43d3052fbad33876964f7"
> myContract.setUniqueHash("0x41f6c6fbdfd4184172d61b390922270db087519137c43d3052fbad33876964f7");

Objetivo: quiero usar un valor hash único dentro de mi contrato como clave. Establecer externamente un valor único parece más eficiente en cuanto al gas.

[Q1] Dentro de la consola geth, ¿es posible crear un hash único? En caso afirmativo, podría enviarlo a mi contrato como un argumento en lugar de un hash de transacción.

¿Lo siguiente podría ayudar? web3.sha3("Print(helloWorld)")como un hash único. En el peor de los casos, tal vez pueda agregar un archivo en ipfs y usar su hash como clave.

[Q2] ¿Hay alguna forma de crear un hash único dentro de la solidez?

Una pregunta sobre algo relacionado es "Cómo generar un número aleatorio" ethereum.stackexchange.com/q/191 . Puede usar una técnica similar para generar un hash único.

Respuestas (2)

Si el hash no necesita ser perfectamente aleatorio, en lugar de eso, solo desea una identificación única garantizada, puede hacer sha3un nonce o, para ser más abstracto, concatenar los datos que se enviaron con la transacción.

uint nonce;
...
bytes32 unique = sha3(block.number, msg.data, nonce++)`

Depende de las propiedades que necesite en el hash resultante.

sha3se puede usar para generar índices propios en asignaciones, como este ejemplo de cadenas propias:

contract OwnedIndex {

    mapping (bytes32 => string) ownedString;

    function set(string _str)
    {
        // Generates a key unique to sender and string
        ownedString[sha3(msg.sender, _str)] = str;
    }

    function clear(string _str)
    {
        // Must be the origional sender to generate key to delete
        delete ownedString[sha3(msg.sender, _str)];
    }
}
¿Es posible llamar a algo como: "web3.sha3(block.number, msg.data, nonce++)" dentro de geth, creo que solo acepta cadenas? @o0ragman0o
Esto parece funcionar: web3.eth.sign(eth.accounts[0], web3.sha3("Some text"), nonce);nonce => web3.eth.getBlock(5).nonce¿verdad? @o0ragman0o
Lo siento, creo que te he desviado del camino con esa pregunta (ahora eliminada). web3.sha3(...)debería ser todo lo que necesitas. Es posible que deba investigar un poco para generar identificaciones únicas a partir de fuentes pseudoaleatorias. Tal vez solo web3.sha3(Math.random()).

La respuesta a la pregunta del título es no, no es posible crear un hash en Solidity que estés seguro de que será único , al menos dada la posibilidad de huérfanos de bloques y reorganizaciones .

Los usuarios pueden pasar un nonce a la transacción, pero a menos que confíes en ellos, no puedes estar seguro de que no pasarán el mismo dos veces. Si está creando su ID completamente en función de los datos proporcionados por el usuario, es posible que intenten malintencionadamente obtener ID que otros usuarios esperan que se asignen a datos diferentes.

Si no le preocupan las reorganizaciones, simplemente puede incrementar un número dentro del contrato. Este número identificará de manera única un solo registro en cualquier bloque dado. Sin embargo, si ese bloque queda huérfano, puede terminar identificando un registro diferente en el bloque competidor que termina en la cadena más larga. Esto puede hacer que sea un inconveniente crear una aplicación que lo use, ya que es posible que deba manejar el ID creado por una transacción que cambia después de que ya lo haya mostrado o procesado.

Si el registro que está creando debe ser único en su contrato según los datos que contiene, simplemente debe codificar los datos en el contrato para crear una identificación que lo identifique de manera única. Hashing es bastante barato en comparación con el almacenamiento de datos, por lo que los costos de gas normalmente no deberían ser prohibitivos. Esto también significa que sabe qué identificación tendrá el registro antes de enviar la transacción, lo que puede facilitar el seguimiento.

Si un registro con el mismo contenido debe poder crearse varias veces, cada una con un nuevo registro, es posible que desee utilizar un nonce creado por el usuario, pero mezcle eso con la dirección del usuario. Haga que el contrato verifique que aún no tiene un registro con esa identificación, y si arroja un error. El nonce se puede rastrear en la aplicación, o puede usar algo que normalmente no colisionará accidentalmente, como un gran número aleatorio generado por el cliente o una marca de tiempo generada por el cliente. De esa forma, aunque un usuario podría crear transacciones que normalmente obtendrían la misma ID, un usuario no puede crear de manera malintencionada una ID que otro usuario espera que se le asigne a su registro. Esto también preserva la capacidad de su aplicación para predecir de antemano qué ID obtendrá la transacción que está enviando,