Hey! Sie scheinen aus United States zu kommen, möchten Sie auf die Englisch Webseite wechseln?
Switch to Englisch site
Skip to main content

Mit Raspberry Pi Ethereum entdecken, Teil 3: Transaktionen auf unserer privaten Blockchain

Pi_Ethereum3_1fa72be7f086b5bdc06c00c480ed56dd73840657.jpg

Mitteltransfer, Mining von Ether und Ausführen von Smart Contracts.

In Teil 1haben wir uns zunächst die Grundlagen von Ethereum angesehen und die Geth-Client-Software installiert, bevor wir dann ein Konto erstellt und einige grundlegende Tests durchgeführt haben.In Teil 2 haben wir unsere eigene private Blockchain mit anfangs zwei als Peers konfigurierten Knoten angelegt.

In diesem Beitrag geht es um die tatsächliche Transaktion mit der Blockchain. Zunächst transferieren wir einige vorab zugewiesene Mittel und schürfen ein bisschen Ether. Dann fahren wir mit Ausführung eines Smart Contract fort und das ist tatsächlich einer der interessantesten Aspekte im Zusammenhang mit Ethereum.

Einrichten/Aktualisieren von Geth

Wir hatten uns für einen Beginn von Grund auf und die Neuinstallation unseres Raspberry Pi entschlossen. Also war zunächst Raspbian Lite geladen worden, bevor wir die übliche „sudo apt-get“-Aktualisierung sowie das Upgrade von „sudo apt-get dist“ durchgeführt haben.

Sollten Sie einen aktuellen Build des Geth-Client ausführen wollen, hat es den Anschein, als wäre zum Zeitpunkt der Niederschrift dieses Beitrags die im Raspbian-Paket enthaltene Version von Golang deutlich zu alt. Sollte sie installiert sein, muss sie zunächst entfernt werden:

$ sudo apt-get remove golang
$ sudo apt-get remove autoremove

Wenn Sie ganz von vorn beginnen, benötigen Sie Git und eine andere Abhängigkeit. Folgendermaßen kann eine Installation erreicht werden:

$ sudo apt-get install git golang libgmp3-dev

Anschließend kann es mit den Geth-Versionen im Vergleich mit den Golang-Versionen ein bisschen kniffelig werden. Im Zusammenhang mit dem Zweig der Geth-Version 1.8 scheint Golang 1.9.2 zu funktionieren, während jüngere Versionen sich als problematisch erweisen.

$ wget https://dl.google.com/go/go1.9.2.linux-armv6l.tar.gz
$ sudo tar -C /usr/local -xzf go1.9.2.linux-armv6l.tar.gz
$ export PATH=$PATH:/usr/local/go/bin

Außerdem scheint es sinnvoll zu sein, Ihrem ~/.profile die letzte Zeile (zum Aktualisieren des Pfads) hinzuzufügen, damit das neu installierte Go-Binary stets sofort nach Anmeldung zur Verfügung steht.

Ist Golang installiert, können wir uns jetzt um die Geth 1.8-Quellen, den Build und die Installation kümmern.

$ mkdir src
$ cd src
$ git clone -b release/1.8 https://github.com/ethereum/go-ethereum.git
$ cd go-ethereum
$ make
$ sudo cp build/bin/geth /usr/local/bin/

Dieser Prozess läuft im Großen und Ganzen wie in Teil 1 beschrieben ab, aber es sollte auch darauf hingewiesen werden, wie man spätere Geth-Builds zum Laufen bringt, weil dazu die Installation einer jüngeren Version von Golang außerhalb der Paketverwaltung erforderlich ist.

Erstellen der privaten Blockchain

EERP3_admin-peers1_3a1346491671ace1c70f06381093a8799d006ea9.png

Die in Teil 2 erläuterten Schritte sollten befolgt werden, um die private Blockchain zu erstellen und sie mit zwei Knoten zu initialisieren. Es scheint deshalb unnötig, die Schritte hier noch einmal ausdrücklich aufzuführen.

Sobald Sie so weit sind, sollte die Ausgabe der oben angezeigten ähnlich sein, wenn Sie für die einzelnen Knoten admin.peers von der Geth-Client-Konsole aus ausführen. Damit wird angezeigt, dass es sich bei den beiden Knoten in der Tat um Peers handelt.

Mitteltransfer und Mining

EERP3_balance-pi1_03c3497ad8f282eb010c81fc33a50069c9a086d2.png

Fangen wir also damit an, den Stand der für die jeweiligen Knoten konfigurierten Konten zu prüfen:

