3
votes

Hyperledger Fabric: vérifiez si la transaction a été validée dans le grand livre

J'ai trois applications clientes qui utilisent respectivement les SDK Java, Node.js et Go pour interagir avec ma blockchain Fabric. En les utilisant, je peux interroger et mettre à jour le grand livre avec succès.

Maintenant, je veux mesurer la latence lors de la mise à jour du livre. Donc, je pensais le faire en prenant un horodatage avant la soumission de la demande et un autre après que la transaction ait été validée avec succès dans le grand livre, puis calculer la différence.

Mon problème est que je ne trouve aucune documentation complète sur l'API du SDK pour Java, Go et Node.js, donc je ne sais pas si, lorsque la méthode de soumission revient, je peux considérer la transaction comme correctement validée dans le grand livre.

Voici le code de mes trois clients. Java:

response, err := client.Execute(channel.Request{ChaincodeID: ccID, Fcn: "mymethod", Args: [][]byte{[]byte("a1")}}, channel.WithRetry(retry.DefaultChannelOpts))

Node.js:

const result = await contract.submitTransaction('mymethod', 'a1');

Aller:

channel.sendTransaction(res)

Ces codes fonctionnent. Mon problème est le suivant: puis-je être sûr qu'après les lignes

sdk, err := fabsdk.New(config.FromFile(configFile))
if err != nil {
    fmt.Printf("failed to create SDK: %v\n", err)
    return
}
fmt.Println("SDK created")

// Prepare channel client context using client context
clientChannelContext := sdk.ChannelContext(channelID, fabsdk.WithUser(userName), fabsdk.WithOrg(orgName))
// ChannelClient is used to query and execute transactions
client, err := channel.New(clientChannelContext)
if err != nil {
    fmt.Printf("failed to create new channel client: %v\n", err)
    return
}
fmt.Println("channel client created")

response, err := client.Execute(channel.Request{ChaincodeID: ccID, Fcn: "mymethod", Args: [][]byte{[]byte("a1")}}, channel.WithRetry(retry.DefaultChannelOpts))
if err != nil {
    fmt.Printf("failed to execute the invoke function: %v\n", err)
} else {
    fmt.Println("Proposal responses: ")
    for _, element := range response.Responses {
        fmt.Printf("Endorser: %s Status: %d ChaincodeStatus: %d\n", element.Endorser, element.Status, element.ChaincodeStatus)
    }
    fmt.Println("chaincode transaction completed: " + string(response.Payload))
}
// Close SDK
sdk.Close()

(en Java)

const gateway = new Gateway();
await gateway.connect(ccp, { wallet: wallet, identity: userName, discovery: { enabled: false } });

// Get the network (channel) our contract is deployed to.
const network = await gateway.getNetwork('mychannel');

// Get the contract from the network.
const contract = network.getContract('mychaincode');

const result = await contract.submitTransaction('mymethod', 'a1');

(dans Node. js)

NetworkConfig ccp = NetworkConfig.fromJsonFile(networkConfigPath.toFile());
// initialize default cryptosuite and setup the client
CryptoSuite cryptoSuite = CryptoSuite.Factory.getCryptoSuite();
HFClient client = HFClient.createNewInstance();
client.setCryptoSuite(cryptoSuite);

Channel channel = client.loadChannelFromConfig(ccp.getChannelNames().iterator().next(), ccp);
channel.initialize();

TransactionProposalRequest transactionProposal = client.newTransactionProposalRequest();
// build chaincode id providing the chaincode name
ChaincodeID mychaincodeID = ChaincodeID.newBuilder().setName("mychaincode").build();
transactionProposal.setChaincodeID(mychaincodeID);
// calling chaincode function
transactionProposal.setFcn("mymethod");
transactionProposal.setArgs("a1");

Collection<ProposalResponse> res = channel.sendTransactionProposal(transactionProposal);
channel.sendTransaction(res);

(dans Go) la transaction a été validée dans le grand livre?

Je n'ai trouvé cela que sur la documentation:

"Soumettez une transaction dans le grand livre. Le nom de la fonction de transaction sera évalué sur les pairs endosseurs puis soumis au service de commande pour validation dans le grand livre. " pour submitTransaction dans Node.js à https : //fabric-sdk-node.github.io/release-1.4/module-fabric-network.Contract.html#submitTransaction__anchor

et

