Freitag, 24. August 2018

Kafka + Streaming + SQL = KSQL

Apache Kafka dürfte vielen Entwicklern vor allem als schnelles Queuing-System und als Quasi-Standard in diesem Bereich bekannt sein. Entsprechend wird es bisher vor allem als Puffer verwendet, um ankommende Daten vor der Verarbeitung zwischenzuspeichern oder einen möglichen Rückstau von Zwischenergebnissen und damit einen Nachrichtenverlust bei der Datenweitergabe zwischen verschiedenen Services zu vermeiden. 

Kafka-Mastermind Jay Kreps hat allerdings große Pläne für sein Werkzeug, mit dem Einbau von Stream-Verabeitungsmöglichkeiten und sogar einer KSQL genannten SQL-Schnittstelle, plant er mit Kafka nichts weniger, als Datenbanken neu zu erfinden (vgl. auch: Turning the Database inside out) und hat damit bereits einiges an Neugierde ausgelöst. In diesem Blog-Beitrag möchte ich daher einige erste Ideen und Möglichkeiten aber auch aktuelle Beschränkungen von KSQL diskutieren und wie alle Schritte nachvollziehbar auflisten, die zum direkten Ausprobieren notwendig sind.

 

Getting Started

Der einfachste Weg KSQL auszuprobieren, ist sicher die Verwendung der sog. Confluent Platform (Download hier), die alle dafür benötigten Einzelteile intergriert. Confluent (engl. für zusammenfließend bzw. -wachsend) ist übrigens die Firma, die Jay Kreps mit Kollegen nach seinem Weggang bei LinkedIn gegründet hat, um Kafka zu vermarkten.

Voraussetzung zum Betrieb der Plattform ist ein installiertes Java 8 (neuere Versionen funktionieren aktuell leider noch nicht), dann kann sie nach dem Herunterladen und Entpacken direkt auf der Kommandozeile aus dem bin-Ordner durch Aufrufen von ./confluent start ausgeführt werden. Danach steht die KSQL-Shell per ./ksql zur Verfügung. SQL-Entwickler sollten sich hier schnell heimisch fühlen, da die üblichen SQL-Befehle wie gewohnt funktionieren, bspw. show tables;

Um eine Tabelle anlegen zu können, werden in KSQL allerdings sog. Kafka-Topics benötigt, in die die gewünschten Daten eingespielt werden. Für alle, die Kafka bisher nicht kennen, Topics sind Kafkas Ansatz zur Datenspeicherung und zunächst im Prinzip nichts weiter als große Listen bestehend aus Key-Value-Paaren. Um Daten in ein solches Topic hineinzubekommen gibt es, wer hätte es gedacht, ein weiteres Kommandozeilen-Skript (kafka-console-producer), das wie folgt aufgerufen werden kann:

./kafka-console-producer --broker-list localhost:9092 --topic exams --property "parse.key=true" --property "key.separator=:" < /pfad/prüfungen.json

Der Einfachheit halber pipen wir die Daten, die wir in das Topic hineinlegen möchten, aus einer Datei names prüfungen.json heraus. Diese könnte bspw. folgende Daten für Prüfungsleistungen an einer Hochschule oder Universität enthalten:

1:{"id":"1","name":"Big Data","note":1.0,"matrikelnummer":"12345"}
5:{"id":"5","name":"Programmierung 1","note":2.0,"matrikelnummer":"23456"}
17:{"id":"17","name":"Programmierung 1","note":4.0,"matrikelnummer":"12345"}

Wie leicht erkennbar ist, enthält die Datei drei Zeilen mit Key-Value-Paaren, die jeweils durch einen Doppelpunkt unterteilt werden. Der Value besteht aus einem JSON-Eintrag, der die eigentlichen Prüfungsdaten enthält. In obigem Beispiel sind das eine ID, ein Vorlesungsname, die erreichte Note sowie die Matrikelnummer des Studierenden, der die Prüfung abgelegt hat, als Fremdschlüssel. Der Key des Key-Value-Paares sollte dabei immer dem Primärschlüssel des Values, in unserem Fall also der Prüfungs-ID, entsprechen.