> web3.fromWei(eth.getBalance(eth.coinbase), “ether”)

Oben sehen wir das in Hinblick auf das Konto auf dem Pi, dem im Voraus keine Mittel zugewiesen worden waren.

EERP3_balance-snow1_480179d37e523fb228430b51a596f186664b7c78.png

Und wir sehen oben den Stand des auf einem Laptop-PC konfigurierten Kontos, dem im Voraus Mittel zugewiesen wurden.

Beachten Sie, dass dies die Umkehrung der Situation im vorherigen Beitrag ist, in dem beim Pi die Mittel im Voraus zugewiesen worden waren, aber nicht beim Laptop-PC. Tatsächlich spielt es keine Rolle, ob es so oder so abläuft, und natürlich können Sie beiden Konten (oder vielen) im Voraus Mittel zuweisen, wenn Sie die Blockchain initialisieren.

In unserem Fall senden wir demnach Ether vom Konto auf dem Laptop-PC zum Konto auf dem Pi. Als Erstes bestätigen wir einfach die Adresse des Letzteren.

EERP3_eth-coinbase1_ffbadc0e0a6d0bf734fd990808e8666d68b35133.png

Dann greifen wir vom Laptop-PC aus auf die Konsole zu:

> var pi = "0x1a49bcee41bff051b8ffd0a01d4a3be4485fd030";

> personal.unlockAccount(eth.coinbase, "")

> eth.sendTransaction({from: eth.coinbase, to: pi, value: web3.toWei(0.1, "ether")})

Mit dieser ersten Zeile wird eine praktische Variable für die Adresse des Kontos auf dem Raspberry Pi definiert. Anschließend schaltet die zweite das Konto auf dem Laptop-PC frei und mit der dritten wird Ether vom Laptop-PC zum Pi übermittelt.

EERP3_send-ether1_25b461e5ba417a06806aef7883d535243076e74d.png

Wenn wir an diesem Punkt den Stand der Konten auf den einzelnen Systemen prüfen würden, wäre er nach wie vor unverändert, weil keine Synchronisation stattfindet. Die können wir auslösen, indem wir vom Laptop-PC aus einen Miner starten:

> miner.start()

EERP3_generate-dag2_0d186248ffd5933633f0bf2d5795295e9269e927.png

Zunächst muss das DAG (eine gerichtete Diagrammdatenstruktur zum Aufzeichnen von Arbeitsnachweisen) generiert werden. Im Anschluss daran wird mit dem Mining und der Synchronisierung begonnen.

EERP3_pi-block-sync-start1_3bb32334add9fb9961fa9981ea77df0c86d862fa.png

Oben sehen wir die Konsolenausgabe auf dem Pi, sobald die Synchronisierung beginnt.

EERP3_pi-get-balance-synced1_100eb97299d210507c15ab76fef505b15270ee3c.png

Und wenn wir jetzt den Kontostand auf dem Pi prüfen, können wir feststellen, dass wir Mittel erhalten haben!

Da wir keinen Wettbewerb haben und das Mining nicht schwierig ist, dauert es nicht lange, bis der Miner auf dem Laptop mehr Ether für uns geschürft hat, als wir im Voraus zugewiesen haben.

EERP3_laptop_mining_balance1_302dad459010e747eaae69afeda27dd1f3dfd97c.png

Zum Schluss können wir den Miner anhalten, indem wir in der Konsole Folgendes eingeben:

> miner.stop()

Beachten Sie, wie wir nur eine Miner-Instanz laufen lassen müssen, um uns einen Strom neuer Blöcke zu verschaffen. Diese Instanz kann, wie hier, auf einem in Hinblick auf Ressourcen weniger beschränkten System ausgeführt werden.

Unser erster Smart Contract

Als Nächstes bauen wir den Greeter, einen „Hello World“- Smart Contract in Ethereum. Beschrieben wird der Greeter als „intelligente digitale Einheit, die in der Blockchain existiert und in der Lage ist, mit allen, die mit ihm interagieren, je nach Eingabe Unterhaltungen zu führen.“

In Teil 1 haben wir festgestellt, wie Smart Contracts in einer Sprache namens Solidity geschrieben werden, die ganz ähnlich wie Java in Bytecode kompiliert wird. Für den Anfang installieren wir also einen geeigneten Compiler auf unserem Laptop-PC mit Ubuntu.

$ sudo add-apt-repository ppa:ethereum/ethereum
$ sudo apt-get update
$ sudo apt-get install solc

