Die Augen fürchten sich, aber die Hände jucken!
In den früheren Artikeln haben wir uns mit den Technologien beschäftigt, auf denen Blockchains basieren () und den Anwendungsfällen, die wir damit umsetzen können (). Es ist an der Zeit, selbst aktiv zu werden! Für die Umsetzung von Prototypen und PoC (Proof of Concept) bevorzuge ich es, Cloud-Dienste zu nutzen, da man von überall auf der Welt darauf zugreifen kann und man oft keine Zeit mit der mühsamen Installation der Umgebung verschwenden muss, da es vorkonfigurierte Setups gibt. Lassen Sie uns etwas Einfaches machen, zum Beispiel ein Netzwerk zur Übertragung von Münzen zwischen den Teilnehmern und nennen wir es bescheiden Citcoin. Dafür verwenden wir die IBM-Cloud und die universelle Blockchain Hyperledger Fabric. Zuerst klären wir, warum Hyperledger Fabric als universelle Blockchain bezeichnet wird.

Hyperledger Fabric — die universelle Blockchain
Allgemein gesagt, ist ein universelles Informationssystem:
- Eine Gruppe von Servern und eine Software, die die Geschäftslogik ausführt;
- Schnittstellen zur Interaktion mit dem System;
- Mittel zur Registrierung, Authentifizierung und Autorisierung von Geräten/Menschen;
- Eine Datenbank, die operative und archivierte Daten speichert:

Die offizielle Version von Hyperledger Fabric kann man nachlesen auf , kurz gesagt, Hyperledger Fabric ist eine Open-Source-Plattform, die es ermöglicht, private Blockchains zu erstellen und beliebige Smart Contracts auszuführen, die in den Programmiersprachen JS und Go geschrieben sind. Lassen Sie uns detailliert auf die Architektur von Hyperledger Fabric schauen und sicherstellen, dass es sich um ein universelles System handelt, das nur spezifische Anforderungen an Speicherung und Aufzeichnung von Daten hat. Die Spezifikationen besagen, dass die Daten, wie in allen Blockchains, in Blöcken gespeichert werden, die nur dann in die Blockchain aufgenommen werden, wenn die Teilnehmer einen Konsens erreicht haben, und nach der Aufzeichnung können die Daten nicht unbemerkt verändert oder gelöscht werden.
Die Architektur von Hyperledger Fabric
Das Diagramm zeigt die Architektur von Hyperledger Fabric:

