¿Cuáles son las limitaciones para estimar Gas y cuándo su estimación sería considerablemente incorrecta?

web3.eth.estimateGasy JSON-RPC estimaGas se puede usar para ver cuánto gas debe especificarse para una transacción, antes de elaborar la transacción.

Dado que es una estimación, ¿hay alguna limitación? ¿En qué casos se debe confiar menos en su uso, ya que puede producir una estimación que no es significativa o precisa?

Respuestas (3)

estimaGas funciona simulando que la transacción realmente se incluyó en la cadena de bloques y luego devuelve la cantidad exacta de gas que se habría cobrado si esa operación simulada fuera real. En otras palabras, utiliza exactamente el mismo procedimiento que usaría un minero para calcular la tarifa real.

Dado este enfoque, un observador casual podría pensar que no hay limitaciones y que la estimación siempre será exactamente correcta. Desafortunadamente, estarían equivocados .

Imagine un contrato simple que verifica el hash de bloque más reciente y luego llama a otro contrato grande que consume mucha gasolina solo si el décimo bit en el hash de bloque es un 1. Si usa estimar Gas para medir el consumo de una transacción que llama a este contrato simple , su resultado dependerá completamente de si el bloque más reciente contenía un 1 en el décimo bit de su hash de bloque. Si se publica un nuevo bloque entre el momento en que llama a estimar Gas y el momento en que se incluye la transacción, su estimación tiene un 50 % de posibilidades de ser totalmente incorrecta . Esto puede parecer un ejemplo artificial, pero muchos contratos usan hash de bloque como fuente de entropía y cambian su comportamiento en función de cuál sea el hash. Así que esto es algo que definitivamente podría suceder en la naturaleza.

Pero se pone peor. ¿Qué sucede si el contrato que solicita su transacción cambia su comportamiento en función de las transacciones que se le envían? Ahora es posible que el consumo de gas sea diferente según el orden en que se enviaron las transacciones .

Por ejemplo, suponga que llamar a un contrato comúnmente llamado casi siempre cuesta solo unos pocos cientos de gasolina . Pero contiene una cláusula extraña en su código para que un mensaje firmado por una clave específica altere su comportamiento, haciendo que consuma millones de gasolina cada vez que se llama . La misma clave es entonces capaz de alterar el comportamiento de nuevo. Ahora el propietario de esa llave puede modificar a voluntad el consumo de gas del contrato. Si el propietario es un minero , podría usar este "contrato atrapado" para activar este comportamiento de desperdicio de gas al comienzo de cada bloque que calculan y desactivarlo al final. Siempre que nunca publiquen públicamente estas transacciones privadas, cada llamada de estimar Gas arrojará un valor bajo, mientras que cadala transacción enviada genuinamente costará millones de gasolina (que va directamente al bolsillo del minero). Con un diseño de contrato cuidadoso, ni siquiera tendrían que realizar los cálculos, porque saben cuál será el resultado. Y podrían ejecutar este "ataque de robo de tarifas" al azar , solo realizándolo ocasionalmente para que nadie se dé cuenta hasta que muchos usuarios hayan sido engañados.

Una vez más, este ejemplo es artificial. Pero el punto es que siempre debes considerar si un atacante tiene algo que ganar si haces una mala estimación . Si hay un vector posible, coloque código adicional en la parte de su aplicación para manejar la situación en la que su estimación es incorrecta. Una técnica simple que siempre debe usar es incluir un límite de gas sensato . De esa manera, hay al menos un límite superior de lo que puede hacer un atacante. Más allá de eso, recuerde que se llama llamada estimada de gas, no llamada máxima garantizada de gas, y sea razonable al confiar en ella.

tl;dr:
Si hay alguna forma de que las consecuencias de su transacción cambien dependiendo de cuándo o a quién se envíe, existe la posibilidad de que la estimación de Gas sea incorrecta en cantidades arbitrariamente grandes. Tome precauciones adicionales.

