IOTA - Praktische Beispiele
In dieser Blogserie geben wir einen tieferen Einblick in die Themen IOTA und Hashgraph und die dahinter liegenden Konzepte:
- IOTA – Einführung
- IOTA – Praktische Beispiele
- Hashgraph – Einführung
- Hedera Hashgraph – Praktische Beispiele
Nachdem wir im ersten Teil der Blogserie einen groben Überblick zu IOTA und der Basistechnologie gegeben haben, zeigen wir im zweiten Teil einige Umsetzungsbeispiele basierend auf der angebotenen JAVA-Client-Bibliothek unter Verwendung des IOTA Devnet .
Für das bessere Verständnis erläutern wir einzelne grundlegende Begriffe etwas detaillierter.
Seed
Für die Erstellung eines Accounts und von Adressen ist ein Seed notwendig. Dieser Seed sollte aus mindestens 81 Tryts bestehen und bildet den Zugangsschlüssel zu einem Konto. Diesen sollte man also auch niemals aus den Händen geben, da er wie eine Geldbörse ist.
Doch was sind Tryts eigentlich?
IOTA setzt anstatt des Binärsystems auf das Ternärsystem (Dreiersytem). Dies führt zu einem eigenen Alphabet, das aus 27 Zeichen besteht: 26 Großbuchstaben (A-Z) und der 9.
Ein Trit (trinary digit) kann dabei drei Zustände annehmen 31 (-1,0,1). Drei Trits ergeben dabei ein Tryt also 33=27, was damit der Anzahl der oben genanten Zeichen im Alphabet entspricht. Mit einem Tryt kann also ein Zeichen im Alphabet dargestellt werden.
Zum besseren Verständnis soll im folgenden Beispiel das Wort HOLD in Trytes umgewandelt werden, um es in Tangle zu schreiben.
Als Ergebnis der Umwandlung ergibt sich aus dem Wort HOLD RBYBNBVB in Trytes. Für den aus 81 Trytes bestehenden Seed ergeben sich damit 2781 Kombinationen.
Erstellen eines Seed
Für die Erstellung eines Seed gibt es verschiedene Möglichkeiten. Das nachfolgende Beispiel zeigt die Erstellung mithilfe des Mac Terminals:
cat /dev/urandom |LC_ALL=C tr -dc 'A-Z9' | fold -w 81 | head -n 1
Als Ergebnis erhält man einen Seed, der aus 81 Zeichen (trytes) besteht (der Seed ist hier nicht vollständig dargestellt):
OUTBHZFNSCEPBFUVMUBCRZGCWLOKLSOAOHHDNPMRLPMIQADCNJOUYDYRIJW9PBXEX9T...
Private Key und Adressen
Ein Seed ist der Ausgangspunkt für das Generieren des Private Key und des Public Key, der die Adresse repräsentiert. Der gesamte Prozess ist in Abbildung 1 visualisiert.
Der Private Key wird von einem Sub-Seed-Schlüsselindex abgeleitet. Auf Basis dieses Schlüssels wird schließlich die Adresse generiert. Dabei kann die Generierung für drei unterschiedliche Signatur-Security-Level erfolgen. Der Unterschied liegt in der Schlüssellänge (81 Trytes, 162 Trytes, 243 Trytes).
Für das Security-Level 2 wird aus dem Seed und dem Index ein Hash abgeleitet. Dieser besteht aus 2 x 27 Segmenten mit je einem 81 Trytes langen Hashwert. (81 x 27= 2187 Trytes). Daraus ergibt sich eine Schlüssellänge für den Private Key von 2 x 2187 = 4374 Trytes. Für die Key-Fragmente wird wiederum aus den beiden Blöcken des Private Key ein 81 Trytes langer Hashwert gebildet. Aus diesen beiden Blöcken wird dann wieder ein 81 Trytes langer Hash ermittelt, der die Adresse ist. Für das Security-Level 1 wird nur jeweils ein Block und für das Level 3 werden drei Blöcke verwendet.
Abbildung 1: Adressgenerierung in IOTA
Erzeugen von Adressen
Die Methode zur Erzeugung der Adressen spiegelt das vorgestellte Konzept zur Adresserzeugung vollständig wider. Dies zeigen auch die entsprechenden Aufrufparameter.
Mit der nachfolgenden Methode werde neue noch nicht verwendete Adressen erzeugt
GetNewAddressResponse res = iotaAPIClient.generateNewAddresses(seed, securityLevel, checksum, index, amount);
Als Ergebnis der Methode erhalten wir zum Beispiel für die verschiedenen Security-Level folgende Adressen (s. Tabelle 1). Die grauen Zeichen bilden dabei die Checksummen. Bei der Ausführung der Methode mit checksum = false fehlen die letzten 9 Zeichen.
Transaktionen
Non-Value-Transaktionen
Basierend auf dem beschriebenen Prozess einer Transaktion (siehe Teil 1) erfolgt zunächst die Erzeugung der Transaktion (Transfer-Daten).
...
Transfer transaction = new Transfer(address, value, message, tag); transfers.add(transaction);
...
Hier werden die notwendigen Daten der Transaktion, wie die Adresse und die Nachricht, erfasst. Der Value bleibt in diesem Fall Null.
Im zweiten Schritt erfolgt der Transfer. Bei der Methode sendTransfer handelt es sich um einen erweiterten API-Aufruf, der die im ersten Teil beschriebenen einzelnen Schritte zusammenfasst.
...
SendTransferResponse str = iotaAPIClient.sendTransfer(seed, security, depth, minWeightMagnitude, transfers, inputs, remainderAddress, validateInputs, validateInputAddresses, tips);
...
Wichtige Parameter, die hier gefüllt sein müssen sind:
Alle anderen Werte können null oder leer sein. Nach dem Senden der Transaktion bekommt man die folgende Response:
hash=X9DQMGHHNSOJBHSVSHSWERSHZXIQIXHQCPTLMLRXKXTYKZOSPYWXQBAMSMMMBCLJWUQWW9ZXG9YTZ9999signatureFrag-ments=ODGASCTCJDXCRCTCSBSCGADBGAVAWAYAXBRBOBGAQAGAJDPC9DIDTCGADBGAVAWAUAGAQD9999999999999999999999999999999999999999999…999address=WBNEWLOFVMDCYLAJWVWXOLRCVRCBWVORV9GVCDHZVPXORYMKWYSPVXAQSQKRCBFNYDOCEDGZ9FGFDMMDWvalue=0obsoleteTag=QRTASPAM99999999999999NHE99timestamp=1542901673currentIndex=0lastIndex=0bundle=IIP9URQVIJTDQSGFFKVXLLUAVBZSACSYFLLDOHLTACXCKECZFRDSTAFSECELQGGQ9VTQEWEN9OJDLLNYXtrunkTransac-tion=VNOWRP9JHCIQFKLELZXSRVMTKOSGJERMRDTDGZ9ZNOLEXIOVWBMWXJOGWXSIWAHPHIMHLUFJSSBCNT999branchTransac-tion=NJIINZRTBDBQZJKUKQQVFQSJCBPAXVGREKEIFEEXCZSYTX9MMDSBKFUIBJYEKDZUFSYEPRZNKCVEII999nonce=IMJSIIWFQANIOIBVXT9N9LRNDBWpersistence=<null>attachmentTimestamp=1542901674831tag=JOTASPAM99999999999999NHE99attachmentTimestampLowerBound=0attachmentTimestampUpperBound=3812798742493
Im signatureFragments befindet sich die eigentliche Nachricht als Trytes String. Im Devnet Tangle Explorer kann man sich die Nachricht dann als Text oder JSON anzeigen lassen.
Abbildung 2: Ansicht der Transaktion im Devnet Explorer
Die beiden Transaktionen, die von unserer Transaktion validiert wurden, findet man als trunkTransaction und branchTransaction. Mithilfe des Devnet Tangle Explorer kann man diesen Zusammenhang sehr gut visualisieren. Hier ist auch die Transaktion zu finden, die unsere Transaktion validiert hat.
Abbildung 3: Visualisierung der Transaktionen
Value-Transaktionen
Bei einer Value-Transaktion werden nun IOTAs, genannt Token, von einem Besitzer zu einem anderen transferiert.
Voraussetzung ist, dass ich einen zweiten Seed mit einer Adresse anlege, um eine entsprechende Überweisung zu tätigen. Weiterhin ist es notwendig, einen Token zu erhalten. Dafür wird ein Service angeboten, der für das Devnet entsprechende Token ausgibt.
Einen Token erhält man, indem man eine generierte Adresse auf der Seite https://faucet.devnet.iota.org eingibt. Den Erhalt kann man anschließend wieder im Devnet Tangle Explorer prüfen. Die Abbildung zeigt nun eine Balance von 1.000i.
Abbildung 4: Balance für eine Adresse im Tangle Explorer
Ein ganz wesentlicher Unterschied zur Non-Value-Transaktion ist die Notwendigkeit, dem Transfer die inputs mitzugeben. Dabei handelt es sich um die Transaktionen, die Guthaben besitzen, von dem transferiert werden soll.
Folgendes Beispiel soll das Ganze etwas anschaulicher machen.
Wir möchten von Person A zu Person B einen Transfer von 1i durchführen.
PersonA
AdressePersonA = FQIYHISQQ9EOOUOZEVLTIBENFCXLDSTRHQINBERHPUTBSCKSJYZBEA9CFNKIJQCWOCXICHSXSWDBEQZFC9VCBDKIAD
Balance / Guthaben = 2.000i
PersonB
AdressePersonB = WBNEWLOFVMDCYLAJWVWXOLRCVRCBWVORV9GVCDHZVPXORYMKWYSPVXAQSQKRCBFNYDOCEDGZ9FGFDMMDW9JSTBIMSX
Balance / Guthaben = 1.000i
Die nachfolgenden Methoden sind in der gegebenen Reihenfolge auszuführen:
1. Transfer definieren für Person A überweist Person B 2iTransfer transaction = new Transfer(address, value, message, tag); transfers.add(transaction);
Für address ist die Empfängeradresse, also die Adresse Person B und der value ist 2 Die Einträge für message, tag kann man beliebig setzen.
2. Jetzt muss man das Guthaben von Person A ermitteln, von dem „abgebucht“ werden soll.GetBalancesAndFormatResponse res = iotaAPIClient.getInputs(seed, security, 0, 1, 1);inputs= res.getInputs();
Dazu muss der seed von Person A verwendet werden. Es wird über alle Adressen des entsprechenden Security-Levels gesucht. Das Ergebnis wird dann als inputs in die sendTransfer-Methode übergeben.
3. Transfer auslösenSendTransferResponse str = iotaAPIClient.sendTransfer(seed, security, depth, minWeightMagnitude, transfers, inputs, remainderAddress, validateInputs, validateInputAddresses, tips);
Im Tangle Explorer findet man das Bundle über die BundleID.
bundle=EBLGCSDFULIAVILWUUBWAOOXWBHHIIDXEHIIZQITWVLHJZLXGKJ9ONFCLREDEJXOVVHXANPEJOCKICQKY
In Abbildung 5 kann man nun sowohl die Input- als auch die Output-Transaktionen sehen.
Abbildung 5: Bundle der Value-Transaktion
Von hier kann man sich dann die einzelnen Transaktionen des Bundles detaillierter anschauen. Die erste Transaktion (Index 0) zeigt, dass Person B 2i erhalten hat. Hier ist als Adresse die „Empfänger-Adresse“ von Person B eingetragen.
Abbildung 6: Transaktion Index 0
Wenn Person B die Transaktionen für seine Adresse nun betrachtet, dann sieht sie, dass das Guthaben nun 1002i beträgt.
Abbildung 7: Guthaben Adresse Person B
Die drei weiteren Transaktionen betreffen die Adresse von Person A und finden sich dort wieder. Hier sehen wir im ersten Eintrag das entfernte „alte“ Guthaben und in der dritten Zeile das „neue“ Guthaben. Zeile zwei ist die Transaktion mit dem zweiten Teil der Signatur.
Abbildung 8: Transaktion von Person A
Im dritten der Blogserie widmen wir uns der verteilten Ledger-Technologie Hashgraph.
Noch Fragen?
Wie können Sie Chancen und mögliche Einsatzfelder von Blockchain-Lösungen identifizieren und diese in Ihrer Organisation umsetzen? Erfahren Sie, wie wir Sie beim Thema Blockchain unterstützen können:
Nico Heinze - ist Projektmanager bei der iteratec GmbH in München. In den vergangenen Jahren setzten sein Team und er immer wieder völlig neuartige Anwendungen um.