Was sind die Laufzeitumfänge in der Vertragsinteroperabilität?

Es scheint, dass es einen Umfang pro Vertrag gibt. Diese Subtilität wird auf Reddit diskutiert:

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

Ich kann diese Behauptung mit einer emulierten js-Blockchain reproduzieren

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

Nach dem Aufruf von doit() gibt die Eigenschaft Server#alive einen Fehler zurück. Interessanterweise kann ich es nicht auf Ropsten ausführen, weil das Gas, das benötigt wird, um aus der Ferne Selbstmord zu rufen und zu werfen, über dem Blocklimit liegt.

Dieser Umfang pro Vertrag ist meiner Meinung nach ein schwerwiegender Fehler, wenn es um die Interoperabilität von Verträgen geht. Was ist der Grund dafür und vor allem wo ist es angegeben?

Sieht aus wie ein Fehler in der Javascript-EVM.

Antworten (2)

Dies sieht nach einem Fehler in der Javascript-EVM aus. Ich kann bestätigen, dass sich der obige Code so verhält, wie Sie es auf dem Javascript-EVM beschreiben.

Dieses Verhalten steht jedoch im Gegensatz zu dem, was das Yellow Paper ( Abschnitt 6 ) beschreibt. Die EVM sollte einen fortlaufenden "Transaktionszustand" aufrechterhalten, der nur dann "festgeschrieben" wird, wenn der ursprüngliche Aufruf/die ursprüngliche Methode/Nachricht vollständig ausgeführt wird. Wenn der ursprüngliche Aufruf/die ursprüngliche Methode/Nachricht irgendwie unterbrochen wird (kein Benzin mehr, „werfen“, was Solidity zu einem ungültigen Sprungziel kompiliert, glaube ich usw.), dann wird der „Transaktionsstatus“ nicht festgeschrieben – er wird effektiv zurückgesetzt. (Ich könnte mich in der tatsächlichen Mechanik der Implementierung irren. Das heißt, EVMs können den EVM-Status während der Transaktion tatsächlich ändern und dann alle vorgenommenen Änderungen rückgängig machen. Aber es läuft auf dasselbe hinaus.)

Der laufende "Transaktionsstatus" enthält eine Liste von Verträgen, die während dieser Transaktion Selbstmord begangen haben. Ein Wurf sollte diese Verträge daher nicht in den Selbstmord treiben – er sollte sie live und in dem Zustand belassen, in dem sie sich vor der Transaktion befanden.

Ich habe den folgenden Code auf meiner privaten Entwicklungskette (Solidity 0.4.4 und Parity 1.4.6) ausgeführt und kann bestätigen, dass er sich so verhält, wie ich es erwarte – wie im Yellow Paper beschrieben:

client.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;
    }
}

server.sol

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

Nach dem Bereitstellen von Server und dem anschließenden Bereitstellen von Client (zeigt auf den bereitgestellten Server) und nach dem Aufrufen von Client#doit() ist Server immer noch ein gültiger Vertrag und Server#alive ist immer noch wahr.

Kann dies 2018 im Ethereum-Mainnet passieren?)) etherscan.io/tx/…

Wenn in einem Aufrufstapel von Nachrichtenaufrufen ein throwauftritt, bleibt der Zustand aller aufgerufenen Nachrichten nach dem throw-ing -Nachrichtenaufruf intakt, während alle Aufrufe unter den Aufrufstapeln zurückgesetzt werden.

Die Auswirkung einer Ausnahme ist, dass der aktuell ausgeführte Aufruf gestoppt und rückgängig gemacht wird (dh alle Änderungen des Zustands und der Salden werden rückgängig gemacht) und die Ausnahme auch durch Solidity-Funktionsaufrufe „aufgebläht“ wird

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

IMHO: Dies ist sicherlich eine Eigenart, die zu ernsthaften Problemen führen wird.
Hut ab vor „I-am-Jam“ auf reddit

Der von Ihnen zitierte Abschnitt der Dokumentation erklärt die Funktionalität angemessen, aber Ihr Kommentar "Der Status aller aufgerufenen Nachrichten nach dem Auslösen des Nachrichtenaufrufs bleibt intakt" ist irreführend. Ein Throw setzt alle Änderungen des Transaktionsstatus auf diesen Punkt zurück und stoppt die Ausführung der Transaktion ("aufgewirbelt" bis zum Aufrufer), sodass keine weiteren Änderungen möglich sind. OP hat einen Fehler in der Javascript-EVM gefunden. Ich habe bestätigt, dass sich Parity so verhält, wie ich es beschreibe und wie es das Gelbbuch beschreibt.
Also haben Sie einen Fehler gemeldet?