Organisationen — Organisationen enthalten Peers, wodurch die Blockchain durch die Unterstützung der Organisationen existiert. Verschiedene Organisationen können Teil eines Channels sein.
Channel — eine logische Struktur, die Peers in Gruppen zusammenfasst, wodurch die Blockchain definiert wird. Hyperledger Fabric kann gleichzeitig mehrere Blockchains mit unterschiedlicher Geschäftslogik verarbeiten.
Membership Services Provider (MSP) — ist ein CA (Zertifizierungsstelle) zur Ausstellung von Identitäten und zur Zuweisung von Rollen. Um einen Node zu erstellen, muss man mit dem MSP interagieren.
Peer-Nodes — sie überprüfen Transaktionen, speichern die Blockchain, führen Smart Contracts aus und interagieren mit Anwendungen. Peers haben eine Identität (digitales Zertifikat), das von MSP ausgestellt wird. Im Gegensatz zum Bitcoin- oder Ethereum-Netzwerk, in dem alle Knoten gleichberechtigt sind, haben die Knoten in Hyperledger Fabric unterschiedliche Rollen:
- Peer kann sein endorsender Peer (EP) und führen Smart Contracts aus.
- Committer Peer (CP) — speichert nur Daten in der Blockchain und aktualisiert den "Weltzustand".
- Anker-Peer (AP) — wenn mehrere Organisationen an der Blockchain teilnehmen, werden Anker-Peer zur Verbindung zwischen ihnen verwendet. Jede Organisation muss einen oder mehrere Anker-Peer haben. Mithilfe von AP kann jeder Peer in der Organisation Informationen über alle Peers in anderen Organisationen abrufen. Für die Synchronisierung der Informationen zwischen AP wird .
- Leader-Peer — wenn eine Organisation mehrere Peers hat, wird nur der Leader-Peer Blöcke vom Ordering-Service erhalten und sie an die anderen Peers weitergeben. Der Leader kann statisch festgelegt oder dynamisch von den Peers in der Organisation ausgewählt werden. Auch für die Synchronisierung der Informationen über die Leader wird das Gossip-Protokoll verwendet.
Assets — Werte, die in der Blockchain gespeichert sind. Genauer gesagt sind dies Key-Value-Daten im JSON-Format. Diese Daten werden in die Blockchain "Blockchain" geschrieben. Sie haben eine Historie, die in der Blockchain gespeichert ist, und einen aktuellen Zustand, der in der Datenbank "Weltzustand" gespeichert ist. Die Datenstrukturen werden je nach Geschäftsanforderungen zufällig gefüllt. Es gibt keine obligatorischen Felder, die einzige Empfehlung ist, dass Assets einen Besitzer haben und einen Wert darstellen.
Ledger — besteht aus der Blockchain "Blockchain" und der Datenbank "Weltzustand", in der der aktuelle Zustand der Assets gespeichert ist. Der Weltzustand verwendet LevelDB oder CouchDB.
Smart Contract — die Geschäftslogik des Systems wird durch Smart Contracts umgesetzt. In Hyperledger Fabric werden Smart Contracts Chaincode genannt. Mit Chaincode werden Assets und Transaktionen darüber definiert. Technisch gesprochen sind Smart Contracts Programmiermodule, die in den Programmiersprachen JS oder Go implementiert sind.
Endorsement-Politik — für jeden Chaincode können Richtlinien festgelegt werden, wie viele und von wem Bestätigungen für die Transaktion erwartet werden müssen. Wenn keine Politik festgelegt ist, wird standardmäßig verwendet: 'Die Transaktion muss von einem Mitglied (Member) jeder Organisation im Channel bestätigt werden.' Beispiele für Politiken:
- Die Transaktion muss von einem beliebigen Administrator der Organisation bestätigt werden;
- Jedes Mitglied oder jeder Kunde der Organisation muss bestätigen;
- Jeder Peer der Organisation muss bestätigen.
Bestelldienst – verpackt Transaktionen in Blöcke und sendet sie an die Peers im Kanal. Garantiert die Zustellung von Nachrichten an alle Peers im Netzwerk. Für industrielle Systeme wird , für Entwicklung und Test .
CallFlow

