GithubHelp home page GithubHelp logo

mlabs-haskell / plutus-simple-model Goto Github PK

View Code? Open in Web Editor NEW
31.0 32.0 17.0 1.9 MB

Unit testing with resource estimation for Plutus

License: BSD 3-Clause "New" or "Revised" License

Makefile 2.10% Nix 0.73% Haskell 97.17%

plutus-simple-model's Introduction

Plutus simple model

Unit test library for Plutus with estimation of resource usage.

Library defines simple mock model of Blockchain to unit test plutus contracts and estimate usage of resources. What are the benefits for this framework comparing to other test frameworks for Plutus? It's:

  • easy to use
  • easy to think about
  • it has minimal dependency set. It depends only on plutus and cardano-ledger. Ain't no plutus-apps or cardano-node or ouroboros
  • works for both Plutus V1 and Plutus V2
  • support for Alonzo and Babbage eras
  • blazing fast
  • can estimate usage of resources with real functions used on Cardano node.
  • pure
  • good for unit testing of on-chain code
  • being fast and pure it's also suitable for property based testing

Quick start guide

See user guide to get started

How to compile the library

Library is compiled with nix, flakes and cabal. Enter developer nix shell with:

nix develop

Inside the nix shell we can run build and tests over make:

make build
make test

It calls cabal under the hood.

How to update docs

Docs are written in mdbook and reside in the docs directory. They are auto-deployed with Git actions on push to main. To run docs locally use mdbook:

cd docs
mdbook serve

plutus-simple-model's People

Contributors

anton-k avatar arifordsham avatar blamario avatar danielfarrelly avatar euonymos avatar geometer1729 avatar l-as avatar marcinbugaj avatar sourabhxyz avatar t4ccer avatar willbasky avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

plutus-simple-model's Issues

More detailed error messages

It would be great if errors would have more detailed logs.

For example: Transaction outputs should not contain zero Ada.
The log is easy to understand but harder to debug.
Helpful would be in this case for example to have wallet address/script address where this happened.

Functions for cardano-simple

  • Move evalScript from TestSingleScript to cardano-simple
  • Implement new functions in cs:
    • utxoForTransaction :: 
        Map P.ScriptHash (C.Versioned P.Script) -> 
        Network ->
        Tx era -> 
        Either ToCardanoError (Ledger.UTxO era)
      
    • txBalance :: 
        PParams era -> 
        Map P.ScriptHash (C.Versioned P.Script) ->
        Network ->
        Tx era ->
        Ledger.Value era
      
    • evaluateScriptsInTx ::
        PParams era ->
        Map P.ScriptHash (C.Versioned P.Script) ->
        Network ->
        Tx era ->
        Either (TranslationError (Crypto era)) Alonzo.ExUnits
      

In an appropriate new or existing cs module.

Modify getUtxo, checkBalance and checkUnits in Plutus.Model.Mock to use them.

While you're at it, rename checkUnits to make it clear it is actually executing the scripts and validating the transaction.

Allow untyped scripts and data

Currently, we have an implementation of typed scripts that is embedded in the PSM API. This disallows testing with untypesafe data - essentially assuming that PlutusTx library is doing its job correctly. We should enable testing with untyped data.

Ideally the way to do this is to add untyped types and use them exclusively in the core API, adding typing in a layer on top.

Fix config for V2

The Babbage config provided sets the protocol version to V1, which since a recent ledger upgrade won't support V2 scripts.

Fix plan:

Major version bump (second component, x.X.x.x) and changelog.

Factor Cardano layer into separate package

psm has its own lightweight wrapper layer of Cardano functions, kept in the Fork.* hierarchy. These are considered internal modules and not exposed.

The problem is that hedgehog-plutus-simple (and potentially other packages) need many of these functions. The current solution, maintaining a branch of psm where these are exposed, is not satisfactory in the long term.

The proposed solution is to move these modules into a separate package, that both psm and hps can depend on.

  • Create a new repository, maybe cardano-simple, based on mlabs-tooling.
  • Move the Fork hierarchy to this repo. Probably remove the Fork prefix and add a suffix such as Simple to to each non-novel module
  • Switch psm to new dependency
  • Switch hps to the new dependency.

When this is done, it may be interesting to see what functionality that hps has duplicated from psm can be removed by exposing more functions from the new Cardano layer, or possibly even moving useful functionality from psm proper to the new layer.

The overarching goal is to move towards a tidier design on all three modules.

Cannot compile cabal after upgrading to Plutus V2

I get the following error when trying to run cabal build:
immagine

My cabal.project tries to include Plutus Simple Model as follows:
immagine

I'm not sure how I can solve this, it's the latest commit of master branch.

`spend` fails without descriptive error

Plutus.Model.Contract.spend fails with:

Exception: Maybe.fromJust: Nothing
CallStack (from HasCallStack):
  error, called at libraries/base/Data/Maybe.hs:149:21 in base:Data.Maybe
  fromJust, called at src/Plutus/Model/Contract.hs:276:10 in plutus-simple-model-0.5.2.0-4fEbkvuS1hh58koi6xqmzV:Plutus.Model.Contract

It forces user to dive into PSM source code to figure out the reason of the error, which is not the best user experience.

Proposed solution

Make a descriptive error message.
Maybe even take optional error message as a function parameter.

`spend'` fails to spend users' funds is some cases

The reason is that strangely enough, lt from Plutus.V1.Ledger.Value can't seem to be correct for all inputs. For example, it doesn't consider a<b if

