Neues Hyperledger Fabric: Go SDK-Softwaremodell



In einem früheren Artikel haben wir über das neue Programmiermodell des Codecodes in Hyperledger Fabric gesprochen. Obwohl die Veröffentlichung des neuen Go SDK noch nicht stattgefunden hat, hindert uns nichts daran, zu sehen, was uns in Zukunft erwartet, und es sogar an einem Testbuild zu testen. Es ist noch nicht alles implementiert (z. B. Commit-Handler ), aber das geplante Design des Softwaremodells ist bereits klar. Schauen wir uns das genauer an.

In diesem Repository habe ich das Beispielraster geringfügig geändert, sodass es mit dem Kettencode beginnt, den wir im vorherigen Artikel gesehen haben, und einen einfachen Client hinzugefügt, der mit der neuen API geschrieben wurde. Das Repository enthält einfache Anweisungen zum Starten und Konfigurieren des Netzwerks.

Wie Sie in go.mod sehen können, verwenden wir zur Verwendung der neuen API keine Version (es gibt noch keine Version), sondern alle Änderungen an einem bestimmten Commit (dies ist eine vorübergehende Maßnahme vor der Veröffentlichung der Version): In unserer Anwendung importieren wir das Gateway-Paket in app.go. Das Wesentliche der neuen API Bereitstellung gemeinsamer Abstraktionen für alle SDKs (go, node, java) und Reduzierung der vom Entwickler von Projekt zu Projekt übertragenen Boilerplate. Eine solche Abstraktion ist Wallet.

require github.com/hyperledger/fabric-sdk-go v1.0.0-beta1.0.20200404205634-0e550fc1a918



"github.com/hyperledger/fabric-sdk-go/pkg/gateway"

. Die Initialisierung der Brieftasche sieht folgendermaßen aus:

wallet, err := gateway.NewFileSystemWallet("wallet")
if err != nil {
	fmt.Errorf(err.Error())
}

err = wallet.Put("admin", gateway.NewX509Identity("Org1MSP", string(cert), string(privKey)))
if err != nil {
	fmt.Errorf(err.Error())
}

Wallet ist eine Implementierung der WalletStore-Oberfläche:

type WalletStore interface {
	Put(label string, stream []byte) error
	Get(label string) ([]byte, error)
	List() ([]string, error)
	Exists(label string) bool
	Remove(label string) error
}

Wie Sie sehen können, beschreibt diese Schnittstelle die grundlegenden Operationen mit der Benutzeridentität speichern . Zusätzlich zum Dateisystem kann die Identität im Speicher gespeichert werden. Verwenden Sie einfach eine andere integrierte Factory - NewInMemoryWallet () . Stellen Sie eine Verbindung zum Netzwerk her:



gw, err := gateway.Connect(gateway.WithConfig(config.FromFile("./../connection-org1.yaml")),
gateway.WithIdentity(wallet, "admin"),
gateway.WithDiscovery(true),
gateway.WithCommitHandler(gateway.DefaultCommitHandlers.OrgAny))

gateway.Connect () gibt einen Zeiger auf Gateway zurück , ein Objekt, das Netzwerkkonnektivität bereitstellt. gateway.WithCommitHandler - eine funktionale Option zum Festlegen einer Strategie zum Warten auf Festschreibungsereignisse . Bisher wurde keine Strategie implementiert (was bedeutet, dass die Standardstrategie des "alten" SDK "Warten auf Commits von allen Endorsern" verwendet wird ), aber Folgendes ist geplant:

  • gateway.DefaultCommitHandlers.OrgAll - Warten Sie auf ein Commit bei allen Peers der Organisation (standardmäßig).
  • gateway.DefaultCommitHandlers.OrgAny - Warten auf ein Commit bei einem Organisations- Peer
  • gateway.DefaultCommitHandlers.NetworkAll - Warten auf ein Commit bei allen Peers aller Organisationen im Kanal
  • gateway.DefaultCommitHandlers.NetworkAny - Warten auf ein Commit bei einem Peer im Kanal

Sie können überhaupt nicht auf Commits warten, dazu später mehr, aber achten Sie zuerst darauf:

network, err := gw.GetNetwork("mychannel")
if err != nil {
	panic(err)
}

contract := network.GetContract("mycc")

Zuerst erhalten wir vom Kanal eine Teilmenge von Peers, mit denen wir interagieren werden, und dann einen Zeiger auf Contract, dessen Methoden es uns ermöglichen, mit dem Kettencode zu interagieren.

Jetzt haben wir die Möglichkeit zu bestimmen, ob eine Strategie zum Warten auf ein Commit verwendet werden soll oder nicht. Schauen wir uns zunächst eine Transaktion an, bei der ein Commit wartet:

result, err := contract.SubmitTransaction("Create", "b", "50")


Hier starten wir die Simulation der Transaktion beim Peer, erhalten die Antwort, senden die Angebotsantwort an den Besteller, warten auf die Validierung und legen gemäß der obigen Strategie fest, um auf das Festschreiben zu warten. Standard und vertrautes Verhalten. Wir schauen weiter.

result, err := contract.EvaluateTransaction("Read", "b")
	if err != nil {
		panic(err)
	}
fmt.Println(string(result))

In diesem Fall erhält der Kunde eine Angebotsantwort und unternimmt nichts anderes. Wir erwarten keine Commits . Dies sollte verwendet werden, um den Status zu lesen.

transient := make(map[string][]byte)
transient["someTransient"] = []byte("mytransientdata")
txn, err := contract.CreateTransaction("Update", gateway.WithTransient(transient))
if err != nil {
	panic(err)
}
result, err = txn.Submit("b", "100")
if err != nil {
	panic(err)
}

contract.CreateTransaction bietet etwas mehr Kontrolle über die Transaktion, nämlich die Möglichkeit, funktionale Optionen zu übergeben:

  • gateway.WithTransient (transient) - zum Senden privater Daten
  • gateway.WithEndorsingPeers ("peer0.org1.example.com") - zum manuellen Bestimmen von Zielen


Rufen Sie app.go auf und ersetzen Sie die Transaktionsmethoden durch verschiedene Schlüssel, Werte und Optionen, um zu sehen, wie dies funktioniert.

Damit ist die Überprüfung der neuen API abgeschlossen. Übrigens ist es ganz einfach, Ihre eigene Brieftasche zu implementieren, Handler und Identität festzulegen, sodass Sie Standardimplementierungen zu denen hinzufügen können, die Ihren Zielen entsprechen, oder der Community Ihre eigenen Ideen und Ihren eigenen Code anbieten können.

Vielen Dank für Ihre Aufmerksamkeit.

All Articles