Nun können wir in der KSQL-Shell nachschauen, ob alles korrekt funktioniert hat, in dem wir uns zunächst alle Topics ausgeben lassen: show topics;

Wir haben damit (endlich) eine schöne Möglichkeit, die in Kafka enthaltenen Daten zu erkunden. Taucht dort nämlich das Topic mit dem zuvor gewählten Namen exam auf, können wir uns auch seinen Inhalt folgendermaßen anzeigen lassen: print 'exams' from beginning;

Doch... die Abfrage scheint hängen zu bleiben..? DON'T PANIC, it's not a bug, it's a feature. Da Topics im Real-Betrieb normalerweise fortlaufend mit Daten gefüttert werden, sind zunächst alle Queries in KSQL sogenannte Continuous Queries, die so lange laufen und neu in das Topic kommende Daten ausgeben, bis sie abgebrochen werden. Das geht wie auf der Kommandozeile üblich mit Control + C.

Nun haben wir alle Vorbereitungen getroffen, um in KSQL wie folgt eine Tabelle anlegen zu können:

create table exams (id varchar, name varchar, note double, matrikelnummer varchar) with (kafka_topic = 'exams', value_format='json', key = 'id');

Der erste Teil ist dabei (fast) normaler SQL-Code, im zweiten Teil werden einige Metadaten übergeben, die KSQL mitteilen, mit welchem Topic die Tabelle verbunden werden soll.

 

(K)SQL-Abfragen

Wie von SQL gewohnt können wir uns nun das Schema über describe exams; anzeigen lassen, dabei wird deutlich, dass Kafka automatisch zwei weitere Spalten zu unseren Daten hinzugefügt hat, nämlich die ROWTIME und den ROWKEY. Erstere ist der Timestamp, wann Kafka den Datensatz empfangen hat, zweitere ist der Key des jeweiligen Key-Value-Paars aus dem Kafka-Topic, der mit dem Inhalt der Key-Spalte, die in der With-Klausel genannt ist identisch sein muss. Ferner können wir uns natürlich auch den Inhalt der Tabelle mit einer normalen Select-Abfrage ausgeben lassen:

select * from exams;

Doch Moment, wir sehen, dass wir außer einer "hängenden Query", die sich mit Ctrl-C beenden lässt, wieder nichts sehen...? Das liegt daran, dass Kafka per default so konfiguriert ist, dass es nur neu ankommenden Einträge in einem Topic auswertet (daher zuvor auch das "from beginning"). Wir könnten also a) neue Einträge an das Topic schicken oder b), wenn wir alle vorhandenen Einträge in der Select-Abfrage angezeigt bekommen möchten, müssen wir vor der nächsten Anfrage folgendes Kommando auf der KSQL-Shell absenden (und das nach jedem Neustart der Shell):

SET 'auto.offset.reset' = 'earliest'; 

Nun sollte unsere Select-Abfrage problemlos funktionieren, daher können wir auch gleich noch eine Where-Klausel an sie anhängen:

select * from exams where name = 'Programmierung 1';

Einer Query kann auch ein Limit mitgegeben werden, so dass sie automatisch endet, wenn die gesetzte Anzahl von Ergebnissen ausgegeben worden ist:  select * from exams where name = 'Programmierung 1' limit 1;

Ferner sind natürlich auch Aggregat-Funktionen wie z.B. die Berechnung des Notendurchschnitts pro Fach möglich (auch wenn es bis dato keine avg-Funktion gibt):

select name, sum(note) / count(name) from exams group by name;

Dieser Aufruf ergibt folgende Ausgabe:

Big Data | 1.0
Programmierung 1 | 3.0

Interessant dabei ist es nun zu beobachten, was auf der nicht abgebrochenen Streaming Query passiert, wenn ein weiteres Prüfungsergebnis in das Kafka-Topic geschrieben wird. Das können wir bspw. tun, in dem wir den Konsole-Producer wie oben nur ohne Piping aufrufen und dann folgende Zeile dort hinein pasten:

