¿Cuáles son los alcances de tiempo de ejecución en la interoperabilidad de contratos?

Parece que hay un alcance por contrato. Esta sutileza se debate en Reddit:

https://www.reddit.com/r/ethereum/comments/5hiy29/solidity_throw_after_selfdestruct_why_does_the/

Puedo reproducir este reclamo con una cadena de bloques js emulada

contract Client{
    Server public s  = new Server();
    function doit(){
        s.homicide();
        throw;
    }
}
contract Server{ 
    bool public alive = true;
    function homicide(){
        Suicide();
        suicide(msg.sender);

    }
    event Suicide();
}

https://ethereum.github.io/browser-solidity/#version=soljson-v0.4.6+commit.2dabbdf0.js&optimize=undefined&gist=9a48bde651631bff7591817811610070

Después de llamar a doit(), la propiedad Server#alive devuelve un error. Curiosamente, no puedo ejecutarlo en Ropsten porque el Gas necesario para llamar al suicidio de forma remota y lanzar está por encima del límite de bloques.

Este alcance por contrato es un defecto grave cuando se trata de la interoperabilidad de los contratos, en mi humilde opinión. ¿Cuál es el motivo y, lo que es más importante, dónde se especifica?

Parece un error en Javascript EVM.

Respuestas (2)

Esto parece un error en Javascript EVM. Puedo confirmar que el código anterior se comporta como usted describe en Javascript EVM.

Sin embargo, ese comportamiento es contrario a lo que describe el Libro Amarillo ( sección 6 ). El EVM debe mantener un "estado de transacción" continuo que solo se "compromete" si la llamada/método/mensaje original se ejecuta hasta su finalización. Si la llamada/método/mensaje original se interrumpe de alguna manera (sin gasolina, "lanzar" que Solidity compila a un objetivo de salto no válido, creo, etc.), entonces el "estado de transacción" no se compromete, se revierte efectivamente. (Podría estar equivocado en la mecánica real de la implementación. Es decir, los EVM podrían modificar el estado de EVM durante la transacción y luego revertir los cambios realizados. Pero equivale a lo mismo).

El "estado de transacción" en curso incluye una lista de contratos que se han suicidado durante esa transacción. Por lo tanto, un lanzamiento no debería comprometer esos contratos con su suicidio: debería dejarlos vivos y en el estado en que se encontraban antes de la transacción.

Ejecuté el siguiente código en mi cadena de desarrollo privada (Solidity 0.4.4 y Parity 1.4.6) y puedo confirmar que se comporta como esperaba, como se describe en el Libro amarillo:

cliente.sol

pragma solidity ^0.4.4;
import "server.sol";
contract Client{
    Server public server;
    function Client(address _server) {
        server = Server(_server);
    }
    function doit(){
        server.homicide();
        throw;
    }
}

servidor.sol

pragma solidity ^0.4.4;
contract Server{ 
    bool public alive = true;
    function homicide(){
        alive = false;
        suicide(msg.sender);
    }
}

Después de implementar el servidor y, a continuación, implementar el cliente (que apunta al servidor implementado) y después de llamar a Client#doit(), Server sigue siendo un contrato válido y Server#alive sigue siendo verdadero.

¿Puede suceder esto en la red principal de Ethereum en 2018?)) etherscan.io/tx/…

si en una pila de llamadas de mensajesthrow ocurre una , entonces el estado de todos los mensajes llamados después de la llamada de mensajethrow -ing permanece intacto, mientras que todas las llamadas debajo de las pilas de llamadas se revierten.

El efecto de una excepción es que la llamada que se está ejecutando actualmente se detiene y se revierte (es decir, todos los cambios en el estado y los saldos se deshacen) y la excepción también se "burbujea" a través de llamadas a funciones de Solidity.

https://solidity.readthedocs.io/en/latest/control-structures.html#excepciones

En mi humilde opinión: Esta es sin duda una peculiaridad que dará lugar a algunos problemas graves.
Felicitaciones a "I-am-jam" en reddit

La sección de los documentos que cita explica adecuadamente la funcionalidad, pero su comentario "el estado de todos los mensajes llamados después de que el mensaje de lanzamiento permanece intacto" es engañoso. Un lanzamiento revierte todos los cambios de estado de la transacción a ese punto y detiene la ejecución de la transacción ("burbujeando" hasta la persona que llama), por lo que no es posible realizar más cambios. OP ha encontrado un error en Javascript EVM. He confirmado que Parity se comporta como lo describo y como describe el Libro Amarillo.
Entonces, ¿presentaste un error?