Nouveau tissu Hyperledger: modèle de logiciel Go SDK



Dans un article précédent, nous avons parlé du nouveau modèle de programmation du codecode dans Hyperledger Fabric. Bien que la sortie du nouveau Go SDK n'ait pas encore eu lieu, rien ne nous empêche maintenant de voir ce qui nous attend dans le futur, et même de le tester sur un build de test. Tout n'est pas encore implémenté (comme les gestionnaires de validation ), mais la conception prévue du modèle logiciel est déjà claire, alors examinons-le de plus près.

Dans ce référentiel, j'ai légèrement modifié l'exemple de grille pour qu'il commence par le code de chaîne que nous avons vu dans l'article précédent et ajouté un client simple écrit à l'aide de la nouvelle API. Le référentiel contient des instructions simples pour démarrer et configurer le réseau.

Comme vous pouvez le voir dans go.mod , pour utiliser la nouvelle API, nous ne prenons pas de version (il n'y a pas encore de version), mais toutes les modifications apportées à un commit spécifique (il s'agit d'une mesure temporaire avant la publication de la version): dans notre application, nous importons le package de la passerelle dans app.go. L'essence de la nouvelle API en fournissant des abstractions communes à tous les SDK (go, node, java) et en réduisant le passe-partout transféré par le développeur d'un projet à l'autre. Une telle abstraction est Wallet.

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



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

. L'initialisation du portefeuille ressemble à ceci:

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 est une implémentation de l'interface WalletStore:

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
}

Comme vous pouvez le voir, cette interface décrit les opérations de base avec le référentiel d' identité des utilisateurs. En plus du système de fichiers, l'identité peut être stockée en mémoire, il suffit d'utiliser une autre usine intégrée - NewInMemoryWallet () .

Connectez-vous au réseau:

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 () renvoie un pointeur sur Gateway , un objet qui fournit la connectivité réseau. gateway.WithCommitHandler - une option fonctionnelle pour définir une stratégie d'attente des événements de validation. Jusqu'à présent, aucune stratégie n'a été mise en œuvre (ce qui signifie que la stratégie par défaut de "l'ancien" SDK "attendre les validations de tous les endosseurs" sera utilisée ), mais ce qui suit est prévu:

  • gateway.DefaultCommitHandlers.OrgAll - attend un commit sur tous les pairs de l'organisation (par défaut)
  • gateway.DefaultCommitHandlers.OrgAny - en attente d'un commit sur n'importe quel homologue d' organisation
  • gateway.DefaultCommitHandlers.NetworkAll - en attente d'un commit sur tous les pairs de toutes les organisations du canal
  • gateway.DefaultCommitHandlers.NetworkAny - en attente d'une validation sur n'importe quel homologue du canal

Vous ne pouvez même pas attendre du tout les commits, plus à ce sujet plus tard, mais faites d'abord attention à ceci:

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

contract := network.GetContract("mycc")

Tout d'abord, nous obtenons du canal un sous-ensemble de pairs avec lesquels nous allons interagir, puis un pointeur vers Contract, dont les méthodes nous permettront d'interagir avec le code de chaîne.

Nous avons maintenant la possibilité de déterminer s'il convient ou non d'utiliser une sorte de stratégie pour attendre un commit. Voyons d'abord une transaction avec une attente de validation:

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


Ici, nous commençons la simulation de la transaction chez l'homologue, obtenons la réponse, envoyons la réponse de la proposition au client, attendons la validation et validons conformément à la stratégie ci-dessus pour attendre la validation. Comportement standard et familier. Nous regardons plus loin.

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

Dans ce cas, le client reçoit une réponse à la proposition et ne fait rien d'autre. Nous n'attendons aucun engagement . Cela devrait être utilisé pour lire l'état.

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 donne un peu plus de contrôle sur la transaction, à savoir la possibilité de passer des options fonctionnelles:

  • gateway.WithTransient (transitoire) - pour envoyer des données privées
  • gateway.WithEndorsingPeers ("peer0.org1.example.com") - pour déterminer manuellement les cibles


Essayez d'appeler app.go , en substituant diverses clés, valeurs et options dans des méthodes transactionnelles pour voir comment cela fonctionne.

Ceci conclut l'examen de la nouvelle API. Soit dit en passant, il est assez facile d'implémenter votre propre portefeuille, de valider les gestionnaires et votre identité, de sorte que vous pouvez ajouter des implémentations standard à celles qui répondent à vos objectifs ou proposer des idées et du code à votre communauté.

Merci pour l'attention.

All Articles