In unserem Fall war der erste Schritt nicht wirklich notwendig, da wir den PPA bereits bei der Installation von Geth entsprechend konfiguriert hatten.

Nehmen wir den folgenden Solidity-Code heran und speichern ihn in eine Datei namens Greeter.sol.

contract Mortal {
    /* Define variable owner of the type address */
    address owner;

    /* This function is executed at initialization and sets the owner of the contract */
    function Mortal() { owner = msg.sender; }

    /* Function to recover the funds on the contract */
    function kill() { if (msg.sender == owner) selfdestruct(owner); }
}

contract Greeter is Mortal {
    /* Define variable greeting of the type string */
    string greeting;

    /* This runs when the contract is executed */
    function Greeter(string _greeting) public {
        greeting = _greeting;
    }

    /* Main function */
    function greet() constant returns (string) {
        return greeting;
    }
}

Zum Kompilieren geben wir Folgendes ein:

$ solc -o target --bin --abi Greeter.sol

EERP3_solc_compile1_0e0cac750ce3d8112f2e3ef4b13d42b9efb68624.png

Dies führt zu einigen Warnungen, aber es wird ein Zielverzeichnis mit vier Dateien erstellt: je eine abi- und eine bin-Datei für die Greeter- und Mortal-Contracts. Wir benötigen sie für den Greeter-Contract, da dieser aus dem Mortal-Contract übernimmt.

Die einfachste Möglichkeit, diese in Geth zu laden, besteht darin, ein Skript zu erstellen, dem wir den Namen greeter.js geben. Werfen wir einen Blick auf die fertiggestellte Datei.

