1

我有一个场景,我需要从链码函数(比如更新)调用其他一些(比如查询)函数。超级账本结构是否为此提供任何接口。例如:

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

我已经尝试了以下帖子的答案,但没有奏效。 如何从自身调用链码函数来记录子交易。虽然通过使用 invokeChaincode() 我可以从另一个链码调用函数。

提前致谢。

链码代码:

    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());
4

4 回答 4

1

更新:正如@kartik-chauhan 在他的回答中指出的那样,如果您使用fabric-contract-api. 如果您正在使用,请按照他的回答fabric-shim

对于 OP 来说可能有点晚了,但对于其他感兴趣的人,您可以使用this.<another_function>.

我们一直在为 VSCode 使用IBM Blockchain Platform 扩展,它有一种向导可以在 GO、javascript 和 typescript 中生成链码。以下是为 javascript 生成的链码的摘录,您可以在其中观察函数 myAssetExists 是如何从函数 createMyAsset 调用的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);
    }
...
于 2020-03-11T15:23:55.933 回答
0

作为一种替代方法,我正在安装和实例化具有两个名称的相同链代码,例如 cc1 和 cc2 在同一通道上,例如 ch1。然后我正在使用:

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

来自链码一(cc1)。

但问题是我需要在同一通道上安装和实例化相同的链码两次,但名称不同。

欢迎任何其他见解。

于 2019-01-03T09:13:53.097 回答
0

@jama 对这个问题的回答是正确的。但是,它是特定于fabric-contract-api. 对于使用fabric-shim包的人,可以通过传入this要调用的方法来实现相同的功能。例如

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);
    }
}

只需传入即可thisawait method()当前类的上下文提供给被调用的方法。

必须从内部调用另一个方法的方法必须接受this作为参数之一,例如

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) {
...
}

在上面的代码片段中,thisClass作为方法中的参数传递,getMarblesByRange方法使用该参数调用另一个方法getAllResults()

可以使用thisClass['getAllResults']或简单地调用该方法thisClass.getAllResults

所有代码片段均取自大理石链代码

于 2020-07-29T21:35:19.790 回答
-1

有时候我们应该认为它更简单。好吧,答案是:直接调用它。例如:我们有两个函数 A 和 B

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

如果我们想在函数 B 中调用函数 A,只需这样做

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

 s.A(APIstub,args)

}
于 2019-03-19T15:15:35.303 回答