19:{"id":"19","name":"Big Data","note":2.0,"matrikelnummer":"55555"}

Dadurch wird das Ergebnis der noch laufenden Query aktualisiert und ein neuer Durchschnitt für das Fach Big Data ausgeben:

Big Data | 1.5

Analog würde der neue Eintrag auch bei einer einfachen Select-Query angehängt werden. Übrigens unterstützt es Kafka auch direkt, den Timestamp von Einträgen für Menschen lesbar zu formatieren: select TIMESTAMPTOSTRING(ROWTIME, 'yyyy-MM-dd HH:mm:ss.SSS') from exams;

 

Tables vs. Streams

Neben Tables unterstützt KSQL auch sogenannte Streams, die ebenfalls per SQL durchsucht werden können. Während Tabellen immer den aktuellen Stand der Datenlage, also quasi einen Snapshot, ausgeben, speichern und zeigen Streams immer alle aufgetretenen Events. Schauen wir uns als Beispiel die Änderung einer Note an, die wir über den Konsole-Producer einspielen können:

19:{"id":"19","name":"Big Data","note":1.7,"matrikelnummer":"55555"}

Eine Select-Abfrage auf der Tabelle liefert für diesen Key genau den zuletzt eingetragenen Stand der Note, bzw. natürlich auch den aller enthaltenen Spalten:

select * from exams where id='19'; 
   --> 1535127212852 | 19 | 19 | Big Data | 1.0 | 55555

Wie sieht das im Gegensatz dazu bei einem Stream aus? Auch diesen müssen wir zunächst einmal anlegen:

create stream str_exams (id varchar, name varchar, note double, matrikelnummer varchar) with (kafka_topic = 'exams', value_format='json', key = 'id');

Danach können wir die entsprechende Abfrage losschicken:

select * from str_exams where id='19';
   --> 1535126428549 | 19 | 19 | Big Data | 2.0 | 55555
       1535127660012 | 19 | 19 | Big Data | 1.7 | 55555

... und erhalten hier die gesamte Stream-Historie unseres Datensatzes. Ein offensichtlicher Usecase im vorliegenden Fall ist daher die Historisierung von Daten, die richtig spannende Möglichkeit liegt hier allerdings darin, dass eine Verarbeitung von Streaming-Daten mit Hilfe von SQL-Befehlen möglich wird, also kein eigenes Streaming Framework wie Flink oder Storm mehr notwendig ist. Darauf werde ich sicher bei nächster Gelegenheit noch genauer eingehen.

Sowohl Tabellen als auch Streams können übrigens wie gewohnt über drop table bzw. stream plus den Namen wieder gelöscht werden.

 

Limitierungen

Beenden wollen wir unseren ersten Ausflug in die Welt von KSQL, allerdings mit der Frage, wie es um die Join-Fähigkeiten der aktuellen KSQL-Version bestellt ist. Grundsätzlich sind Joins zwar vorgesehen, sie funktionieren zwischen Tabellen allerdings bis dato (Stand Ende 2019) nur auf den Keys selbst (vgl. hier). Mit anderen Worten sind bisher also nur 1:1-Joins und keine 1:N- bzw. N:1-Verknüpfungen über Fremdschlüssel möglich. Bei Joins, die auf Fremdschlüsseln beruhen, wird die rechte Seite Seite immer mit null-Werten aufgefüllt. Naheliegend ist die Vermutung, dass das (noch?) nicht funktioniert, da Kafka bisher keine Indices unterstützt.

Um das näher zu illustrieren benötigen wir noch einige ausgedachte Studenten (mit Studiengängen der HS Mannheim) in einem neuem Kafka-Topic namens "students". Das geht wieder wie oben mit dem Konsole-Producer:

12345:{"vorname":"Klaus","name":"Mayer","matrikelnummer":"12345","studiengang":"UIB"}23456:{"vorname":"Katrin","name":"Müller","matrikelnummer":"23456","studiengang":"IMB"}55555:{"vorname":"Steven","name":"Müller-Mayer","matrikelnummer":"55555","studiengang":"IB"} 

