reach-sh/reach-lang

Getting Error("no log for ".concat(o_lab)) when using remote call

lorenzopolidori opened this issue · 3 comments

Discussed in #1354

Originally posted by lorenzopolidori August 19, 2022
I have two Reach applications, one calling the other through an API.

The fist contract executes a parallelReduce, and after it stops it, it calls an API implemented in a second contract and terminates:

// ...
const SPP = {
    SolarPowerPlant_increaseCapacity: Fun([UInt], UInt),
    SolarPowerPlant_decreaseCapacity: Fun([UInt], UInt),
    SolarPowerPlant_increaseOutput: Fun([UInt], UInt),
};

// ...
const spp = remote(sppContractInfo, SPP);

// ... parallelReduce

if (withdrawn) {
    A.interact.log("The token has been withdrawn");
    const _ = spp.SolarPowerPlant_decreaseCapacity(power)
    commit();
    exit();
}

// ... other logic

The second contract is quite straightforward:

const SolarPowerPlant = Tuple(UInt, UInt);

export const main = Reach.App(() => {
    const A = Participant('Admin', {
        ...hasConsoleLogger,
        onReady: Fun(true, Null)
    });

    const V = API('SolarPowerPlant', {
        stop: Fun([], Bool),
        decreaseCapacity: Fun([UInt], UInt),
        // other functions
    });

    init();

    A.publish();

    A.interact.onReady(getContract());

    const [done, capacity, output] =
        parallelReduce([false, 0, 0])
            .invariant(balance() == 0)
            .while(!done)
            .api(V.decreaseCapacity,
                ((amount, k) => {
                    if (amount > capacity) {
                        k(0);
                        return [false, 0, output]
                    }
                    else {
                        const newCapacity = capacity - amount;
                        k(newCapacity);
                        return [false, newCapacity, output]
                    }
                }))
            .api(V.stop,
                (() => { assume(this == A); }),
                (() => 0),
                (k => {
                    const isAdmin = this == A;
                    require(isAdmin);
                    k(isAdmin);
                    return [true, capacity, output]
                }))
            // other functions
            .timeout(false);

    commit();
    exit();
});

The compiler does not give any errors, but when spp.SolarPowerPlant_decreaseCapacity(power) is executed, I get the following error message:

The token has been withdrawn
/stdlib/dist/cjs/ALGO.js:2463
                                            throw Error("no log for ".concat(o_lab));
                                                  ^

Error: no log for v786
    at /stdlib/dist/cjs/ALGO.js:2463:51
    at step (/stdlib/dist/cjs/ALGO.js:67:23)
    at Object.next (/stdlib/dist/cjs/ALGO.js:48:53)
    at /stdlib/dist/cjs/ALGO.js:42:71
    at new Promise (<anonymous>)
    at __awaiter (/stdlib/dist/cjs/ALGO.js:38:12)
    at Object.getOutput (/stdlib/dist/cjs/ALGO.js:2435:97)
    at Module.Admin (file:///app/build/index.main.mjs:444:29)
    at processTicksAndRejections (node:internal/process/task_queues:96:5)
    at async Promise.all (index 1)

If I remove the remote call, the error disappears.
It seems to be related to #1329

This error comes from this code block --- https://github.com/reach-sh/reach-lang/blob/master/js/stdlib/ts/ALGO.ts#L2067-L2082

And it roughly means that Reach couldn't find the result of the function call in the on-chain log. Can you run with debugging and show me the whole output (uploaded to gist.github.com)? It would also be useful to have an automated test case version of your code that I could run with reach run and try it out.

@jeapostrophe This is the gist with the debug logging: https://gist.github.com/lorenzopolidori/75e9e8a873a7d99c892fe8ea13a3e32b

You can find the full source code of the two contracts here: https://github.com/terragrids/dapp/tree/dev/blockchain

The automated test code that I ran to generate the debug logging is here https://github.com/terragrids/dapp/blob/dev/blockchain/token-market/index.mjs

token-market is the calling contract, solar-power-plant is the called contract.

To reproduce the issue:

  1. Compile the first contract here https://github.com/terragrids/dapp/tree/dev/blockchain/solar-power-plant
  2. Copy blockchain/solar-power-plant/build/index.main.mjs into ./blockchain/token-market/build
  3. Uncomment this line in the called contract https://github.com/terragrids/dapp/blob/dev/blockchain/token-market/index.rsh#L104
  4. Run only await testSellAndStop() at the end of the test file to reproduce the issue, rather than all 3 test cases.

I have just pushed a fix to this problem. Thank you for finding it. It will be released on Thursday.

If you want to work-around before then, then the problem is that you are calling a remote function in the continuation of while (i.e. parallelReduce) and I had a bad compilation. You can add an extra publish to get a new transaction... or just wait until Thursday :)