1
votes

Hyperledger fabric chaincode: fonction appelant une autre fonction depuis le chaincode?

J'ai un scénario dans lequel je dois appeler une autre fonction (par exemple, une requête) à partir d'une fonction de code de chaîne (par exemple, mise à jour). Le tissu hyperledger fournit-il une interface pour cela. Par exemple:

    let Chaincode = class {

    async Init(stub) {
        return shim.success();
    }

    async Invoke(stub) {

        let ret = stub.getFunctionAndParameters();

        console.info(ret);

        let method = this[ret.fcn];

        if (!method) {
            throw new Error('Received unknown function ' + ret.fcn + ' invocation');
        }
        try {
            let payload = await method(stub, ret.params);
            return shim.success(payload);
        } catch (err) {
            return shim.error(err);
        }
    }

    async init(stub, args) {

        if (args.length != 1) {
            throw new Error('Invalid args. Expects no args');
        }
    }

    async query(stub, args) {
        ...
    }

    async dummy(stub, args) {
        return Buffer.from('Hello');
    }


    async update(stub, args) {
    ...
        let resp = await dummy(); // gives error
        //let resp = await stub.invokeChaincode('cc2', ['dummy'] );  // working
        console.log(resp)
    ...
    }    
};
shim.start(new Chaincode());

J'ai essayé la réponse sur le message suivant mais cela n'a pas fonctionné. comment appeler la fonction de code de chaîne de lui-même pour enregistrer un sous transactions . Bien qu'en utilisant invokeChaincode (), je puisse appeler une fonction à partir d'un autre code de chaîne.

Merci d'avance.

Code de code de chaîne:

   ...
    async query(stub, args) {
    }
    async update(stub, args) {
      if(condition) {
        call query();
      }
    }
    ...


0 commentaires

4 Réponses :


0
votes

En guise d'approche alternative, j'installe et instancie le même chaincode avec deux noms disons cc1 et cc2 sur le même canal, disons ch1. Ensuite, j'utilise:

 invokeChaicode('cc2', ['function', 'arg1', arg2]);

du chaincode one (cc1).

Mais le problème est que je dois installer et instancier le même chaincode deux fois avec des noms différents sur le même canal.

Toutes autres informations sont les bienvenues.


5 commentaires

Pourquoi ne pas simplement appeler la deuxième fonction par son nom directement à partir de la première fonction?


OK va essayer ça. Je n'ai jamais pensé de cette façon. :) Parfois, nous manquons des scénarios plus simples.


J'ai déclaré une fonction factice comme: async dummy (stub, args) {return Buffer.from ('hello'); } et l'a appelé à partir d'une autre fonction (disons update) comme: async update (stub, args) {console.log (await dummy ()); } et a obtenu l'erreur suivante: Erreur: Erreur lors de la validation de l'appel: erreur rpc: code = Inconnu desc = erreur lors de l'exécution du code de chaîne: transaction retournée avec un échec: ReferenceError: factice n'est pas défini -


cela vous dérangerait-il de publier un plus grand échantillon de votre code de chaîne?


@GariSingh a ajouté le plus grand exemple de code à la question.



-1
votes

Parfois, nous devrions penser que c'est plus simple. Eh bien, la réponse est: appelez-le directement. Par exemple: nous avons deux fonctions A et B

func (s *SmartContract) B(APIstub shim.ChaincodeStubInterface, args []string) sc.Response {

 s.A(APIstub,args)

}
func (s *SmartContract) B(APIstub shim.ChaincodeStubInterface, args []string) sc.Response {}

si nous voulons appeler la fonction A dans la fonction B, faites-le simplement comme

func (s *SmartContract) A(APIstub shim.ChaincodeStubInterface, args []string) sc.Response {}


1 commentaires

Le chaincode d'OP est écrit en javascript. Il serait préférable d'afficher une solution pour la même chose.



1
votes

MISE À JOUR: Comme indiqué par @ kartik-chauhan dans sa réponse , cette approche est utile si vous utilisez fabric-contract-api . Suivez sa réponse si vous utilisez fabric-shim .

Peut-être un peu tard pour OP mais pour toute personne intéressée, vous pouvez appeler une autre fonction à partir d'une fonction du même code de chaîne en utilisant ceci . .

Nous avons utilisé la IBM Blockchain Platform extension pour VSCode et il a une sorte d'assistant pour générer un chaincode en GO, javascript et dactylographié. Ce qui suit est un extrait du chaincode généré pour javascript où vous pouvez observer comment la fonction myAssetExists est appelée à partir de la fonction createMyAsset via this.myAssetExists:

const { Contract } = require('fabric-contract-api');

class MyAssetContract extends Contract {

    async myAssetExists(ctx, myAssetId) {
        const buffer = await ctx.stub.getState(myAssetId);
        return (!!buffer && buffer.length > 0);
    }

    async createMyAsset(ctx, myAssetId, value) {
        const exists = await this.myAssetExists(ctx, myAssetId);
        if (exists) {
            throw new Error(`The my asset ${myAssetId} already exists`);
        }
        const asset = { value };
        const buffer = Buffer.from(JSON.stringify(asset));
        await ctx.stub.putState(myAssetId, buffer);
    }
...

p >


0 commentaires

0
votes

La réponse de @ jama à la question est correcte. Cependant, il est spécifique à fabric-contract-api . Les personnes qui utilisent le package fabric-shim peuvent implémenter la même chose en passant this dans la méthode qui doit être appelée. par exemple

async getMarblesByRange(stub, args, thisClass) {
    if (args.length < 2) {
      throw new Error('Incorrect number of arguments. Expecting 2');
    }

    let startKey = args[0];
    let endKey = args[1];

    let resultsIterator = await stub.getStateByRange(startKey, endKey);
    let method = thisClass['getAllResults'];
    let results = await method(resultsIterator, false);

    return Buffer.from(JSON.stringify(results));
}

async getAllResults(iterator, isHistory) {
...
}

Il suffit de passer this dans la await method () pour fournir le contexte de la classe actuelle à la méthode invoquée.

La méthode qui doit appeler une autre méthode de l'intérieur doit accepter this comme l'un des arguments, par exemple

async Invoke(stub) {
    console.info('Transaction ID: ' + stub.getTxID());
    console.info(util.format('Args: %j', stub.getArgs()));

    let ret = stub.getFunctionAndParameters();
    console.info(ret);

    let method = this[ret.fcn];
    if (!method) {
        console.log('no function of name:' + ret.fcn + ' found');
        throw new Error('Received unknown function ' + ret.fcn + ' invocation');
    }

    try {
        let payload = await method(stub, ret.params, this);
        return shim.success(payload);
    } catch (err) {
        console.log(err);
        return shim.error(err);
    }
}

Dans l'extrait de code ci-dessus, thisClass est passé en argument dans la méthode getMarblesByRange , à l'aide de laquelle la méthode appelle une autre méthode getAllResults () .

La méthode peut être appelée soit en utilisant thisClass ['getAllResults'] ou simplement thisClass.getAllResults.

Tout le code- des extraits ont été extraits de marbre chaincode a >.


0 commentaires