Dieses können wir nun ebenfalls analog zu oben in eine Tabelle wandeln:

create table studis (vorname varchar, name varchar, matrikelnummer varchar, studiengang varchar) with (kafka_topic = 'students', value_format='json', key = 'matrikelnummer');

Nun läuft allerdings folgender Join ins Leere:

select * from exams left join studis on studis.matrikelnummer = exams.matrikelnummer; --> 
1535126105952 | 1 | 1 | Big Data | 1.0 | 12345 | null | null | null | null | null | null
1535126105961 | 5 | 5 | Programmierung 1 | 2.0 | 23456 | null | null | null | null | null | null
    ...

Ein entsprechernder Join einer Tabelle mit einem Stream funktioniert interessanterweise bereits, was  sich wie folgt als Workaround nutzen lässt, um Fremdschlüsselbeziehungen abzubilden:

select * from str_exams left join studis on str_exams.matrikelnummer = studis.matrikelnummer; -->
1535316616713 | 12345 | 1 | Big Data | 1.0 | 12345 | 1535316139962 | 12345 | Klaus | Mayer | 12345 | UIB
1535316616723 | 23456 | 5 | Programmierung 1 | 2.0 | 23456 | 1535316139970 | 23456 | Katrin | Mueller | 23456 | IMB
1535316616723 | 12345 | 17 | Programmierung 1 | 4.0 | 12345 | 1535316139962 | 12345 | Klaus | Mayer | 12345 | UIB
...

Vorausgesetzt, wir haben in unserem Stream keine Wertänderungen auf ein und dem selben Key, die dann natürlich mehrfach gejoint werden würden. Eine weitere Voraussetzung ist, dass beide Datensätze nach der "Join-Spalte" partitioniert sind (sog. Co-Partitioning, d.h., dass die zu joinenden Elemente auf dem gleichen Broker liegen). Das ist üblicherweise auf der Fremdschlüsselseite nicht der Fall, kann aber ggf. mit einem "partition by" erzwungen werden, vgl. hier.

Ein abschließendes Wort der Warnung soll diesen Post beschließen, Kafka ist per default "vergesslich" und löscht Daten nach einer Woche, wenn die Größe eines Topics 1 GB übersteigt. Wer hier tiefer einsteigen möchte, sollte sich die beiden Parameter log.retention.hours und log.retention.bytes genauer betrachten und sie ggf. auf -1 setzen, um das Löschen zu verhindern.

Weiterführend




Java-Versionen dynamisch wechseln

Mit 2 Zeilen im .bash_profile eines Macs (und ähnlich gestrickten Linux-Versionen) lässt sich eine praktische Umschaltung zwischen Java 8 und Java 10 (oder auch jeder beliebigen anderen Java-Version) einbauen.

Damit lässt sich das nervige Problem der Inkompatibilitäten von Frameworks mit Java-Versionen, das uns sicher alle schon einmal genervt hat, elegant aus der Welt schaffen. Ein direkter Bezug zu Big Data ist hier natürlich nicht gegeben, aber da ich gerade beim Experimentieren mit KSQL und der Confluent-Plattform darüber gestolpert bin, möchte ich eine mögliche Lösung dennoch kurz beschreiben. Es handelt sich also um einen kurzen Beitrag aus der Rubrik "Notiz an mich". 😉

Und so einfach ist sie umzusetzen:
  1. Öffne ein Terminal
  2. Öffne die Datei .bash_profile in einem beliebigen Editor, z.B.: nano ~/.bash_profile
  3. Ergänze die dort folgenden beiden Zeilen:
    alias java8='export JAVA_HOME=$(/usr/libexec/java_home -v1.8)'
    alias java10='export JAVA_HOME=$(/usr/libexec/java_home -v10)'
  4. Speichere die Änderungen und schließe den Editor
  5. Jetzt noch im Terminal folgendes tippen: source ~/.bash_profile
  6. Und nun lässt sich auf dem Terminal mit dem Befehl java8 oder java10 die benötigte Java-Version auswählen; was mit einem darauf folgenden java -version leicht überprüft werden kann