"Exécuter prépare et exécute la transaction à l'aide des options de requête et de requête facultatives "pour Exécuter in Go à https://godoc.org/github.com/hyperledger/fabric-sdk-go/pkg/client/channel#Client.Execute

Pour Java I ne trouve pas de documentation ... et je ne suis pas sûr non plus de Node.js et Go.


0 commentaires

3 Réponses :


1
votes

Je pense que j'ai résolu. Dans chaque application cliente, j'ai essayé d'ajouter une requête au grand livre la ligne après la demande. Le résultat de ce test est que la version Node.js et Go fonctionne bien: après

NetworkConfig ccp = NetworkConfig.fromJsonFile(networkConfigPath.toFile());
// initialize default cryptosuite and setup the client
CryptoSuite cryptoSuite = CryptoSuite.Factory.getCryptoSuite();
HFClient client = HFClient.createNewInstance();
client.setCryptoSuite(cryptoSuite);

Channel channel = client.loadChannelFromConfig(ccp.getChannelNames().iterator().next(), ccp);
channel.initialize();

TransactionProposalRequest transactionProposal = client.newTransactionProposalRequest();
// build chaincode id providing the chaincode name
ChaincodeID mychaincodeID = ChaincodeID.newBuilder().setName("mychaincode").build();
transactionProposal.setChaincodeID(mychaincodeID);
// calling chaincode function
transactionProposal.setFcn("mymethod");
transactionProposal.setArgs("a1");

Collection<ProposalResponse> res = channel.sendTransactionProposal(transactionProposal);
CompletableFuture<TransactionEvent> cf = channel.sendTransaction(res);
TransactionEvent te = cf.get();

logger.info("Status: " + te.isValid());
logger.info("Committed the transaction with transactionID + " + te.getTransactionID());

et

response, err := client.Execute(channel.Request{ChaincodeID: ccID, Fcn: "mymethod", Args: [][]byte{[]byte("a1")}}, channel.WithRetry(retry.DefaultChannelOpts))

le résultat de la requête est correct , J'obtiens la nouvelle valeur correcte. Cela signifie donc que le registre est correctement mis à jour après l'exécution de la méthode.

Pour la version Java, j'ai résolu de cette manière:

const result = await contract.submitTransaction('mymethod', 'a1');

utile. Bien sûr, si quelqu'un a des commentaires, ils sont bien acceptés.


0 commentaires

2
votes

Encore une réponse pour aider ceux qui voudront peut-être cette fonctionnalité de la CLI.

Par défaut, la CLI renvoie le succès lorsque la commande reçoit la transaction.

Pour attendre la validation sur peer chaincode invoke commnad, ajoutez le drapeau --waitForEvent

De cette façon, le cli attendra les événements de commit des pairs.

J'espère que cela vous aidera.


1 commentaires

Absolument utile! Je vous remercie!



1
votes

Je pense que la meilleure façon d'effectuer cela est d'utiliser Fabric EventHub, de cette façon vous enregistrez un auditeur et recevez un événement lorsqu'il est validé. L'utilisation de requêtes peut vous conduire à traiter des résultats incohérents et à effectuer de nouvelles tentatives pour les transactions retardées.

L'extrait de code ci-dessous peut être utilisé avec NodeSDK et je pense qu'il sera utile, d'autres exemples et documentation peuvent être trouvés ici: https://fabric-sdk-node.github.io/release -1.4 / tutoriel-écoute-événements.html

var options = {
    wallet_path: path.join(__dirname, './creds'),
    user_id: 'PeerAdmin',
    channel_id: 'mychannel',
    chaincode_id: 'fabcar',
    peer_url: 'grpc://localhost:7051',
    event_url: 'grpc://localhost:7053',
    orderer_url: 'grpc://localhost:7050'
};



    let eh = client.newEventHub();
    eh.setPeerAddr(options.event_url);
    eh.connect();


    let txPromise = new Promise((resolve, reject) => {
        let handle = setTimeout(() => {
            eh.disconnect();
            reject();
        }, 30000);

        eh.registerTxEvent(transactionID, (tx, code) => {
            clearTimeout(handle);
            eh.unregisterTxEvent(transactionID);
            eh.disconnect();

            if (code !== 'VALID') {
                console.error(
                    'The transaction was invalid, code = ' + code);
                reject();
            } else {
                console.log(
                    'The transaction has been committed on peer ' +
                    eh._ep._endpoint.addr);
                resolve();
            }
        });
    });
    eventPromises.push(txPromise);


0 commentaires