¿Podemos llamar a una función constante sin gastar gas dentro de una función de transacción?

Tengo una lista ordenada ordenada que contiene alrededor de 1000 elementos. Cuando recibo un artículo nuevo, mi objetivo es empujar el artículo a la lista manteniendo el orden ordenado. Entonces, si recibo un valor muy pequeño, debo iterar toda la lista para encontrar la cola de la lista.

El objetivo de la función constante es devolver la ubicación del índice para que se inserte la función de transacción.

La iteración (iterateListToFindPushIndex()) podría verse así:

struct Interval { 
  uint32 num;  //contained value.
  uint32 next; //points to next node on the linkedlist.
}

prevNode     = self.list[self.head]; //head of the list, largest value.
currentNode  = self.list[prevNode.next];
while( true ) {
  if( s > currentNode.num ){ 
    //self.list.push(Interval( { num: s, next: prevNode.next }) );
    //prevNode.next = uint32(self.list.length - 1);
    return prevNode.next; 
//returned indexed would be use in transaction function to insert intem into the correct location.
  }
  prevNode         = currentNode;
  currentNode      = self.list[currentNode.next];
}

Como sabemos cuando llamamos a una función constante, no cuesta nada y es de uso gratuito. Entonces, cuando encuentre la ubicación del índice a través de una función constante, no me costará gasolina.

function iterateListToFindPushIndex() constant returns(uint index){}
function func(intervalNode storage self) { 
  index = iterateListToFindPushIndex();
  self.list.push(Interval( { num: s, next: index }) )
}

Dentro de una función de transacción, cuando itero a través de mi lista aunque no cambie ningún almacenamiento de memoria, me cuesta gasolina adicional.

Entonces, ¿es posible llamar a una función constante sin gastar gasolina dentro de una función de transacción?

Gracias por su valioso tiempo y ayuda.

Respuestas (3)

Llamar a una constantfunción dentro de una transacción cuesta tanto como llamar a una no constantfunción dentro de una transacción. Lo constantque significa es que, dado que no altera el estado, su nodo local puede ejecutarlo y decirle el resultado sin necesidad de una transacción. Esto no cuesta gasolina porque solo su nodo tiene que ejecutar el cálculo.

Puede usar esto para ahorrar combustible en una transacción ejecutando primero la función constante desde su código JavaScript para obtener un resultado y luego pasando ese resultado como un parámetro a la transacción. Sin embargo, a menos que su contrato confíe en la persona que lo envía, aún debe verificarlo dentro de la transacción. Esto aún puede ser útil: si tiene una lista ordenada y desea saber dónde colocar un elemento, puede ser útil verificarlo en el lado del cliente y encontrar el índice x, pasar el índice xcomo un parámetro de transacción, luego dejar el código de contrato inteligente en la transacción verifica que el artículo en x-1viene antes de lo que está agregando y el artículo en x+1viene después.

Una trampa es que los datos pueden cambiar entre leer un resultado y enviar una llamada que lo contenga a la cadena de bloques en una transacción, en cuyo caso su transacción fallará y tendrá que enviarla nuevamente.

Relacionado con su sugerencia: por ejemplo, el mejor bloque de blockchain es 100. Pero mi nodo se encuentra actualmente en blockNumber 90 (básicamente detrás de blockchain). Entonces, cuando haga su sugerencia, el nodo del cliente puede obtener el índice de la lista hasta los primeros 90 bloques y perder los elementos generados en los 10 bloques restantes. ¿Es posible verificar que el número de bloque de mi nodo coincida con el mejor y más reciente número de bloque de la cadena de bloques? Si es posible, su solución funcionará. De lo contrario, el cliente no se dará cuenta de que su nodo se sincroniza con la cadena y puede encontrar el índice de la lista en función de los elementos que faltan. @Edmund Edgar
Tenga en cuenta que parece una pregunta diferente, pregunté en un hilo diferente: ethereum.stackexchange.com/q/13863/4575
Si solicita "más reciente", obtendrá el bloque más reciente que su nodo puede ver. Por lo general, su nodo no debería estar más de unos segundos por detrás del resto de la red una vez que haya terminado de sincronizarse. Si está constantemente atrasado, como usted dice, es posible que desee hacer otra pregunta.
Estoy trabajando en una cadena privada. Como puede ver en la imagen (ethereum.stackexchange.com/q/13863/4575), a veces mi nodo se retrasa 10 o tal vez más bloques. Pero en algún momento todo en el último bloque. Por lo tanto, es difícil confiar en el comportamiento del nodo en mi caso. @Edmund Edgar

Como sabemos cuando llamamos a una función constante, no cuesta nada y es de uso gratuito.

Esta afirmación es falsa. Me gustaría saber cuál es la fuente de esta declaración, ya que debería corregirse.

Una transacción, por definición, cambia el estado de la cadena de bloques de Ethereum, mueve ETH o bits.

Cuando las transacciones realizan cálculos, utilizan el tiempo de CPU de los mineros. No solo los mineros, sino también el tiempo de CPU de todos los nodos completos de Ethereum, ya que actualmente todas las transacciones se reproducen en todos los nodos. Los mineros no son sin fines de lucro y, naturalmente, le cobran por el servicio de usar su CPU. No importa si las subllamadas o los cómputos mutan el estado (no constante) o no tienen efectos secundarios (constante) si el resultado total de la transacción es el cambio de aunque sea un bit en la cadena de bloques de Ethereum.

Llamar a la función constante es gratis solo si consulta el estado desde su nodo local, ya que entonces no está haciendo una transacción, solo está haciendo una llamada de consulta RPC a su base de datos local de blockchain.

Votado a favor. Las llamadas constantes pueden ser fáciles de perder algunos puntos; una explicación relacionada es ethereum.stackexchange.com/questions/10906/…
En otras palabras, ¿la escritura y la lectura de bots cuestan gasolina?

La función de llamada constantpodría aumentar su consumo de gas. El EVM ahora necesita buscar otra función y agregarla a la pila para calcular el valor correcto. Echa un vistazo al siguiente código, por ejemplo:

contract Child{

    uint8 public age = 1;


    function birthDay() { <-- gas used: 26933 
        age = age + 1;
    }

    function nextYearIllBe() constant returns (uint8){
        return age + 1;
    }


    function newBirthDay() { <-- gas used 26991
        age = nextYearIllBe();
    }
}

Ambas funciones de cumpleaños realizan la misma operación de adición y almacenamiento, pero la newBirthDayfunción también agrega una llamada adicional a su flujo.