Voraussetzung ist natürlich, dass die entsprechenden Java-Versionen installiert worden sind.

gefunden bei:

Mittwoch, 21. Februar 2018

Ethereum Smart Contracts mit Solidity - eine Kurz-Einführung

Als wäre die Blockchain, die den heute gängigen Kryptowährungen (wie Bitcoin, Ethereum und anderen) zu Grunde liegt, nicht bereits kompliziert genug, rückt Ethereum nun auch noch "intelligente Verträge" (sog. Smart Contracts) ins Licht der Öffentlichkeit.

Viele der bisher im Web verfügbaren Erklärungen dazu sind leider recht unscharf und gerade für Programmierer entweder zu oberflächlich oder gleich ein ausgewachsener Programmierkurs mit nicht unerheblichem Aufwand. Mit diesem Blog-Post möchte ich versuchen, die Mitte zu treffen und zunächst kurz die Idee hinter Smart Contracts erklären, bevor ich ein einfaches Solidity-Beispiel für die Ethereum-Blockchain vorstellen möchte. Es sollte sich inkl. der Pausen zur Validierung der genutzten Test-Blockchain in ca. 60 bis max. 90 Minuten nachvollziehen lassen. Dazu wird außer dem Download des Ethereum-Browsers Mist und eines Social-Media-Account zur Beantragung von Test-Geld im Rinkeby-Netzwerk kein weiterer Aufwand benötigt. Sollten Sie das später gezeigte Programm-Beispiel also selbst ausprobieren wollen, empfiehlt es sich gleich mit dem Download von Mist zu beginnen und dort einen Account im Rinkeby-Netzwerk anzulegen, da die Validierung der dort benutzten Blockchain ca. eine halbe bis dreiviertel Stunde dauern wird.

Bevor wir uns mit weiteren technischen Details befassen, möchte ich noch ein paar Hintergründe zu Smart Contracts in Ethereum erwähnen. Während Bitcoin bis dato nur einen Typ von Accounts anbietet (nämlich die Konten der Nutzer), gibt es in Ethereum einen zweiten Typ: eben die Smart Contracts. Diese können wir uns einfach als Programme vorstellen, die in die Ethereum-Blockchain hochgeladen und dort abgelegt werden. Hochgeladene Programme bekommen eine Adresse, so dass sie durch Ethereum-Transaktionen angestoßen werden können; das geht insbesondere auch von anderen Contracts aus der Blockchain heraus, oder eben durch Überweiseungen, die von Nutzern an einen Contract ausgeführt werden. Einfache Programme bestehen nur aus einem einzelnen Contract, komplexere können auch aus vielen bestehen. Dafür hat sich der Name DApps für Decentralized Apps eingebürgert.

Decentralized Apps
DApps sind im Wesentlichen grob mit Java-Programmen und Contracts wiederum ungefähr mit Java-Klassen vergleichbar, sie können insbesondere auch öffentlich sichtbare Methoden anbieten, die als Einsprungspunkt (also als eine API) für Aufrufe von außen dienen. Sie werden aktuell zumeist in Solidity geschrieben, einer Sprache, die an Javascript angelehnt ist und in der Ethereum Virtual Machine (EVM) ausgeführt werden kann. Um das Ethereum-Netzwerk vor D.O.S.- und anderen Attacken zu schützen, kostet das Ausführen von Smart Contracts Geld oder besser Aufwand, der in diesem Kontext "gas" genannt wird.

Der Zustand eines Contracts, wenn wir so wollen also seine Objektvariablen, wird ebenfalls in der Ethereum-Blockchain gespeichert, wir können Solidity-Programme also im Prinzip beliebig rückwirkend debuggen. A propos Debuggen, ist ein Contract einmal in die Blockchain hochgeladen, verbleibt er dort für die komplette Lebenszeit der Blockchain (er ist immutable), auch wenn er fehlerhaften Code enthalten sollte. Um Fehler auszubessern oder Updates durchzuführen, muss ein neuer Contract hochgeladen werden, der entsprechend eine neue Adresse bekommt.

