input-output-hk / plutus-apps

The Plutus application platform

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Variable Var n is not bound

locallycompact opened this issue · comments

Summary

Hi, this occurs sporadically. I can run thousands of model checks in succession and not experience this, but sometimes I will experience this error:

  Standard Model Check:  FAIL (43.28s)
    *** Failed! (after 45 tests and 10 shrinks):
    Exception:
      Variable Var 14 is not bound!
      CallStack (from HasCallStack):
        error, called at src/Test/QuickCheck/StateModel.hs:75:18 in quickcheck-dynamic-0.1.0.0-KyLL9UuOfU2
5O9KQ5A71yO:Test.QuickCheck.StateModel
    Actions
     [tok3 := SetupTokens,
      tok8 := MintIdents (Wallet 1) ["plazlemff",""],
      Init (Wallet 1) (SymInstanceParams {ident = tok14.hk, assets = [tok3.A,tok3.C]})]

Steps to reproduce the behavior

Unable to share code for this, but I will try and make a reproduction when I can.

Actual Result

Error

Expected Result

No error

Describe the approach you would take to fix this

No response

System info

NixOS

As you can see from the error message you're trying to use a symbolic token that doesn't exist - you have SymInstanceParams {ident = tok14.hk, ...} but there is no tok14 in the list of actions. This is because your precondition for your actions is missing a check to make sure that the tokens that are in your actions after shrinking actually exist. Unfortunately you have to code this check up yourself as there is currently no generic programming support for this - we are working on a fix for that. For reference, see the Uniswap example.

Thank you for explaining I'll try this.

To be specific check out the following line:

&& t1 `elem` s ^. contractState . exchangeableTokens

Here we check that the tokens we trying to set up a swap for actually exist in the set of tokens we've created for this test. When running normal tests this is "obviously true" - we don't generate symbolic tokens that haven't been created by createToken. However, because a symbolic token is just a pair of basically an action number and a specific identifier within the action (an action can create more than one token) this check still needs to be there for shrinking to work properly. Specifically, your original counterexample may be something like Actions [tok1 := SetupTokens, UseToken tok1.A, <do something else>] and shrinking will try to remove individual actions, so you get Actions [UseToken tok1.A, <do something else>]. Here tok1 is basically a pointer to a token that is created non-existen action (what was originally SetupTokens) and so this test is meaningless. To avoid this problem we need checks like the one I linked above to make sure that tok1.A is actually meaningful in this particular trace.

Now, in the future it would be very nice to be able to automate these checks and make sure that no actions are present that contain references to unbound tokens. One way to do this is to pose some SYB-like constraints on Action model to require it to give you all symbolic tokens in an action so that we can check this behind the scenes. I'll bump this to the top of my bugfixing prio list.

Heads up @locallycompact a feature that makes this more ergonomic has just been merged to main. I think you should be able to get rid of some of your wellformedness checks here now!

This is wonderful I'll try this now. Thank you.

I can't actually locate that plutus commit you used 4127e9cd6e889824d724c30eae55033cb50cbf3e

If I use plutus latest then I get

Preprocessing library for cardano-ledger-alonzo-0.1.0.0..
Building library for cardano-ledger-alonzo-0.1.0.0..
[ 1 of 20] Compiling Cardano.Ledger.Alonzo.Language ( src/Cardano/Ledger/Alonzo/Language.hs, dist/build/Cardano/Ledger/Alonzo/Language.o, dist/build/Cardano/Ledger/Alonzo/Language.dyn_o )
[ 2 of 20] Compiling Cardano.Ledger.Alonzo.Scripts ( src/Cardano/Ledger/Alonzo/Scripts.hs, dist/build/Cardano/Ledger/Alonzo/Scripts.o, dist/build/Cardano/Ledger/Alonzo/Scripts.dyn_o )

src/Cardano/Ledger/Alonzo/Scripts.hs:198:6: error:
    Not in scope: ‘PV1.validateCostModelParams’
    Module ‘Plutus.V1.Ledger.Api’ does not export ‘validateCostModelParams’.
    |
198 |   if PV1.validateCostModelParams cm
    |      ^^^^^^^^^^^^^^^^^^^^^^^^^^^

src/Cardano/Ledger/Alonzo/Scripts.hs:202:6: error:
    Not in scope: ‘PV2.validateCostModelParams’
    Module ‘Plutus.V2.Ledger.Api’ does not export ‘validateCostModelParams’.
    |
202 |   if PV2.validateCostModelParams cm
    |      ^^^^^^^^^^^^^^^^^^^^^^^^^^^

src/Cardano/Ledger/Alonzo/Scripts.hs:220:19: error:
    Not in scope: ‘PV1.defaultCostModelParams’
    Module ‘Plutus.V1.Ledger.Api’ does not export ‘defaultCostModelParams’.
    |
220 |       PlutusV1 -> PV1.defaultCostModelParams
    |                   ^^^^^^^^^^^^^^^^^^^^^^^^^^

src/Cardano/Ledger/Alonzo/Scripts.hs:221:19: error:
    Not in scope: ‘PV2.defaultCostModelParams’
    Module ‘Plutus.V2.Ledger.Api’ does not export ‘defaultCostModelParams’.
    |
221 |       PlutusV2 -> PV2.defaultCostModelParams
    |                   ^^^^^^^^^^^^^^^^^^^^^^^^^^
``

You have to use release/node-1.34 - that's the branch of plutus that plutus-apps depends on. What are you using to organize your dependencies?

Ping @sjoerdvisscher as I don't quite understand how this is organized in separate projects.

I'm using a haskell.nix stack.yaml conversion. This works now:

https://gitlab.homotopic.tech/plutus/contracts/nft/-/blob/master/stack.yaml

Actually, no it doesn't. I'm getting this on models that previously worked.

    Exception while generating shrink-list:
      QuickCheck.elements used with empty list

This was after adding a Data instance to SymValue, which I needed to compile the model. Not sure if that's relevant. I'll try and put together some open source examples.

I'm not experiencing model failures before I switch to the new version and I get this one now with the new version. I'll try and dig in.

Ok, I think I know the reason. Previously the precondition was being evaluated against the ModelState eagerly first before constructing the Action lazily later, so the precondition was firing before the call to elements, so I did have a bug, which was incidentally hidden by a bug previously in plutus-apps.