Gran respuesta. ¿Cómo pueden los mineros activar el comportamiento de desperdicio de gas y "nunca publicar públicamente estas transacciones privadas"? ¿O debería ser una pregunta aparte?
Por "nunca publicar públicamente" solo quiero decir que nunca envían las transacciones para que otros mineros las incluyan. Por supuesto, cuando incluyen la transacción de inicio/detención en su propio bloque, se publica como parte del bloque. Entonces, un análisis cuidadoso de la cadena de bloques aún detectaría lo que están haciendo. Solo quise decir que nunca "se arriesgan" sobre si alguien más puede incluir su transacción enviándola a través de la red p2p de la forma en que se enviaría una transacción normal. ¿Tiene sentido?
Si gracias. En tldr, "a quién se envía" no está tan claro, porque el "a" está fijo en la transacción. Por "a quién", ¿se refiere a su ejemplo de una transacción firmada por una clave específica?
La palabra clave es "enviado", no abordado: estaba hablando de qué minero procesa la transacción. Pero si esa parte es confusa, puedo intentar reformularla.
Si todo lo que quieres decir es el minero, creo que la reformulación sería mucho más clara :) ejemplo "... cambiar dependiendo de quién es el minero o cuándo se extrae"
No creo, el segundo ejemplo en la respuesta es 100% correcto. Si el minero altera el comportamiento al comienzo del cómputo del bloque y nunca publica, esto significa que si alguien hace la transacción, solo necesitará mucha gasolina si ese alguien hizo la transacción a este minero específico, ya que ahí es donde está la transacción malvada ( alterar la transacción) es. La probabilidad de que esto ocurra es muy baja. @eth que opinas?
@NikaKurashvili Tienes razón en que solo el minero específico puede aprovechar y sus posibilidades de minar un bloque son proporcionales a su tasa de hash. Pero lo que se describe no pretende ser un ataque que todos los mineros puedan realizar todo el tiempo. Nada inconsistente en lo que usted y la respuesta están diciendo.
El segundo ejemplo anticipó el principal problema de la red Ethereum hoy...

Una limitación que encontré, o al menos un aspecto digno de mención del método eth.estimateGas, es que solo funciona según lo previsto si la llamada real no arroja una excepción.

Esto bien puede ser un error en la versión actual de geth, pero lo que he encontrado es que una llamada a un método que arroja una excepción siempre arroja el mismo resultado de estimación de gas, que es un valor de 50000000 unidades de gas. A un precio de gasolina de 20000000000, mis llamadas estimadas de Gas arrojaban exactamente 1 éter, lo que parecía ser una cantidad enorme para una simple llamada que generaba una excepción.

Esto es un poco fastidioso, ya que no he encontrado una forma confiable de estimar el gas en transacciones que realmente lanzan una excepción (que consumen gas), pero al menos vale la pena saberlo ;-) Así que parece una buena idea de depurar.traceTransaction su transacción antes de estimar su consumo de gas para asegurarse de que no arrojará una excepción y no le dará una estimación de gas muy incorrecta.

Por cierto, este valor "50000000" parece ser el mismo que se usa para inicializar las variables relacionadas con el gas en el código fuente de la API go ( https://github.com/ethereum/go-ethereum/blob/master/eth/api .go ), lo que parece insinuar que esto es más un error que una característica ;-)

Votado a favor. Si puede, archívelo en github.com/ethereum/go-ethereum/issues (y actualice la respuesta con lo que sucede).
Curiosamente, en realidad usamos la función estimar Gas de esta manera a propósito para detectar si alguien ya había votado por una propuesta de DAO o estaba tratando de enviar DAO cuando estaba bloqueado. Dado que sabíamos que el contrato fallaría en esas circunstancias, estimaríamos Gas y, si consumiera todo el combustible, mostraríamos una advertencia en lugar de enviar el TX. Esto evitó que las personas intentaran votar dos veces / intentar enviar DAO en la interfaz, donde podíamos controlar la mensajería y, por lo tanto, reducir los correos electrónicos de soporte.

Una limitación (según mi propia observación, espero que alguien me corrija si no estoy entendiendo bien) es que incluso si estimateGaslas estimaciones son correctas, eso no le da el límite de gasolina que debe establecer al enviar su transacción.

El problema es que los reembolsos se acreditan solo al final de la transacción, por lo que si tiene una transacción que funciona y limpia algo de almacenamiento a medida que avanza, debe establecer un límite de gasolina lo suficientemente alto para hacer todo el trabajo sin el beneficio del reembolso.