- Die Anwendung interagiert mit Hyperledger Fabric, indem sie das Go-, Node.js- oder Java-SDK verwendet;
- Der Client erstellt die Transaktion tx und sendet sie an die Endorsing-Peers;
- Der Peer überprüft die Signatur des Clients, führt die Transaktion aus und sendet die Bestätigungssignatur zurück an den Client. Chaincode wird nur auf Endorsing-Peers ausgeführt, und das Ergebnis wird an alle Peers verteilt. Ein solches Verfahren wird als PBFT (Practical Byzantine Fault Tolerant) Konsens bezeichnet. Es unterscheidet sich von dadurch, dass die Nachricht verteilt wird und die Bestätigung nicht von allen Teilnehmern, sondern nur von einer bestimmten Gruppe erwartet wird;
- Nachdem der Client die Anzahl der Antworten erhalten hat, die der Bestätigungsrichtlinie entspricht, sendet er die Transaktion an den Bestelldienst;
- Der Bestelldienst erstellt den Block und sendet ihn an alle Commit-Peers. Der Bestelldienst sorgt für die sequentielle Aufzeichnung der Blöcke, was einen sogenannten Ledger-Fork ausschließt ();
- Die Peers erhalten den Block, überprüfen erneut die Bestätigungsrichtlinie, speichern den Block in der Blockchain und ändern den Status in der „Weltzustands“-Datenbank.
Das heißt, es erfolgt eine Rollenverteilung zwischen den Knoten. Dies sorgt für Skalierbarkeit und Sicherheit der Blockchain:
- Smart Contracts (Chaincode) werden von den Endorsing-Peers ausgeführt. Dies gewährleistet die Vertraulichkeit der Smart Contracts, da sie nicht bei allen Teilnehmern gespeichert werden, sondern nur bei den Endorsing-Peers.
- Die Bestellung muss schnell arbeiten. Dies wird dadurch sichergestellt, dass die Bestellung nur den Block erstellt und ihn an eine feste Anzahl von Leader-Peers sendet.
- Commit-Peers speichern nur die Blockchain – es können viele davon vorhanden sein und sie erfordern keine große Leistung oder sofortige Verarbeitung.
Weitere Informationen zu den architektonischen Entscheidungen von Hyperledger Fabric und warum es so funktioniert, wie es funktioniert, finden Sie hier: oder hier: .
Also ist Hyperledger Fabric tatsächlich ein universelles System, mit dem man:
- beliebige Geschäftslogik mit Hilfe des Smart Contract-Mechanismus umsetzen kann;
- Daten in einem Blockchain-Datenbankformat JSON aufzeichnen und abrufen;
- Zugriff auf die API bereitstellen und überprüfen unter Verwendung einer Zertifizierungsstelle.
Jetzt, da wir ein wenig über die Besonderheiten von Hyperledger Fabric verstanden haben, lasst uns endlich etwas Nützliches tun!
Blockchain bereitstellen
Aufgabenstellung
Die Aufgabe besteht darin, ein Citcoin-Netzwerk mit folgenden Funktionen zu implementieren: ein Konto erstellen, den Kontostand abrufen, das Konto aufladen, Münzen von einem Konto auf ein anderes übertragen. Wir werden ein objektdiagramm zeichnen, das wir später in einem Smart Contract umsetzen. Also, wir werden Konten haben, die durch Namen (name) identifiziert werden und einen Kontostand (balance) sowie eine Liste von Konten enthalten. Konten und die Liste der Konten sind in den Begriffen von Hyperledger Fabric Assets. Dementsprechend haben sie eine Historie und einen aktuellen Zustand. Ich werde versuchen, dies anschaulich darzustellen:

Die oberen Figuren sind der aktuelle Zustand, der in der 'World state'-Datenbank gespeichert ist. Darunter sind die Figuren, die die Historie zeigen, die in der Blockchain gespeichert ist. Der aktuelle Zustand der Assets wird durch Transaktionen geändert. Ein Asset ändert sich nur ganz, weshalb als Ergebnis der Ausführung einer Transaktion ein neues Objekt erstellt wird und der aktuelle Wert des Assets in die Historie übergeht.
IBM Cloud
Ein Konto in . Um die Blockchain-Plattform nutzen zu können, muss sie auf Pay-As-You-Go aktualisiert werden. Dieser Prozess kann nicht schnell sein, da IBM zusätzliche Informationen anfordert und diese manuell überprüft. Aus dem Positive kann ich sagen, dass IBM gute Schulungsmaterialien hat, die es ermöglichen, Hyperledger Fabric in ihrer Cloud einzurichten. Mir hat der folgende Artikelzyklus und die Beispiele gefallen:
Im Folgenden sind Screenshots der IBM Blockchain-Plattform aufgeführt. Dies ist keine Anleitung zur Erstellung einer Blockchain, sondern einfach eine Demonstration des Umfangs der Aufgabe. Für unsere Zwecke erstellen wir eine Organisation:

Darin erstellen wir Knoten: Orderer CA, Org1 CA, Orderer Peer:

Wir legen Benutzer an:

Wir erstellen einen Channel und nennen ihn citcoin:

Im Grunde genommen ist ein Channel eine Blockchain, weshalb er mit einem nullten Block (Genesis block) beginnt:

Wir schreiben einen Smart Contract
/*
* Citcoin smart-contract v1.5 for Hyperledger Fabric
* (c) Alexey Sushkov, 2019
*/
'use strict';
const { Contract } = require('fabric-contract-api');
const maxAccounts = 5;
class CitcoinEvents extends Contract {
async instantiate(ctx) {
console.info('instantiate');
let emptyList = [];
await ctx.stub.putState('accounts', Buffer.from(JSON.stringify(emptyList)));
}
// Get all accounts
async GetAccounts(ctx) {
// Get account list:
let accounts = '{}'
let accountsData = await ctx.stub.getState('accounts');
if (accountsData) {
accounts = JSON.parse(accountsData.toString());
} else {
throw new Error('accounts not found');
}
return accountsData.toString()
}
// add a account object to the blockchain state identifited by their name
async AddAccount(ctx, name, balance) {
// this is account data:
let account = {
name: name,
balance: Number(balance),
type: 'account',
};
// create account:
await ctx.stub.putState(name, Buffer.from(JSON.stringify(account)));
// Add account to list:
let accountsData = await ctx.stub.getState('accounts');
if (accountsData) {
let accounts = JSON.parse(accountsData.toString());
if (accounts.length < maxAccounts)
{
accounts.push(name);
await ctx.stub.putState('accounts', Buffer.from(JSON.stringify(accounts)));
} else {
throw new Error('Max accounts number reached');
}
} else {
throw new Error('accounts not found');
}
// return object
return JSON.stringify(account);
}
// Sends money from Account to Account
async SendFrom(ctx, fromAccount, toAccount, value) {
// get Account from
let fromData = await ctx.stub.getState(fromAccount);
let from;
if (fromData) {
from = JSON.parse(fromData.toString());
if (from.type !== 'account') {
throw new Error('wrong from type');
}
} else {
throw new Error('Accout from not found');
}
// get Account to
let toData = await ctx.stub.getState(toAccount);
let to;
if (toData) {
to = JSON.parse(toData.toString());
if (to.type !== 'account') {
throw new Error('wrong to type');
}
} else {
throw new Error('Accout to not found');
}
// update the balances
if ((from.balance - Number(value)) >= 0 ) {
from.balance -= Number(value);
to.balance += Number(value);
} else {
throw new Error('From Account: not enought balance');
}
await ctx.stub.putState(from.name, Buffer.from(JSON.stringify(from)));
await ctx.stub.putState(to.name, Buffer.from(JSON.stringify(to)));
// define and set Event
let Event = {
type: "SendFrom",
from: from.name,
to: to.name,
balanceFrom: from.balance,
balanceTo: to.balance,
value: value
};
await ctx.stub.setEvent('SendFrom', Buffer.from(JSON.stringify(Event)));
// return to object
return JSON.stringify(from);
}
// get the state from key
async GetState(ctx, key) {
let data = await ctx.stub.getState(key);
let jsonData = JSON.parse(data.toString());
return JSON.stringify(jsonData);
}
// GetBalance
async GetBalance(ctx, accountName) {
let data = await ctx.stub.getState(accountName);
let jsonData = JSON.parse(data.toString());
return JSON.stringify(jsonData);
}
// Refill own balance
async RefillBalance(ctx, toAccount, value) {
// get Account to
let toData = await ctx.stub.getState(toAccount);
let to;
if (toData) {
to = JSON.parse(toData.toString());
if (to.type !== 'account') {
throw new Error('wrong to type');
}
} else {
throw new Error('Accout to not found');
}
// update the balance
to.balance += Number(value);
await ctx.stub.putState(to.name, Buffer.from(JSON.stringify(to)));
// define and set Event
let Event = {
type: "RefillBalance",
to: to.name,
balanceTo: to.balance,
value: value
};
await ctx.stub.setEvent('RefillBalance', Buffer.from(JSON.stringify(Event)));
// return to object
return JSON.stringify(from);
}
}
module.exports = CitcoinEvents;
Hier sollte alles intuitiv verständlich sein:
- Es gibt mehrere Funktionen (AddAccount, GetAccounts, SendFrom, GetBalance, RefillBalance), die das Demo-Programm über die Hyperledger Fabric API aufrufen wird.
- Die Funktionen SendFrom und RefillBalance generieren Ereignisse (Event), die das Demo-Programm erhalten wird.
- Die Funktion instantiate wird einmal beim Instanziieren des Smart Contracts aufgerufen. Tatsächlich wird sie nicht nur einmal aufgerufen, sondern jedes Mal, wenn die Version des Smart Contracts geändert wird. Daher ist die Initialisierung der Liste mit einem leeren Array eine schlechte Idee, da wir bei der Versionsänderung des Smart Contracts die aktuelle Liste verlieren würden. Aber macht nichts, ich lerne ja nur).
- Accounts und die Liste der Accounts (accounts) sind JSON-Datenstrukturen. Für die Manipulation der Daten wird JS verwendet.
- Den aktuellen Wert des Assets kann man mit dem Aufruf der Funktion getState abrufen und mit putState aktualisieren.
- Beim Erstellen eines Accounts wird die Funktion AddAccount aufgerufen, in der mit der maximalen Anzahl der Accounts in der Blockchain (maxAccounts = 5) verglichen wird. Und hier gibt es einen Fehler (habt ihr ihn bemerkt?), der zu einem unbegrenzten Wachstum der Anzahl der Accounts führt. Solche Fehler sollten vermieden werden).
Laden Sie dann den Smart Contract in den Channel und instanziieren Sie ihn:

Überprüfen Sie die Transaktion zur Einrichtung des Smart Contracts:

Sehen Sie sich die Details zu unserem Channel an:

Infolgedessen erhalten wir das folgende Schema des Blockchain-Netzwerks in der IBM-Cloud. Auf dem Schema ist auch ein Demo-Programm zu sehen, das in der Amazon-Cloud auf einem virtuellen Server läuft (detaillierte Informationen dazu gibt es im nächsten Abschnitt):

Erstellung einer GUI für Aufrufe des Hyperledger Fabric API
Hyperledger Fabric verfügt über eine API, die für Folgendes verwendet werden kann:
- Erstellung eines Channels;
- Verbindung eines Peers mit einem Channel;
- Installation und Instanziierung von Smart Contracts im Channel;
- Aufruf von Transaktionen;
- Anforderung von Informationen in der Blockchain.
Anwendungsentwicklung
In unserem Demo-Programm werden wir die API nur für den Aufruf von Transaktionen und die Anforderung von Informationen verwenden, da wir die anderen Schritte bereits durchgeführt haben, indem wir die IBM-Blockchain-Plattform genutzt haben. Wir schreiben die GUI unter Verwendung des Standard-Technologiestacks: Express.js + Vue.js + Node.js. Wie man moderne Webanwendungen erstellt, könnte man einen separaten Artikel schreiben. Hier lasse ich einen Link zu einer Vorlesungsreihe, die mir am besten gefallen hat: . Infolgedessen entstand eine Client-Server-Anwendung mit einer vertrauten grafischen Benutzeroberfläche im Stil des Material Designs von Google. Die REST API zwischen Client und Server besteht aus mehreren Aufrufen:
- HyperledgerDemo/v1/init — Blockchain initialisieren;
- HyperledgerDemo/v1/accounts/list — Liste aller Accounts abrufen;
- HyperledgerDemo/v1/account?name=Bob&balance=100 — Bob Account erstellen;
- HyperledgerDemo/v1/info?account=Bob — Informationen zum Bob Account abrufen;
- HyperledgerDemo/v1/transaction?from=Bob&to=Alice&volume=2 — zwei Münzen von Bob an Alice überweisen;
- HyperledgerDemo/v1/disconnect – die Verbindung zur Blockchain schließen.
Die API-Beschreibung mit Beispielen habe ich auf – einem weit verbreiteten Programm zum Testen von HTTP-APIs.
Demo-Anwendung in der Cloud von Amazon
Ich habe die Anwendung auf Amazon hochgeladen, da IBM immer noch nicht in der Lage war, mein Konto zu aktualisieren und mir zu erlauben, virtuelle Server zu erstellen. Als Sahnehäubchen habe ich die Domain hinzugefügt: . Ich werde den Server ein wenig laufen lassen, dann aber abschalten, da die Kosten für die Miete anfallen und die Citcoin-Münzen an der Börse noch nicht gehandelt werden) Ich füge Screenshots der Demo hinzu, um die Logik der Funktionsweise zu verdeutlichen. Die Demo-Anwendung kann:
- Die Blockchain initialisieren;
- Ein Konto erstellen (aber zurzeit kann kein neues Konto erstellt werden, da in der Blockchain die maximal Anzahl an Konten, die im Smart Contract festgelegt ist, erreicht wurde);
- Eine Liste der Konten abrufen;
- Citcoin-Münzen zwischen Alice, Bob und Alex transferieren;
- Ereignisse abrufen (aber derzeit können Ereignisse nicht angezeigt werden, deshalb steht im Interface vereinfacht, dass Ereignisse nicht unterstützt werden);
- Aktionen protokollieren.
Zuerst initialisieren wir die Blockchain:

Dann legen wir unser Konto an und sparen nicht am Guthaben:

Wir holen die Liste aller verfügbaren Konten:

Wir wählen den Absender und den Empfänger aus und erhalten deren Guthaben. Wenn Absender und Empfänger dieselbe Person sind, wird das Konto aufgeladen:

Im Log überwachen wir die Ausführung der Transaktionen:

Mit der Demo-Anwendung sind wir damit am Ende. Weiterhin können wir unsere Transaktion in der Blockchain betrachten:

Und die Gesamtliste der Transaktionen:

Damit haben wir erfolgreich die Implementierung des PoC zur Schaffung des Citcoin-Netzes abgeschlossen. Was müssen wir noch tun, damit Citcoin ein vollwertiges Netzwerk für die Übertragung von Münzen wird? Nicht viel:
- Bei der Erstellung des Kontos die Generierung des privaten / öffentlichen Schlüssels umsetzen. Der private Schlüssel soll beim Benutzer des Kontos aufbewahrt werden, der öffentliche in der Blockchain.
- Die Übertragung von Münzen so gestalten, dass zur Identifizierung des Benutzers nicht der Name, sondern der öffentliche Schlüssel verwendet wird.
- Transaktionen, die vom Benutzer an den Server gesendet werden, mit seinem privaten Schlüssel verschlüsseln.
Fazit
Wir haben das Citcoin-Netzwerk mit Funktionen implementiert: Konto hinzufügen, Guthaben abrufen, das eigene Konto aufladen, Münzen von einem Konto auf ein anderes übertragen. Was hat uns also der PoC gekostet, um es aufzubauen?
- Wir mussten die Blockchain allgemein und Hyperledger Fabric im Besonderen studieren;
- Wir mussten lernen, die Cloud-Dienste von IBM oder Amazon zu nutzen;
- Wir mussten die Programmiersprache JS und ein Web-Framework lernen;
- Wenn bestimmte Daten nicht in der Blockchain, sondern in einer separaten Datenbank gespeichert werden müssen, lernen Sie, sich beispielsweise mit PostgreSQL zu integrieren;
- Und das Letzte auf der Liste, aber nicht weniger wichtig – ohne Linux-Kenntnisse kommt man in der modernen Welt nicht weit!)
Natürlich ist es keine Raketenwissenschaft, aber Sie müssen sich anstrengen!
Quellcodes auf GitHub
Ich habe die Quellcodes auf . Kurze Beschreibung des Repositories:
Das Verzeichnis „server“ – Node.js-Server
Das Verzeichnis „client“ – Node.js-Client
Das Verzeichnis „blockchain“ (die Parameterwerte und Schlüssel sind natürlich nicht funktionsfähig und dienen nur als Beispiel):
- contract – Quellcode des Smart Contracts
- wallet – Benutzerschlüssel zur Verwendung der Hyperledger Fabric API.
- *.cds – kompilierte Versionen von Smart Contracts
- *.json-Dateien – Beispielkonfigurationsdateien für die Verwendung der Hyperledger Fabric API
Es ist erst der Anfang!
Quelle: habr.com