b (curVal)=Value (
Map [
(5c0ce33a2223eea4d068af7ee5d8972627ce212f44608709c1922107,
Map [
(0x2cb30e42f0336c7644965a977f7e560dc72bac3da94daedf7fd8cc3e24971523,1)
(0x35c6de58fa135aff6c159c5d05330a44206c235f428afa5649720cd805f03d59,1),
(0x567f4ca57846c3226ce5db4504f6d0200d3794efc9809a0fb99dd0e59b6bd808,1),
(0x6673ae665b6ba82c86619ae6ff419d0216db75f2a40bb747271d4af3871c576d,1),
(0x7b6c94cb7a029647f524ac4839599a8fd2c31ef762354d531d0ef6a63336c621,1),
(0x83baee89200833482a9d52bacb603f32e1d1f1dc354c8027cfc0a9932ff6259a,1),
(0xadc9cbfc8448341351192aded5ca67141244034fd60c75281f6225545266d8df,1),
(0xcaae7a64bfc5052e0d52d08add1316731aad69ea665e97aafa1a630a2198b298,1),
(0xe113351fbff67ec6c32d2b7906d49732a06de0144999c6efa4a2e4bda4433948,1)
])
])

and

a (nextVal)=Value (
Map [
(5c0ce33a2223eea4d068af7ee5d8972627ce212f44608709c1922107,
Map [
(0x35c6de58fa135aff6c159c5d05330a44206c235f428afa5649720cd805f03d59,1),
(0x7b6c94cb7a029647f524ac4839599a8fd2c31ef762354d531d0ef6a63336c621,1),
(0xcaae7a64bfc5052e0d52d08add1316731aad69ea665e97aafa1a630a2198b298,1)
])
])  

I am not going to figure out what's wrong with lt right now, though it's worthwhile on its own. Probably it just have different semantics. Instead I am offering a workaround to make things working right now.

[BUG - found cause] zero ada error mistakenly raised

I've posted #15 issue some time ago and when I was digging deeper into the actual problem I've found out that there is probably a bug somewhere and created the minimal reproducible example.

The following code fails the test with the zero ada error even when there should be no such error.

I found out that this happens when I changed this package in the project from commit 64f37881c3c6a1ece104413e95b6a272d22dbfaa to 2077162655a62f9b6404e153eed3ef56c65cad67

EDIT:
The error occurs with both of the commits, so the bug is implemented somewhere further in the past.
Modifying this line:

void $ sendValue admin (Ada.toValue minAdaTxOut <> Value.assetClassValue (fakeCoin (FakeCoin "SMTH")) 10_000_000) user

to this:

void $ sendValue admin (Ada.toValue minAdaTxOut <> Ada.toValue minAdaTxOut  <> Value.assetClassValue (fakeCoin (FakeCoin "SMTH")) 10_000_000) user

solves the error.

However, it should work either way in my opinion.

Buggy code
{-# LANGUAGE NumericUnderscores #-}
{-# LANGUAGE OverloadedStrings #-}

module Spec.MyTest where

import Control.Monad
import Ledger
import qualified Ledger.Value as Value
import Plutus.Test.Model
import qualified Plutus.V1.Ledger.Ada as Ada
import Test.Tasty
import Utils.Helpers (checkBool)

main :: IO ()
main = do
  cfg <- readDefaultBchConfig
  defaultMain $
    testGroup
      "benchmark test suite"
      [ tests cfg
      ]

tests :: BchConfig -> TestTree
tests cfg =
  testGroup
    "Foo"
    [ check True "foo" foo'
    ]
  where
    tokens = Value.assetClassValue (fakeCoin (FakeCoin "SMTH")) 10_000_000

    check :: Bool -> String -> Run Bool -> TestTree
    check = checkBool cfg (Ada.adaValueOf 100_000_000 <> tokens)

    foo' = do
      user <- newUser mempty
      admin <- getMainUser
      void $ sendValue admin (Ada.toValue minAdaTxOut <> Value.assetClassValue (fakeCoin (FakeCoin "SMTH")) 10_000_000) user
      foo user

foo :: PubKeyHash -> Run Bool
foo user = do
  admin <- getMainUser
  let spendVal = Ada.toValue minAdaTxOut
  sp <- sendValue admin spendVal user >> spend user spendVal
  void $ Plutus.Test.Model.signTx user (userSpend sp <> payToPubKey admin spendVal) >>= sendTx
  noErrors

`spendScript[Ref]` datum parameter purpose?

What's the purpose of the Datum parameter since the actually used datum that is sent to validator is the actual one that is attached to the UTXO?

I.e. when I have a UTXO at the script address with datum "BUM" and use the on this UTXO:

spendScript script oref () "Hello"

Then when I send the transaction, the datum that arrives to the validator is the "BUM" datum instead of the "Hello" datum.

Maybe the Datum parameter could be removed to prevent confusion?

Confusing constructor of Ada type

Ada's constructor is Lovelace.
It is expected one find inside of the constructor Lovelace lovelaces, but there are adas as the usage in all tests shows. However it wrapped to Lovelace without any conversion. Why?
To get Lovelace there is a function adaToLovelace which is not type safe.

If I didn't miss anything why it made that way, let rename Lovelace constructor to Ada at least. (1)
Or keep Constructor as it is, but not export getLovelace and expose extra function mkAda and fromAda to construct Ada type and get its values. Well mkAda == asAda which is not used. (2)

In case of (2) the function

adaValue :: Integer -> Value
adaValue = ada . Lovelace

could be refactored

adaValue :: Integer -> Value
adaValue = ada . asAda

Utilities for Plutarch scripts

Implement functions in Plutus.Model.Validator.Vx for Plutarch.

  • From the appropriate Plutarch type to TypedValidator
  • For validators, minting policies and staking validators
  • For V1 and V2

Remember to add a CHANGELOG entry and bump the minor version number (C in A.B.C.D).

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.