Nova malha do Hyperledger: modelo de software SDK Go



Em um artigo anterior, falamos sobre o novo modelo de programação do código de código no Hyperledger Fabric. Embora o lançamento do novo Go SDK ainda não tenha ocorrido, nada nos impede de ver o que nos espera no futuro e até testá-lo em um conjunto de teste. Nem tudo ainda está implementado (como manipuladores de confirmação ), mas o design planejado do modelo de software já está claro, então vamos dar uma olhada mais de perto.

Neste repositório, modifiquei levemente a grade de amostra para começar com o código da cadeia que vimos no artigo anterior e adicionei um cliente simples escrito usando a nova API. O repositório possui instruções simples para iniciar e configurar a rede.

Como você pode ver em go.mod , para usar a nova API, não temos um release (ainda não existe), mas todas as alterações em um commit específico (esta é uma medida temporária antes do lançamento do release): Em nosso aplicativo, importamos o pacote de gateway no app.go. A essência da nova API fornecendo abstrações comuns para todos os SDKs (go, node, java) e reduzindo o padrão transferido pelo desenvolvedor de um projeto para outro. Uma dessas abstrações é a Wallet.

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



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

. A inicialização da carteira é assim:

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 é uma implementação da 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
}

Como você pode ver, essa interface descreve as operações básicas com o repositório de identidade do usuário. Além do sistema de arquivos, a identidade pode ser armazenada na memória, basta usar outra fábrica embutida - NewInMemoryWallet () .

Conecte-se à rede:

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 () retorna um ponteiro para Gateway , um objeto que fornece conectividade de rede. gateway.WithCommitHandler - uma opção funcional para definir uma estratégia para aguardar eventos de confirmação. Até o momento, nenhuma estratégia foi implementada (o que significa que a estratégia padrão do "antigo" SDK "aguardar confirmações de todos os endossantes" será usada ), mas o seguinte é planejado:

  • gateway.DefaultCommitHandlers.OrgAll - aguarde uma confirmação em todos os pares da organização (por padrão)
  • gateway.DefaultCommitHandlers.OrgAny - aguardando uma confirmação em qualquer ponto da organização
  • gateway.DefaultCommitHandlers.NetworkAll - aguardando uma confirmação em todos os pares de todas as organizações no canal
  • gateway.DefaultCommitHandlers.NetworkAny - aguardando uma confirmação em qualquer ponto no canal

Você não pode nem esperar por quaisquer confirmações, mais sobre isso mais tarde, mas primeiro preste atenção a isso:

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

contract := network.GetContract("mycc")

Primeiro, obtemos do canal um subconjunto de pares com os quais interagiremos e, em seguida, um ponteiro para Contrato, cujos métodos nos permitirão interagir com o código de código.

Agora temos a oportunidade de determinar se deve ou não usar algum tipo de estratégia para aguardar uma confirmação. Primeiro, vejamos uma transação com uma confirmação em espera:

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


Aqui, iniciamos a simulação da transação no mesmo nível, obtemos a resposta, enviamos a resposta da proposta ao solicitante, aguardamos a validação e confirmamos de acordo com a estratégia acima para aguardar a confirmação. Comportamento padrão e familiar. Nós olhamos mais longe.

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

Nesse caso, o cliente recebe uma resposta da proposta e não faz mais nada. Não esperamos nenhum commit . Isso deve ser usado para ler o 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 oferece um pouco mais de controle sobre a transação, ou seja, a capacidade de passar opções funcionais:

  • gateway.WithTransient (transient) - para enviar dados privados
  • gateway.WithEndorsingPeers ("peer0.org1.example.com") - para determinar destinos manualmente


Tente chamar app.go , substituindo várias chaves, valores e opções em métodos transacionais para ver como isso funciona.

Isso conclui a revisão da nova API. A propósito, é muito fácil implementar sua própria carteira, manipular commit, identidade, para que você possa adicionar implementações padrão àquelas que atendem às suas metas ou oferecer suas próprias idéias e códigos à comunidade.

Obrigado pela atenção.

All Articles