bytes32 cadenas hexadecimales de la misma longitud cuestan diferente gas ¿por qué?

No puedo entender la diferencia de gas para el siguiente problema. Generé un valor hash sha256 y la salida que elegí para ser hexadecimal en minúsculas. Entonces, el valor de salida es una cadena hexadecimal de 64 caracteres. Luego guardé este valor en una variable bytes32 dentro de un contrato inteligente. El código del contrato inteligente es:

pragma solidity ^0.4.23;

contract Project {
    bytes32 public value;

    function addValue(bytes32 val) public {
        value = val;
    }
}

Usando remix, noté que la operación para agregar un valor costaba 43629 para algunos valores y 43693 para otros. Entonces, la diferencia es 64 de gas. ¿Alguien puede ayudarme a entender por qué sucede esto? Probé muchos valores y la diferencia fue de 64 gases, ¿fue aleatorio? También probé para almacenarlo como cadena. Luego, el costo fue constante para todas las entradas, tal vez porque los valores tienen la misma longitud, como dije, los valores de las entradas tienen 64 caracteres.

Solo una suposición, pero ¿la diferencia es cuántos bytes hay 0 en la entrada?
@smarx Lo probé para dos entradas que tienen siete ceros. Uno costó 43629 y el otro 64 de gasolina, más 43693, así que no creo que importen los ceros. Pero buena idea, no he pensado en comprobarlo antes de que lo notes.
Para aclarar, ¿está contando la cantidad de bytes completos que son 0, no solo la cantidad total de 0 que ocurren en la cadena hexadecimal? (Por ejemplo, 0x102030 no tiene bytes cero, pero 0x100020 tiene un byte cero).
@smarx ok, lo hice mal, conté el número de ceros, tonto de mí... Entonces, ¿quieres decir que debería convertirlo a binario y luego debería hacer equipos de 8 bits consecutivos y ver si un "equipo" tiene todos los bits 0? lo siento si mi inglés no es bueno
Bueno, hexadecimal está bien. Cada dos caracteres hexadecimales es un solo byte. Si tan solo compartiera los valores que está probando aquí, esto sería mucho más fácil.
@smarx for example a value that cost 43629 is "0x44c6a374366f345cec0fa7d98eddf8185a533d4f3922c9c9397c38e8a8f526e2" and the other with 64 less gas is "0xd5bf2cb491dd63f800373f16ab0fc486ffe040923587c00adcead3dc4a4544b6". Entonces, ¿los ceros consecutivos en la segunda entrada son el problema?
@smarx ¡Bravo! ¡Usted tenía razón! Ahora lo entiendo, lo divido en equipos de dos consecutivos para obtener un byte. luego veo cuantos equipos son solo ceros. Sí, la segunda cadena tiene un equipo de ceros, por lo que cuesta 64 menos. Luego inserto este "0x44c6a374366f345cec0fa7d98eddf8185a533d4f3922c9c9397c38e8a8f50000", que es la primera cadena con 4 ceros al final. Entonces 2 bytes cero y costaba 120 menos. ¡¡¡Gracias!!!
Debería haber costado 128 menos que un valor que no tenía ceros. Ver mi respuesta para un poco más de detalle.
@smarx, sé que está fuera de tema, pero ¿sabe por casualidad cuántos bytes cero pueden ocurrir en una salida de sha256? Si claro 128!
La salida de sha256 es de 256 bits, que son 32 bytes. Entonces puede haber hasta 32 ceros.

Respuestas (1)

Del papel amarillo :

Gtxdatazero 4 Pagado por cada cero byte de datos o código para una transacción.

Gtxdatanonzero 68 Pagado por cada byte de datos o código distinto de cero para una transacción

Entonces, si reemplaza un valor distinto de cero con un cero en los datos de su transacción, reducirá el costo en 64 (68-4).

Tenga en cuenta que los 0 consecutivos no necesariamente importan, solo si representan un byte completo. Es más fácil ver si separa los bytes: d5 bf 2c b4 91 dd 63 f8 00 37 3f 16 ab 0f c4 86 ff e0 40 92 35 87 c0 0a dc ea d3 dc 4a 45 44 b6. Entonces, el segundo valor que mencionó en su comentario tiene exactamente un byte cero.