var greeterFactory = eth.contract([{"constant":false,"inputs":[],"name":"kill","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"greet","outputs":[{"name":"","type":"string"}],"payable":false,"stateMutability":"view","type":"function"},{"inputs":[{"name":"_greeting","type":"string"}],"payable":false,"stateMutability":"nonpayable","type":"constructor"}])

var greeterCompiled = "0x" + "608060405234801561001057600080fd5b5060405161039b38038061039b83398101806040528101908080518201929190505050336000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508060019080519060200190610089929190610090565b5050610135565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f106100d157805160ff19168380011785556100ff565b828001600101855582156100ff579182015b828111156100fe5782518255916020019190600101906100e3565b5b50905061010c9190610110565b5090565b61013291905b8082111561012e576000816000905550600101610116565b5090565b90565b610257806101446000396000f30060806040526004361061004c576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff16806341c0e1b514610051578063cfae321714610068575b600080fd5b34801561005d57600080fd5b506100666100f8565b005b34801561007457600080fd5b5061007d610189565b6040518080602001828103825283818151815260200191508051906020019080838360005b838110156100bd5780820151818401526020810190506100a2565b50505050905090810190601f1680156100ea5780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b6000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161415610187576000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16ff5b565b606060018054600181600116156101000203166002900480601f0160208091040260200160405190810160405280929190818152602001828054600181600116156101000203166002900480156102215780601f106101f657610100808354040283529160200191610221565b820191906000526020600020905b81548152906001019060200180831161020457829003601f168201915b50505050509050905600a165627a7a72305820467ac32dfa208b06ba97f3a7f72d039f2f912938b54b9881c603d80f6b004df40029"

var _greeting = "Hello DesignSpark!"

var greeter = greeterFactory.new(_greeting,{from:eth.accounts[0],data:greeterCompiled,gas:1000000}, function(e, contract){
    if(e) {
      console.error(e); // If something goes wrong, at least we'll know.
      return;
    }

    if(!contract.address) {
      console.log("Contract transaction send: TransactionHash: " + contract.transactionHash + " waiting to be mined...");

    } else {
      console.log("Contract mined! Address: " + contract.address);
      console.log(contract);
    }
})

Die ersten beiden Zeilen enthalten den Inhalt der abi- und der bin-Datei (diese beschreiben jeweils die Funktionen des Contract und sind der kompilierte Bytecode).

var greeterFactory = eth.contract(<contents of the file Greeter.abi>)

var greeterCompiled = "0x" + "<contents of the file Greeter.bin>"

Die Variable _greeting wird verwendet, um die Grußbotschaft zu definieren, die bei Ausführung des Contract zurückgegeben wird.

Als Nächstes sollten wir sicherstellen, dass wir einen Miner auf einem geeigneten Knoten betreiben und anschließend das Konto auf dem Computer freischalten, auf dem der Contract bereitgestellt werden soll. In unserem Fall haben wir erneut Miner.start() über die Geth-Konsole auf dem Laptop ausgeführt und beschlossen, den Contract über den Raspberry Pi bereitzustellen.

Auf dem Pi haben wir Folgendes eingegeben:

> personal.unlockAccount(eth.coinbase, "")

> loadScript("greeter.js")

EERP3_load-script1_01c87ab2ee3ec82dc32d6254c611a220bcc561fb.png

Erfolg! Unter den Synchronisierungsmeldungen können wir sehen, dass die Contract-Transaktion übertragen wird, ferner einen Hinweis auf das erwartete Mining und schließlich die Benachrichtigung, dass es abgeschlossen wurde.

Das können wir anschließend folgendermaßen überprüfen:

> eth.getCode(greeter.address)

EERP3_getCodeAddress1_3bacdf9503010d7d52ce8bd50e07953dff41bb82.png

Wenn wir den Kontostand auf dem Pi überprüfen, stellen wir fest, dass er geringfügig gesunken ist.

EERP3_getBalanceEnd1_d68a30801e9a1f78db1bed4b1ffde4f924896838.png

Die Mittel sind zum entsprechenden Miner übertragen worden, in unserem Fall in das Konto auf dem Laptop-PC.

Schließlich können wir den Contract folgendermaßen ausführen:

> greeter.greet();

EERP3_greeterGreet1_0cce5c8706b7dbae29a6b63d3cf9e55e77372866.png

Wie auf der Ethereum-Website vermerkt ist, erfolgt unmittelbar eine Rückgabe, weil der Aufruf nichts an der Blockchain ändert und keine Betriebskosten aufweist.

Dokumentation und Debugging

Es sollte beachtet werden, dass die Ethereum-Dokumentation stellenweise veraltet ist. Mit ihrer Verteilung über die Website und verschiedene Wiki-Seiten kann das einigermaßen verwirrend und manchmal sogar frustrierend sein, wenn die dokumentierten Schritte nicht funktionieren. Ein gutes Beispiel dafür ist das Contract-Tutorial im Geth-Wiki, das eine Solidity-Kompilierung aus Geth heraus vorschlägt – was allerdings nicht länger unterstützt wird.

Man kann wohl behaupten, dass Ethereum, wie viele Blockchain-Technologien, ein „schnell bewegliches Ziel“ darstellt, während regelmäßige Verbesserungen vorgenommen werden, um Effizienz und Widerstandsfähigkeit gegen Angriffe zu steigern. Deshalb kann die Dokumentation als solche hinterherhinken. Falls also etwas nicht funktioniert, prüfen Sie genau nach, um sicherzustellen, dass Sie die jeweils korrekte Dokumentation für die jeweilige Version von Ethereum verwenden. In privaten Testnetzwerken ist auch die Verwendung älterer Softwareversionen eine Möglichkeit, die sich allerdings wohl eher nicht für Netzwerke im echten Betrieb eignet.

Wenn Sie sich nicht sicher sind, wie genau die Lage der Dinge aussieht, hier ein praktischer Befehl zum Zurücksetzen der Blockchain:

$ geth removedb --datadir .designspark

Allerdings sollten Sie bedenken, dass anschließend eine Neuinitialisierung mit der benutzerdefinierten .json-Datei für das Netzwerk erforderlich ist.

Fazit

Fassen wir also zusammen:

    1. Wir haben gesehen, dass mit leichter Synchronisation theoretisch ein kleiner Knoten wie ein Raspberry Pi an einem großen Blockchain-Netzwerk teilhaben kann, zum Beispiel einem öffentlichen Netzwerk.
    2. Es wurde vorgeführt, wie ein privates Netzwerk eingerichtet werden kann.
    3. Wir haben Ether zwischen Konten übertragen, die auf Knoten in einem privaten Netzwerk konfiguriert waren. Anschließend haben wir einen Smart Contract kompiliert, ihn von einem Raspberry Pi aus bereitgestellt und anschließend eine Funktion aufgerufen.

Von diesem Punkt aus wäre es möglich, weitere Knoten hinzuzufügen und Contracts zu erstellen, die irgendeine nützliche Funktion ausführen und ihren Vorteil aus der von der Ethereum bereitgestellten Blockchain-Technologie ziehen.

  — Andrew Back

Open source (hardware and software!) advocate, Treasurer and Director of the Free and Open Source Silicon Foundation, organiser of Wuthering Bytes technology festival and founder of the Open Source Hardware User Group.