Als erste Killer-Applikation für DApps gilt übrigens aktuell das Crowdfunding, hier kann mit einigen wenigen Zeilen Code ein Projekt angelegt werden, dessen Einzahlungen nur dann an den Ideengeber ausgezahlt werden, wenn innerhalb einer festgelegten Frist genügend Ether zusammen gekommen sind. Andernfalls fließt das eingezahlte Geld wieder zurück an seinen jeweiligen Geldgeber. Weitere spannende Ideen für DApps finden sich beispielsweise hier.

Accounts anlegen
Kommen wir nun zu einem ersten kleinen Solidity-Programm, das nichts weiter tun soll, als einen eingezahlten Betrag gleichmäßig an zwei anfangs definierte Konten weiterzuverteilen. So ließen sich beispielsweise Taschengeld und Geldgeschenke unter Geschwistern aufteilen.

Sie hatten doch zuvor bereits die Prüfung der Blockchain in Mist angestoßen? Vermutlich läuft sie zwar trotzdem noch, glücklicherweise lässt sich aber bereits währenddessen, beispielsweise mit einem Tweet, die Übertragung von Test-Ether an den in Mist automatisch angelegten Main-Account anstoßen, so dass wir sofort loslegen können, wenn die Prüfung abgeschlossen ist.

Hat das Starten des Mist-Browsers einwandfrei geklappt (evtl. kann der ein oder andere Neustart des Programms notwendig sein, weil es doch nicht ganz reibungslos läuft), können der enthaltenen Wallet (grünes Icon in der Seitenleiste links) verschiedene Konten hinzugefügt und diesen durch einen Klick auf Senden (rechts neben dem Wallet-Icon) Ether überwiesen werden. Das Ergebnis könnte dann etwa folgendermaßen aussehen:


Das erste Solidity-Programm
Nun können wir auch schon mit unserem ersten Solidity-Programm loslegen. Es bietet sich an, den Code nicht direkt in Mist zu editieren (was nach einem Klick auf "Verträge" rechts oben möglich wäre), sondern eine IDE zu verwenden. Auf der Solidity-Website sind zahlreiche Möglichkeiten verlinkt, für unsere erste Annäherung sollte die online verfügbare sogenannte Remix-Umgebung für den Moment vollständig ausreichend sein. Wie auf der folgenden Abbildung zu erkennen ist, erinnert diese stark an gängige IDEs wie Eclipse. Links sind die bisher angelegten Contracts aufgelistet, in der Mitte findet sich der aktuell geöffnete Sourcecode, darunter die Konsolenausgabe und rechts können verschiedene Tabs geöffnet werden, die uns beim Testen und Analysieren der Contracts unterstützen.


Das folgende Programm können Sie einfach aus dem Post nach Remix kopieren oder auch direkt über Mist als neuen Contract in der Blockchain veröffentlichen. Zu letzterem gleich mehr.

pragma solidity ^0.4.18;

contract FairShare {
    address[] receivers = [
        0xFeE2E38AB12c202e82de36975A58d0d9A71Ea4f6,
        0x416e754EcAAD9eEB87f6a242aB15F3272ab6E880];
   
    function FairShare() public payable {
        shareEther();
    }
   
    function () public payable {
        shareEther();
    }
   
    function shareEther() internal {
        uint money = msg.value / receivers.length;
       
        for (uint i = 0; i < receivers.length; i++) {
            receivers[i].transfer(money);
        }
    }
   
}

Zunächst aber noch einige Worte zum Programm-Code selbst. In der ersten Zeile (pragma...) wird die Solidity-Version festgelegt, die unser Contract verwenden soll. contract entspricht in etwa dem "class" in objektorientierten Programmiersprache und gibt unserem Contract seinen Namen.

Danach folgt die Definition eines Arrays mit Namen receivers vom Typ address, das die Kontonummern von zwei Empfänger-Konten enthält, an die alle eingehenden Beträge aufgeteilt weitergeleitet werden sollen.

