Kann eine Funktion auf die Genehmigung eines anderen Benutzers warten?

Ich habe eine einfache Funktion in Vertrag x, die einen Wert von Vertrag y subtrahiert. Ist es möglich, dass Vertrag x eine Nachricht an den Benutzer von Vertrag y sendet und eine Bedingung festlegt, die der Vertrag nicht ausführt, bis der Benutzer die Aktivität bestätigt?

Danke

Antworten (2)

Sie können diesen Workflow erstellen, aber wenn alles in der Kette ist, müssen Sie alle Teile erstellen, und jeder Schritt im Workflow erfordert eine Transaktion, also eine für „Aktion anfordern“ und eine für „Aktion bestätigen“.

Außerdem können Verträge keine E-Mails oder ähnliches senden. Das Senden einer Nachricht an den Benutzer von Vertrag y bedeutet also, etwas in das Ereignisprotokoll zu schreiben oder eine Nachricht in eine Warteschlange einzufügen und dann zu hoffen, dass der Empfänger sie liest. (Sie können natürlich einen Off-Chain-Dienst haben, der auf dieses Ereignis lauscht und E-Mails oder was auch immer sendet.)

Wenn Sie die Benachrichtigung ohnehin außerhalb der Kette durchführen müssen, könnte ein interessantes Muster darin bestehen, dass der Initiator einige Daten signiert, in denen die Aktion angefordert wird, und diese dann nicht an den Vertrag, sondern direkt an den Benutzer sendet, der bestätigen soll. Dieser Benutzer sendet dann eine einzelne Transaktion an die Blockchain, die msg.sender prüft, um den Bestätiger zu validieren, und dann die signierten Daten mit ecrecover prüft, um die Aktion des Initiators zu validieren.

Angenommen, Sie haben diesen Vertrag, der nur von updaterder Adresse von aktualisiert werden kann:

Vertrag StringStore {
    string public myString;
    öffentlichen Updater adressieren; // Dies ist die Adresse eines Vertrags

    Funktion StringStore(Adresse _updater) {
        updater = _updater;
    }

    Funktion setString(string neueString) {
        if (updater != msg.sender) throw;
        myString = newString;
    }
}

Nehmen wir nun an, dass die updaterAdresse von dieser Vertrag ist, der jeden Listener über erforderliche Aufrufe benachrichtigt:

Vertrag HoldOff {
    Adresse öffentlicher Eigentümer;

    Ereignis LogRequest(
        Adressanforderer,
        Adressziel,
        Bytes msgData);

    Funktion HoldOff() {
        Eigentümer = msg.sender;
    }

    Funktion requestCall(Adresse Ziel, Bytes msgData)
        gibt zurück (bytes32-Schlüssel) {
        LogRequest(msg.sender, Ziel, msgData);
    }

    Funktion doCall(Adresse Ziel, Bytes msgData)
        gibt zurück (boolesch) {
        if (Eigentümer != msg.sender) throw;
        return target.call(msgData);
    }
}

Und schließlich, um einen Test in Truffle zu machen , der EtherPudding verwendet :

Vertrag('HoldOff', Funktion(Konten) {

  var Eigentümer = Konten[0];
  var Anforderer = Konten[1];

  it("sollte eine verzögerte Aktion haben können", function() {

    var holdOff = HoldOff.deployed();
    var stringStore = StringStore.deployed();
    var msgData;

    Rückgabe stringStore.myString()
      .then(Funktion (myString) {
        assert.equal(myString, "", "sollte zu Beginn ein leerer String sein");

        // Der Anforderer sammelt die erforderlichen Daten
        // Wir erhalten die Anrufdaten. Bei EtherPudding müssen wir .contract machen, sonst ist es ein direkter .getData()
        msgData = stringStore.contract.setString
          .getData("Hallo Welt", { from: requester });

        // Wir wollen nur Ereignisse, die in neuen Blöcken kommen
        var blockNumber = web3.eth.blockNumber;

        // Anfragender fordert...
        holdOff.requestCall(stringStore.address, msgData, { from: requester });
        // Siehe https://gist.github.com/xavierlepretre/afab5a6ca65e0c52eaf902b50b807401
        // Warten wir, bis das Ereignis ausgelöst wird, was bedeutet, dass der Block abgebaut wurde.
        return getEventsPromise(holdOff.LogRequest(
          {},
          { from: web3.eth.blockNumber }));
      })
      .then(Funktion (Ereignisse) {
        // Tatsächlich gab es nur ein Ereignis.
        return holdOff.doCall(
            events[0].args.target,
            events[0].args.msgData,
            { von: Eigentümer });
      })
      .then(Funktion (tx) {
        // Siehe https://gist.github.com/xavierlepretre/88682e871f4ad07be4534ae560692ee6
        web3.eth.getTransactionReceiptMined(tx) zurückgeben;
      })
      .then(Funktion (Empfang) {
        // Stellen wir sicher, dass es aktualisiert wurde.
        return stringStore.myString();
      })
      .then(Funktion (myString) {
        console.log(myString);
        assert.equal(myString, „Hello World“, „sollte aktualisiert worden sein“);
      });
  });
});
Übrigens, das gesamte Projekt ist hier github.com/b9lab/hold-off