Nuevo tejido Hyperledger: modelo de software Go SDK



En un artículo anterior, hablamos sobre el nuevo modelo de programación del código de código en Hyperledger Fabric. Aunque el lanzamiento del nuevo Go SDK aún no ha tenido lugar, nada nos impide ahora ver lo que nos espera en el futuro, e incluso probarlo en una versión de prueba. No todo está implementado (como los controladores de confirmación ), pero el diseño planificado del modelo de software ya está claro, así que echemos un vistazo más de cerca.

En este repositorio, modifiqué ligeramente la cuadrícula de muestra para que comience con el chaincode que vimos en el artículo anterior y agregué un cliente simple escrito con la nueva API. El repositorio tiene instrucciones simples para iniciar y configurar la red.

Como puede ver en go.mod , para usar la nueva API no tomamos una versión (todavía no hay una versión), sino todos los cambios en una confirmación específica (esta es una medida temporal antes de la publicación de la versión): en nuestra aplicación, importamos el paquete de puerta de enlace en app.go. La esencia de la nueva API para proporcionar abstracciones comunes para todos los SDK (go, node, java) y reducir la repetitiva transferida por el desarrollador de un proyecto a otro. Una de esas abstracciones es Wallet.

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



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

. La inicialización de la billetera se ve así:

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 es una implementación de la interfaz 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
}

Como puede ver, esta interfaz describe las operaciones básicas con el repositorio de identidad del usuario. Además del sistema de archivos, la identidad se puede almacenar en la memoria, solo use otra fábrica incorporada : NewInMemoryWallet () .

Conéctese a la red:

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 () devuelve un puntero a Gateway , un objeto que proporciona conectividad de red. gateway.WithCommitHandler : una opción funcional para establecer una estrategia para esperar eventos de confirmación. Hasta el momento, no se ha implementado ninguna estrategia (lo que significa que se utilizará la estrategia predeterminada del "antiguo" SDK "esperar confirmaciones de todos los endosantes" ), pero se planea lo siguiente:

  • gateway.DefaultCommitHandlers.OrgAll : espera una confirmación en todos los pares de la organización (de forma predeterminada)
  • gateway.DefaultCommitHandlers.OrgAny - esperando una confirmación en cualquier par de la organización
  • gateway.DefaultCommitHandlers.NetworkAll : esperando una confirmación en todos los pares de todas las organizaciones del canal
  • gateway.DefaultCommitHandlers.NetworkAny - esperando una confirmación en cualquier par en el canal

Ni siquiera puede esperar ninguna confirmación, más sobre eso más adelante, pero primero preste atención a esto:

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

contract := network.GetContract("mycc")

Primero, obtenemos del canal un subconjunto de pares con los que interactuaremos, y luego un puntero a Contract, cuyos métodos nos permitirán interactuar con el chaincode.

Ahora tenemos la oportunidad de determinar si usar o no algún tipo de estrategia para esperar un compromiso. Primero, veamos una transacción con un commit esperando:

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


Aquí comenzamos la simulación de la transacción en el par, obtenemos la respuesta, enviamos la respuesta de la propuesta al ordenante, esperamos la validación y nos comprometemos de acuerdo con la estrategia anterior para esperar la confirmación. Comportamiento estándar y familiar. Nosotros miramos más allá.

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

En este caso, el cliente recibe una respuesta de propuesta y no hace nada más. No esperamos ningún compromiso . Esto debería usarse para leer el estado.

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 ofrece un poco más de control sobre la transacción, es decir, la capacidad de pasar opciones funcionales:

  • gateway.WithTransient (transitorio) : para enviar datos privados
  • gateway.WithEndorsingPeers ("peer0.org1.example.com") - para determinar objetivos manualmente


Intente llamar a app.go , sustituyendo varias claves, valores y opciones en métodos transaccionales para ver cómo funciona.

Esto concluye la revisión de la nueva API. Por cierto, es bastante fácil implementar su propia billetera, controladores de compromiso, identidad, por lo que puede agregar implementaciones estándar a las que cumplan sus objetivos u ofrecer sus propias ideas y código a la comunidad.

Gracias por la atención.

All Articles