Ferner enthält der Contract noch drei Funktionen. Die erste entspricht dem Constructor einer Java-Klasse und wird einmalig aufgerufen, wenn der Contract in der Blockchain angelegt wird. Die zweite, namenlose Funktion (der sogenannte Fallback) wird immer dann aufgerufen, wenn eine normale Überweisung ohne Funktionsaufruf an den Contract getätigt wird. Public definiert die öffentliche Sichtbarkeit, im Gegensatz zu internal bei der dritten Funktion und payable gibt an, dass Ether an diese Funktionen geschickt werden können. Dies ist bei der Erstellung eines Contracts nicht zwingend, es kann auch Contracts ohne Ether-Eingang geben. Wenn ein Ether-Eingang vorgesehen ist, sollte man sich auch zwingend darüber Gedanken machen, wie man die Ether wieder aus dem Contract heraus bekommt; wir erinnern uns daran, dass einmal auf der Blockchain verewigte Überweisungen nicht mehr rückgängig zu machen sind.

Offensichtlich leiten die beiden genannten Eingangsfunktionen nur an die dritte Funktion mit Namen shareEther weiter. Diese ermittelt die in den Vertrag eingezahlte Ether-Summe (msg.value) teilt sie in zwei Hälften und schickt diese mit Hilfe von transfer an die beiden in receivers definierten Kontonummern weiter.

Möchten wir das Programm nun lokal testen, ist dies rechts oben im Tab "Run" möglich, wie in der folgenden Abbildung gezeigt.


Wir wählen im Dropdown-Menü in der Mitte das Programm aus, das wir starten möchten und klicken auf "Create". Daraufhin erscheint unten eine Instanz des Programms und die Möglichkeit ihre Funktionen aufzurufen. Da das FairShare-Programm nur den Fallback als öffentliche Methode hat, kann auch nur dieser durch einen Klick unten links aufgerufen werden. Um dem Fallback dabei einen Ether-Betrag zu senden, muss zuvor oberhalb des Dropdown-Menüs ein "Value" eingegeben werden. Ferner kann auch ein lokaler Test-Account gewählt werden, der dafür verwendet werden soll. Das Ergebnis dieser Aufrufe kann jeweils in der grauen Konsolenausgabe unterhalb des Programmcodes begutachtet werden.

Den Contract veröffentlichen
Die Veröffentlichung des Contracts ist mit Hilfe des Mist-Browsers nicht weiter schwer. Zunächst ist dafür ein Klick auf "Verträge" und dann ein Klick auf "Neue Verträge Veröffentlichen" notwendig, woraufhin folgende Seite erscheint.


Auf dieser kann ausgewählt werden, von welchem Account aus der Contract veröffentlicht werden soll und ob dem Contract gleich bei seiner Initialisierung Ether übermittelt werden sollen. Der eben in der Remix-Umgebung erstellte Programmcode kann nun hierhin kopiert und mit einem weiteren Klick in der Blockchain veröffentlicht werden. Der Vertrag erhält dann eine eigene Adresse und erscheint in der Auflistung der eigenen Verträge im Mist-Browser, wie im Folgenden gezeigt:


Der von mir in die Blockchain gestellte Contract hat beispielsweise die Adresse 0x63e37aFb51DD5BD30DAbcee135B747D745980634 im Rinkeby-Netzwerk erhalten. Wenn Sie mögen, können Sie probehalber gerne einmal Test-Geld dorthin überweisen, das dann an die beiden im Code gezeigten Accounts weiter verteilt wird.
Ein Klick auf den Vertrag bringt noch einige weitere Detailinformationen zum Vorschein, die an dieser Stelle allerdings recht uninteressant sind, da der Contract über keinerlei öffentliche Funktionen und auch über keinerlei Ether verfügt, da alle eingehenden Beträge direkt wieder ausgezahlt werden. Ich plane daher, den in der Abbildung ebenfalls zu sehenden Lottery-Contract bei nächster Gelegenheit hier vorzustellen und dabei auch ein wenig auf das Debugging in Solidity einzugehen.