Hedera Hashgraph – Praktische Beispiele
In diese Blogserie geben wir einen tieferen Einblick zu den Themen IOTA und Hashgraph und die dahinter liegenden Konzepte:
- IOTA – Einführung
- IOTA – Praktische Beispiele
- Hashgraph – Einführung
- Hedera Hashgraph – Praktische Beispiele
Aufbauend auf den theoretischen Grundlagen des Hashgraph-Algorithmus des vorherigen Artikels wird sich dieser Artikel der Praxis widmen. Basis dafür ist die Hedera-Plattform und das von Hedera angebotene Java SDK (Version 0.6.1).
Eine erste Erkenntnis beim Schreiben des Artikels war, dass solche Plattformen sehr schnelllebig in einem sehr frühen Entwicklungsstadium sind. Begonnen hatte ich den Artikel und die ersten Beispielimplementierungen mit der Version 0.2.X des SDK. Aus verschiedenen Gründen verzögerte sich die Fertigstellung und ich musste immer wieder die Implementierungen auf die neueste SDK Version umstellen, um die Funktionalität des aktuellen Standes zu nutzen. Dies war dann auch immer mit Überraschungen verbunden.
Mittlerweile wurden z. B. die Fees (Transaktionsgebühren) eingeführt, die es am Anfang so in der Implementierung nicht gab. Diese sind aber aktuell noch im Beta-Stadium und man sieht, dass die Dokumentation sich innerhalb einer Woche ändern kann.
Die Hedera-Plattform
Hedera ist ein Public Distributed Ledger für den Bau und die Bereitstellung dezentraler Anwendungen und Services. Die Hedera-Plattform bietet die Nutzung von drei unterschiedlichen Services an:
- Kryptowährung
- Smart Contracts
- Fileservice
Das Distributed Ledger von Hedera besteht aktuell aus permissioned Nodes, die vom Hedera Governing Council verwaltet und betrieben werden. Das Netzwerk soll sich nach Aussage auf der Website von Hedera aber im Laufe der Zeit zu einem permissionless Modell entwickeln. Wann das sein wird, ist bisher nicht klar.
Plattform-Feature
Die Hedera-Plattform bietet für die drei angebotenen Services jeweils APIs an, die sich in Queries und Transactions strukturieren.
Über die Query APIs kann man existierende Informationen abfragen. Diese Anfragen gehen an eine einzelne Node. Zu solchen Abfragen gehören z. B. Infos zu einem Account.
Transaktionen sind hingegen Anfragen an das gesamte Netz, bei denen eine Konsensbildung stattfindet. Dies ist z. B. der Fall bei einem Transfer von HBARs (die Hedera Coins) von einem Account zu einem anderen.
Transaktionen, die an einen Node übertragen wurden, werden mit einer Response bestätigt. Dazu gibt es unterschiedliche Response-Typen, die unterschiedliche Informationen verfügbar machen. Die wichtigsten sind aktuell Receipts und Records.
Receipts liefern minimale Informationen dazu, ob die Transaktion erfolgreich zur Konsensbildung übertragen wurden.
Records liefern detailliertere Informationen zu einer Transaktion, wie z. B. den Transaktionszeitstempel.
In der hier betrachteten Version 0.6.1 des SDK sind die Records als Response-Objekt allerdings schon als „deprecated“ gekennzeichnet. Es gibt aber eine Methode, um Records zu einem Account separat abfragen.
Wie bereits erwähnt wurden mittlerweile Fees eingeführt, die für Transaktionen und Abfragen zu entrichten sind. Diese werden mit Tinybars (1hbar (ℏ) = 100.000.000 tinybars (tℏ)) bezahlt. Bei der Einrichtung eines Test-Accounts bei Hedera erhält man 1000ℏ, um damit seine Beispiele oder Testanwendungen implementieren und testen zu können.
Nachfolgend finden sich einige Implementierungsbeispiele für die Services „Cryptocurrency Account“ und „File“. Den Service „Smart Contract“ werde ich später in einem separaten Beitrag beleuchten.
Implementierungsbeispiele
Für die Nutzung des Hedera Distributed Ledger ist ein Zugang notwendig. Aktuell wird ein Mainnet und ein Testnet betrieben. Diese stellen aufgrund ihres Entwicklungstands aktuell noch unterschiedliche Services zur Verfügung. Die nachfolgenden Beispiele wurden mit einem Testnet-Account umgesetzt.
Bevor die Implementierung starten kann sind die folgenden Schritte durchzuführen:
- Anlegen eines Profils im Hedera-Portal. Dies erfordert auch die Verifikation der Identität (z. B. mit dem Personalausweis)
- Verbindung mit dem Testnet herstellen. Dazu ist es notwendig, ein Schlüsselpaar bestehend aus einem Public und Private Key zu erzeugen
- Einrichten der Entwicklungsumgebung (Hedera Java SDK importieren)
Alle notwendigen Details dazu sind gut beschrieben in der Dokumentation von Hedera zu finden.
Nach der vollständigen Registrierung erhält man eine Account ID. Die Infos zu dieser ID und den verfügbaren Netzwerkknoten befinden sich im Portal (s. Abbildung 1) nachdem die obigen Schritte 1 und 2 durchgeführt wurden.
Die Daten sind wichtig, da diese in die (versteckte) Konfigurationsdatei mit dem Namen „.env“ einzutragen sind. Im SDK befindet sich eine Beispieldatei „.env.sample“.
Nachfolgend die ausgefüllte „.env“-Datei als Beispiel.
# Network Node ID and Address
NODE_ID= 0.0.3
NODE_ADDRESS= 0.testnet.hedera.com:50211
# Operator ID and Private Key
OPERATOR_ID= 0.0.10…
OPERATOR_KEY= 30…
Die Account ID ist die Operator ID und der Operator Key ist der Private Key, den man erzeugt hat. Der Node wird über eine ID und eine Adresse definiert, sodass man auch unterschiedliche Nodes verwenden kann.
Durch die freie Definition der Nodes kann nun auch die gleichzeitige Verfügbarkeit von Informationen auf unterschiedlichen Nodes getestet werden. Dazu muss in der Implementierung nur ein Client mit den entsprechenden Parametern erzeugt werden.
High-level-Methoden
Neben den Transaktionen und Queries, die in der Dokumentation beschrieben sind und in den nachfolgenden Beispielen verwendet werden, gibt es auch noch einige High-level-Methoden, die man direkt im Client aufrufen kann. Allerdings scheint die Umstellung des APIs im Rahmen der Einführung der Fees noch nicht abschlossen, da einige dieser Methoden zwar noch im SDK existieren, aber im folgenden Beispiel aufgrund der Einführung der Fees zu einer Exception (INSUFFICIENT_TX_FEE) führen.
Die beschriebene Anlage eines Accounts konnte bis zur „Aktivierung“ der Fees noch mit der folgenden Methode erfolgen.
…
AccountId newAccountId = client.createAccount(newKey.getPublicKey(), initialBalance);
…
Dies ist ein Beispiel für die Schnelllebigkeit der Plattform in diesem frühen Entwicklungsstadium.
Cryptocurrency Account Services
Mithilfe des Cryptocurrency Account Services der Hedera-Plattform ist es möglich, Konten zu verwalten und Coin-Transaktionen in HBAR (ℏ) auszuführen.
Wie jede andere Cryptowährung, können auch die HBAR-Coins (ℏ) zwischen Partnern getauscht, bzw. zum Begleichen anfallender Gebühren genutzt werden, die für die Nutzung der Hedera-Services als Transaktionsgebühren anfallen.
Um einen Transfer von Coins ausführen zu können, werden zunächst Accounts benötigt, zwischen denen die Coins transferiert werden. Dies erfolgt mit dem Service AccountCreateTransaction().
Anlegen eines Accounts
Der Service AccountCreateTransaction() erstellt einen neuen Account im Hedera-Netzwerk. Für diesen Account wird eine neue Account ID generiert, die zum Senden und Empfangen von HBARs zwischen anderen Benutzern im Netzwerk verwendet werden kann. Das nachfolgende Beispiel zeigt den Beispielcode für die Anlage eines Accounts.
public static AccountId createAccount() throws HederaException{
// Generate a Ed25519 private, public key pair
var newKey = Ed25519PrivateKey.generate();
var newPublicKey = newKey.getPublicKey();
// Establish a connection to a Hedera client
var client = Helper.createHederaClient();
//Initial balance of tinybars for the new account
var initialBalance = 1000;
var tx = new AccountCreateTransaction(client)
.setKey(newKey.getPublicKey())
.setInitialBalance(initialBalance)
.setTransactionFee(80_000_000);
// This will wait for the receipt to become available
var receipt = tx.executeForReceipt();
return receipt;
}
Als Ergebnis erhält man aus dem Receipt-Objekt eine neue Account ID. Diese setzt sich zusammen aus der RealmNumber, der ShardNumber und der AccountNumber.
accountId = 0.0.62402
Bedeutung hat aktuell nur die AccountNumber. Die beiden anderen Werte sind momentan immer 0.
Zur Account ID kann man über den Service AccountInfoQuery() Infos zum Account abfragen. In dem zurückgelieferten Response-Objekt befindet sich u. a. die Balance.
public static AccountInfo getAccountInfo(AccountId accountId, Client client) throws HederaEx-ception {
var query = new AccountInfoQuery(client)
.setAccountId(accountId);
AccountInfo account = query.execute();
return account;
}
accountID {
accountNum: 62402
}
contractAccountID: "000000000000000000000000000000000000f3c2"
proxyAccountID {
}
key {
ed25519: "7\326\237\317\330Q\237M\316g\343\241\260\360\340Z\b\322\212……."
}
balance: 1000
generateSendRecordThreshold: 9223372036854775807
generateReceiveRecordThreshold: 9223372036854775807
autoRenewPeriod {
seconds: 2592000
}
Mit diesem zweiten Account ist jetzt der Weg geebnet, um einen Transfer von Coins durchzuführen.
Cryptocurrency transferieren
Der Service CryptoTransferTransaction() ermöglicht den Transfer von Tinybars (tℏ) von einem Konto auf ein anderes Konto im Hedera-Netzwerk.
Der oder die Absender und Empfänger werden über ihre Account ID identifiziert. In dem folgenden Beispiel werden 1.000.000 tℏ von einem Konto (10291) auf ein anderes Konto (auf das oben erstellte Konto 62402) übertragen.
public static TransactionReceipt transferCryptocurrency(AccountId senderAccountId,
AccountId recipientAccountId,
long transferAmount,
Client client) throws HederaException {
CryptoTransferTransaction ct;
Transaction tx;
ct = new CryptoTransferTransaction(client);
ct.addSender(senderAccountId, transferAmount)
ct.addRecipient(recipientAccountId, transferAmount)
ct.setTransactionFee(90000);
tx = ct.build();
// we are sending from the operator we do not need to explicitly sign the transaction
TransactionReceipt receipt = tx.executeForReceipt();
return receipt;
}
Die Balance vor und nach der Übertragung in beiden Konten sieht folgendermaßen aus.
Vor Übertragung:
balance 10291: 98518051073
balance 62402: 1012
Nach Übertragung:
balance 10291: 98516967018
balance 62402: 1000916
Die Transaktion muss von allen Absender-Accounts signiert werden. In der aktuellen Implementierung des Clients ist eine automatische Signierung durch den Haupt-Account (der für die Transaktionen zahlt) umgesetzt. Die notwendigen Daten dafür werden aus der weiter oben beschriebenen „.env“-Datei geholt. Da der obige Absender identisch zum Haupt-Account ist, muss dieser in dem Beispiel nicht explizit signieren.
Wenn der Absender nicht über genügend Guthaben auf seinem Konto verfügt, um die Transaktion abzuwickeln, schlägt die Transaktion fehl und die Tinybars werden nicht auf das Empfängerkonto überwiesen.
Wenn die zu transferierenden Tinybars aus verschiedenen Accounts stammen, müssen die Quell-Accounts auch jeweils die Transaktion signieren. Im nachfolgenden Beispiel ist der Key für den zweiten Account (62402) zur Signatur angegeben. Der Haupt-Account (10291) muss nicht explizit angegeben werden.
…
ct = new CryptoTransferTransaction(client);
for (int i=0; i< senderAccounts.length; i++) {
ct.addSender(senderAccounts[i], transferAmount);
}
ct.addRecipient(recipientAccountId, transferAmount);
ct.setTransactionFee(180000);
tx = ct.build();
for (int i=1; i< senderAccounts.length; i++) {
tx.sign(key[i]);
}
…
Dieser Codeausschnitt ist die generische Variante zum Beispiel der Überweisung zwischen zwei Accounts.
In dem Beispiel werden jeweils 5000 tℏ vom Account 10291 und 62402 an den Account 69192 übertragen. Die Balances der Accounts vor dem Transfer sehen folgendermaßen aus.
Vor Übertragung:
balance 10291: 98507842535
balance 62402: 985535
balance 69192: 30619
Nach dem Transfer kann man sehen, dass der Account 69192 etwa 10.000 tℏ mehr besitzt (abzüglich Fees).
Nach Übertragung:
balance 10291: 98507699945
balance 62402: 980408
balance 69192: 40492
Im Detail kann man die gesamte Verrechnung inklusive Fees aus dem Transaction Record ableiten. Diesen erhält man über den Service AccountRecordQuery().
Account Records anzeigen
Der Service AccountRecordQuery() liefert alle Datensätze für ein Konto für Ein- und Auszahlungen, die in den letzten 24 Stunden über dem vom Benutzer festgelegten Schwellenwert lagen. Die Abfrageantwort enthält den Header und die Konto-ID sowie die einzelnen Transaction Records.
Die Implementierung dieser Abfrage ist relativ simpel, wie das folgende Beispiel zeigt:
public static CryptoGetAccountRecordsResponse getAccountRecords(
AccountId accountId,
Client client) throws HederaException
{
// Create AccountRecordsQuery() object
var query = new AccountRecordsQuery(client)
.setAccountId(accountId);
CryptoGetAccountRecordsResponse respons = query.execute();
return respons;
}
Im Datensatz zur obigen Transaktion (je 5000 tℏ aus 10291 und 62402 an 69192) können die einzelnen Buchungen genau aufgeschlüsselt werden. Nachfolgend werden nur die wichtigsten Teile aus dem gesamte Transaction Record für den jeweiligen Account gezeigt, um die Buchungen einfach nachzuvollziehen.
Für den Account 10291 hatten wir vor und nach dem Transfer der 5000 tℏ folgende Beträge.
Vor Übertragung:
balance 10291: 98507842535
Nach Übertragung:
balance 10291: 98507699945
In dem zugehörigen Transaction Record ist erkennbar, dass neben den 5000 tℏ noch Fees in Höhe von 136326 tℏ und 1264 tℏ angefallen sind. Die Summe der Abzüge führt dann zu dem obigen Ergebnis nach dem Transfer.
…
accountAmounts {
accountID {
accountNum: 10291
}
amount: -136326
}
…
accountAmounts {
accountID {
accountNum: 10291
}
amount: -1264
}
…
accountAmounts {
accountID {
accountNum: 10291
}
amount: -5000
}
…
Für den zweiten Account, von dem 5000 tℏ abgebucht werden, sieht es ähnlich aus. Es wurden 5000 tℏ abgebucht und 127 tℏ Fees sind angefallen.
Vor Übertragung:
balance 62402: 985535
Nach Übertragung:
balance 62402: 980408
…
accountAmounts {
accountID {
accountNum: 62402
}
amount: -5000
}
accountAmounts {
accountID {
accountNum: 62402
}
amount: -127
}
…
Der „Gewinner“ ist der dritte Account als der Empfänger der 10.000 tℏ. Wie man sieht, sind aber nach der Transaktion nicht alle 10.000 tℏ vorhanden.
Vor Übertragung:
balance 69192: 30619
Nach Übertragung:
balance 69192: 40492
Im zugehörigen Transaction Record ist erkennbar, dass zwar alle 10.000 tℏ transferiert, aber gleichzeitig wieder 127 tℏ als Fees abgezogen wurden.
accountAmounts {
accountID {
accountNum: 69192
}
amount: 10000
}
accountAmounts {
accountID {
accountNum: 69192
}
amount: -127
}
…
Es wurden hier nicht alle Cryptocurrency Account Queries oder Transaktionen als Beispiele betrachtet, da diese alle sehr ähnlich verwendet werden. In der Dokumentation finden sich alle Transaktionen und Queries. Dort sind alle Methoden einzeln mit Beispiel-Implementierungen aufgeführt. Die Herausforderung besteht aktuell noch darin, zu ergründen, ob und wie alle Parameter wirklich funktionieren und wie stabil die Implementierungen sind. Nachfolgend ein Beispiel aus dieser Rubrik.
Der Service CryptoTransferTransaction() des nachfolgenden Beispiel-Codes wäre das Rückgabeobjekt vom Typ CryptoTransferTransaction.
new CryptoTransferTransaction(client)
.addSender(senderAccounts[0], 100)
.addRecipient(recipientAccountId, 100)
.setTransactionFee(10000);
Wenn wir jetzt eine kleine Änderung vornehmen und das Ganze noch signieren mit .sign(), was man aufgrund der Dokumentation als erstes versuchen wird, dann führt die Methode sign() zu einem Objekt vom Typ Transaction.
new CryptoTransferTransaction(client)
.addSender(senderAccounts[0], 100)
.addSender(senderAccounts[1], 100)
.addRecipient(recipientAccountId, 200)
.setTransactionFee(10000)
.sign(key[1]);
Der Versuch für mehrere Accounts, die die Transaktion signieren müssen, einen Transfer auszuführen, wird bei dieser Implementierung zur Laufzeit mit einer Exception scheitern - auch wenn es erstmal keine Compiler-Fehler gibt.
Die Lösung dieses Problems erschließt sich erst, wenn man sich die Implementierung im SDK genauer ansieht. Da die Transaktion von allen Beteiligten zu signieren ist, muss die Transaktion erst „gebaut“ werden, um anschließend signierbar zu sein. Dies ist im folgenden Code veranschaulicht.
cryptoTransferTransaction ctx = new CryptoTransferTransaction(client)
.addSender(senderAccounts[0], 100)
.addSender(senderAccounts[1], 100)
.addRecipient(recipientAccountId, 200)
.setTransactionFee(10000)
Transaction tx = ct.build();
tx.sign(key[1]);
File Service API
Der Hedera-File-Service ermöglicht es, externe Daten in einem öffentlichen Ledger zu verankern. Bei den externen Daten kann es sich z. B. um den Hash eines Dokuments oder einer Datenbank handeln. Aber man kann auch ein eigenes klassisches PDF ablegen. Auch wenn das Ledger sicherlich nicht wirklich als File-System für große Dateien gedacht ist.
Die Services sind dabei in zwei Gruppen aufgeteilt:
- File Service Transactions (Möglichkeiten zum Anlegen, Andern oder Löschen von Dateien)
- File Service Query (Abfragen von Informationen zu einer Datei)
Nachfolgend eine Betrachtung der wesentlichen Services.
Create File
Der Service FileCreateTransaction() erstellt eine neue Datei, die über ihre ID im Ledger referenziert wird.
Diese ID erhält man bei einer erfolgreichen Ausführung der Anlage der Datei im Ledger in der Response.
Bei Ausführung des Beispiel-Codes unten, wird in dem Receipt eine File ID zurückgeliefert, die folgendermaßen aussieht:
file ID: 0.0.61975
Über diese ID kann die Datei später eindeutig identifiziert werden (z. B. bei File-Zugriffen).
Details zu den einzelnen Parametern können in der API-Dokumentation nachgelesen werden. Ich möchte hier nur auf einzelne Parameter eingehen.
public static TransactionReceipt createFile(
Client client,
byte[] fileContents,
long duration,
Ed25519PrivateKey[] keys) throws HederaException
{
FileCreateTransaction ftx;
Transaction tx;
//create new FileCreateTransaction
ftx = new FileCreateTransaction(client);
ftx.setExpirationTime(Instant.now().plus(Duration.ofSeconds(duration)));
for (int i=0; i< keys.length; i++) {
ftx.addKey((keys[i]).getPublicKey());
}
ftx.setContents(fileContents);
ftx.setTransactionFee(42_000_000 * keys.length);
//build FileCreateTransaction
tx = ftx.build();
//sign transaction
for (int i=1; i< keys.length; i++) {
tx.sign(keys[i]);
}
TransactionReceipt receipt = tx.executeForReceipt();
return receipt;
}
In dem Codebeispiel wird eine Datei angelegt, die mehrere Eigentümer hat. Das kann Sinn machen, wenn Dokumente wie z. B. ein Führerschein betrachtet werden. In diesem Fall wäre sowohl die Führerscheinstelle als auch der Inhaber Eigentümer des Dokuments.
Dazu müssen über die Methode addKey() alle Eigentümer (identifiziert über ihren Public Key) hinzugefügt werden, die anschließend auch die Transaktion mit der Methode sign() signieren müssen. Der Eigentümer des Accounts (im obigen Fall key[0]) signiert per Definition immer und muss nicht explizit angegeben werden.
Über die Methode setExpirationTime() kann die Lebensdauer der Datei definiert werden. Nach Ablauf dieser Zeit kann nicht mehr auf den Content zugegriffen werden.
Mit der Einführung der Transaction Fee ist diese auch entsprechend bei Ausführung von Transaktionen zu setzen. Zu den Kosten gibt es eine Übersicht bei Hedera. Für die Operation FileCreate werden 41.666.666,67 tℏ angegeben. Sollen mehrere Eigentümer angegeben werden, wie im obigen Beispiel zwei, dann muss die doppelte Anzahl angeben werden, da wir sonst eine entsprechende Exception erhalten.
Transaktionen sind in Hedera auf eine Größe von 4KB beschränkt. Ist eine Datei aber größer, dann muss diese zerlegt und mit dem Service FileAppendTransaction() schrittweise um die fehlenden Inhalte erweitert werden.
Append File
Mit dem Service FileAppendTransaction() kann einer existierenden Datei Content hinzufügt werden. Dazu benötigt man nur die File ID.
Aufbauend auf dem schon beschriebenen Service FileCreateTransaction() lassen sich damit auch größere Dateien über den File Service ablegen.
Der nachfolgende Code zeigt eine Lösung, bei der die zu speichernde Datei zerlegt und mit dem Service FileCreateTransaction() erstellt und anschließend die fehlenden Inhalte mit dem Service FileAppendTransaction() ergänzt werden. Zur besseren Übersicht sind einzelne Code-Teile in dem Beispiel nicht ausgeführt und durch „…“ ersetzt.
public static TransactionReceipt createLargeFile(
byte[] fileContents,
long duration, Ed25519PrivateKey[] key) throws HederaException
{
final int FILE_PART_SIZE = 1000; // 1K bytes
…
int numParts = fileContents.length / FILE_PART_SIZE;
int remainder = fileContents.length % FILE_PART_SIZE;
…
//find first parts of the file
firstPartBytes = Helper.copyBytes(0, FILE_PART_SIZE, fileContents);
….
// create the new file
TransactionReceipt receipt = createFile(firstPartBytes, duration, key);
…
// append the all parts
for (int i = 1; i < numParts; i++) {
byte[] partBytes = Helper.copyBytes(
i * FILE_PART_SIZE,
FILE_PART_SIZE,
fileContents);
…
appendReceipt = appendFile(partBytes, myFileId);
…
}
// append the rest of the file
…
return receipt;
}
Die im obigen Beispiel aufgerufene appendFile()-Methode, die der Service FileAppendTransaction() ausführt, ist sehr einfach.
public static TransactionReceipt appendFile(
byte[] fileContents,
FileId fileId) throws HederaException
{
var client = Helper.createHederaClient();
var tx = new FileAppendTransaction(client)
.setFileId(fileId)
.setContents(fileContents)
.setTransactionFee(42_000_000);
TransactionReceipt receipt = tx.executeForReceipt();
return receipt;
}
Neben den beiden detaillierter vorgestellten File-Service-Transaktionen gibt es noch Services zum Löschen oder Updaten von Dateien. Das Updaten ist bezüglich der Parameter im Wesentlichen zum Service FileCreateTransaction(), nur dass hier die File ID angeben werden muss, um zu identifizieren, welche Datei geändert werden soll.
Informationen zu einer Datei anzeigen
Mithilfe des Services FileInfoQuery() können verschiedene Informationen zu einer Datei gelesen werden. Diese bekommt man allerdings nur, wenn die Datei noch nicht abgelaufen ist. In der betrachteten Version des Testnet scheint dies aktuell nicht mehr zu funktionieren, da man auch für abgelaufene Dateien Informationen bekommt. In einer früheren Version hatte ich dies bereits getestet und bekam damals auch eine entsprechende Fehlermeldung.
…
var tx = new FileInfoQuery(client)
.setFileId(fileID);
FileInfo info = tx.execute();
…
Nach Ausführung erhält man die folgenden Infos im FileInfo-Objekt zurück:
keys: [302a300506032b6570032100ebeba69760b5b7d52c27867cbc857dee741722d9adf0df1dfebf819d0c321c0b, 302a300506032b65700321008cbb4189fcb252cf0a6f1bd32b7a35cf4b31691e58ba2731deb37e220a81f536]
file experation time: 2019-09-18T14:49:27Z
file size: 10
file Id: 0.0.61974
file deleted: false
In der Aktuellen Version des Testnets scheint es so zu sein, dass für diese Query noch keine Fee notwendig ist, auch wenn in der Dokumentation bereits eine Fee für die Query ausgewiesen wurde.
Ähnlich einfach kann man sich den Content der Datei anzeigen lassen.
Datei löschen
Das Löschen einer Datei ist in der aktuellen Umsetzung etwas widersprüchlich zur existierenden Dokumentation.
Im obigen Beispiel, in dem eine Datei mit zwei Eigentümern angelegt wurde, ist es aktuell auch notwendig, dass beide Eigentümer die Transaktion zum Löschen signieren müssen, sonst erhält man eine Exception.
…
FileDeleteTransaction dftx = new FileDeleteTransaction(client);
dftx.setFileId(fileID);
dftx.setTransactionFee(6_000_000 *2);
dftx.build();
Transaction tx = dftx.sign(key);
…
Das sign() fehlt in der konkreten Dokumentation zum Service FileDeleteTransaction() und passt so auch nicht zu der Beschreibungen der File Service API.
Zusammenfassung: IOTA vs Hashgraph
Was ist nun die Erkenntnis, die ich nach den vier Blogartikeln gewonnen habe? Beide DLTs IOTA und Hashgraph bieten einen vielversprechenden theoretischen Ansatz. Beide sind noch sehr jung in ihrer Umsetzung und müssen noch den Nachweis erbringen, dass sie im großen (versprochenen) Stil funktionieren. Aus Sicht der Implementierungsmöglichkeiten ist IOTA für mein Gefühl aktuell etwas besser aufgestellt. Einerseits existieren mehr und konkretere Informationen, sowohl von IOTA als auch aus der Community. Andererseits fallen hier bisher keine Kosten für Transaktionen an. Der Weg zur Umsetzung von ersten Prototypen ist somit relativ kurz. Des Weiteren gibt es über einen Tangle Browser eine gute Transparenz darüber, welche Daten im Tangle liegen. Was bei IOTA noch immer schwer wiegt, ist der noch existierende Coordinator. Erst mit dessen Entfernung kann der wirkliche funktionale Nachweis erbracht werden.
Hashgraph bzw. genauer gesagt das Hedera Distributed Ledger ist noch sehr stark in der Entwicklungsphase. Dies merkt man mit jedem Update des SDK. Aus Sicht der Implementierung eines Prototyps, ist hier ständig Bewegung im Code. Die Dokumentation bei Hedera ist aber so gut, dass man schnell mit einfachen Beispielen starten kann. In den Details scheint sie immer wieder in Teilen der Entwicklung voraus und in anderen Teilen hinterher zu hinken. Ein weiteres Problem ist, dass aktuell nicht so einfach reproduzierbar ist, welche Daten wirklich wie im Hashgraph liegen. Es gibt kein eigenes Tooling, wie den Tangle Browser bei IOTA, um sich Transaktionen bzw. die Daten direkt im Graphen anzusehen.
Alle bisherigen Ideen (wie z. B. die Möglichkeiten mehrere Eigentümer für ein Asset zu definieren) sind vielversprechend, müssen sich aber erst in der Praxis beweisen.
Da der Hashgraph-Algorithmus patentiert ist, ist es schwer abzusehen, wie sich die Kosten für Transaktionen entwickeln werden.
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.