diff --git a/.github/workflows/integrate.yaml b/.github/workflows/integrate.yaml deleted file mode 100644 index bea599ec..00000000 --- a/.github/workflows/integrate.yaml +++ /dev/null @@ -1,78 +0,0 @@ -on: - push: - paths: - - ".github/workflows/integrate.yaml" - - "**.hs" - - "**.nix" - - "flake.lock" - - "agora.cabal" - branches: - - main - - staging - pull_request: - paths: - - ".github/workflows/integrate.yaml" - - "**.hs" - - "**.nix" - - "flake.lock" - - "agora.cabal" -jobs: - flake: - runs-on: ubuntu-latest - strategy: - matrix: - tasks: - - agora - - formatCheck - - benchCheck - - agora-test - steps: - - uses: actions/checkout@v2.4.0 - - - uses: cachix/install-nix-action@v16 - name: Set up Nix and IOHK caches - with: - nix_path: nixpkgs=channel:nixos-unstable - extra_nix_config: | - trusted-public-keys = hydra.iohk.io:f/Ea+s+dFdN+3Y/G+FDgSq+a5NEWhJGzdjvKNGv0/EQ= iohk.cachix.org-1:DpRUyj7h7V830dp/i6Nti+NEO2/nhblbov/8MW7Rqoo= cache.nixos.org-1:6NCHdD59X431o0gWypbMrAURkbJ16ZPMQFGspcDShjY= - substituters = https://hydra.iohk.io https://iohk.cachix.org https://cache.nixos.org/ - experimental-features = nix-command flakes - - - uses: cachix/cachix-action@v10 - with: - name: mlabs - authToken: ${{ secrets.CACHIX_KEY }} - - - run: nix build .#checks.x86_64-linux.${{ matrix.tasks }} - name: Run '${{ matrix.tasks }}' from flake.nix - - haddock: - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v2.4.0 - - - uses: cachix/install-nix-action@v16 - name: Set up Nix and IOHK caches - with: - nix_path: nixpkgs=channel:nixos-unstable - extra_nix_config: | - trusted-public-keys = hydra.iohk.io:f/Ea+s+dFdN+3Y/G+FDgSq+a5NEWhJGzdjvKNGv0/EQ= iohk.cachix.org-1:DpRUyj7h7V830dp/i6Nti+NEO2/nhblbov/8MW7Rqoo= cache.nixos.org-1:6NCHdD59X431o0gWypbMrAURkbJ16ZPMQFGspcDShjY= - substituters = https://hydra.iohk.io https://iohk.cachix.org https://cache.nixos.org/ - experimental-features = nix-command flakes - - - uses: cachix/cachix-action@v10 - with: - name: mlabs - authToken: ${{ secrets.CACHIX_KEY }} - - - run: nix build .#packages.x86_64-linux.haddock - name: Run 'haddock' from flake.nix - - # This publishes the haddock result to the branch 'gh-pages', - # which is set to automatically deploy to https://liqwid-labs.github.io/agora/. - - name: Publish Documentation - uses: peaceiris/actions-gh-pages@v3 - if: github.ref == 'refs/heads/main' - with: - github_token: ${{ secrets.GITHUB_TOKEN }} - publish_dir: ./result/agora/html diff --git a/CHANGELOG.md b/CHANGELOG.md index 787db68a..3a8f0178 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,70 @@ This format is based on [Keep A Changelog](https://keepachangelog.com/en/1.0.0). +## Unreleased (Candidate for 1.0.0) + +## 0.2.0 -- 2022-08-13 + +### Added + +- Script exporting with `plutarch-script-export` + +### Modified + +- Bump plutarch to 1.2 and use `liqwid-nix` for flake derivation. + + Included by [#150](https://github.com/Liqwid-Labs/agora/pull/150). + +- Script building uses the lazy record `AgoraScripts` instead of explicit per-component parameters. + + Included by [#150](https://github.com/Liqwid-Labs/agora/pull/150). + +- Stake delegation. + + Included by [#149](https://github.com/Liqwid-Labs/agora/pull/149). + +- Fixed bug that checks the proposal thresholds in an incorrect way. Added negative tests for the governor scripts. + + Included by [#146](https://github.com/Liqwid-Labs/agora/pull/146). + +- Draft phase and cosigning for Proposals. + + Included by [#136](https://github.com/Liqwid-Labs/agora/pull/136). + +- Fixed bug with regards to moving from `VotingReady`. + + Included by [#134](https://github.com/Liqwid-Labs/agora/pull/134). + +- Fixed bug that made it impossible to create proposals. Added new stake locking mechanism for creating proposals. + + Included by [#142](https://github.com/Liqwid-Labs/agora/pull/142). + + NOTE: This changes the representation of the following types: + + - `PProposalLock` + - `PStakeDatum` + - `PStakeRedeemer` + - `PProposalRedeemer` + - `PTreasuryRedeemer` + - `PGovernorDatum` + +### Removed + +- Side-stream utilies into `liqwid-Labs/liqwid-plutarch-extra` + - `Agora.MultiSig`--entire module. + - `scriptHashFromAddress` to `Plutarch.Api.V1.ScriptContext`. + - `findOutputsToAddress` to `Plutarch.Api.V1.ScriptContext`. + - `findTxOutDatum` to `Plutarch.Api.V1.ScriptContext`. + - `hasOnlyOneTokenOfCurrencySymbol` to `Plutarch.Api.V1.Value`. + - `mustBePJust` to `Plutarch.Extra.Maybe`. + - `mustBePDJust` to `Plutarch.Extra.Maybe`. + - `isScriptAddress` to `Plutarch.Api.V1.ScriptContext`. + - `isPubKey` to `Plutarch.Api.V1.ScriptContext`. + - `pisUniqBy'` to `Plutarch.Extra.List`. + - `pisUniq'` to `Plutarch.Extra.List`. + - `pon` to `Plutarch.Extra.Function`. + - `pbuiltinUncurry` to `Plutarch.Extra.Function`. + ## 0.1.0 -- 2022-06-22 ### Added diff --git a/Makefile b/Makefile index deab8da8..bab143b7 100644 --- a/Makefile +++ b/Makefile @@ -1,13 +1,32 @@ # This really ought to be `/usr/bin/env bash`, but nix flakes don't like that. SHELL := /bin/sh -.PHONY: hoogle format haddock usage tag format_nix format_haskell format_check lint ps_bridge bench bench_check scripts +.PHONY: hoogle format haddock usage tag format_nix format_haskell format_check \ + lint refactor ps_bridge bench bench_check scripts test build ci -AGORA_TARGETS := agora agora-bench agora-purescript-bridge agora-scripts agora-specs agora-test agora-testlib +SOURCE_FILES := $(shell git ls-tree -r HEAD --full-tree --name-only) +SOURCE_FILES := $(wildcard $(SOURCE_FILES)) +HASKELL_SOURCES := $(filter %.hs,$(SOURCE_FILES)) +CABAL_SOURCES := $(filter %.cabal,$(SOURCE_FILES)) +NIX_SOURCES := $(filter %.nix,$(SOURCE_FILES)) +FORMAT_EXTENSIONS := -o -XQuasiQuotes -o -XTemplateHaskell -o -XTypeApplications \ + -o -XImportQualifiedPost -o -XPatternSynonyms -o -XOverloadedRecordDot +HLINT_EXTS := -XQuasiQuotes + +THREADS ?= 8 +PS_BRIDGE_OUTPUT_DIR ?= agora-purescript-bridge/ +BENCH_OUTPUT ?= bench.csv +TEST_CASE_TIMEOUT ?= 100 usage: - @echo "usage: make [OPTIONS]" + @echo "usage: [env [= ...]] make [OPTIONS]" @echo + @echo "Available variables:" + @echo " THREADS -- The number of threads for building the project" + @echo " PS_BRIDGE_OUTPUT_DIR -- The output directory of the purescript bridge" + @echo " BENCH_OUTPUT -- The output file of the benchmark report" + @echo " TEST_CASE_TIMEOUT -- Timeout for individual tests. Default unit: s" + @echo @echo "Available commands:" @echo " hoogle -- Start local hoogle" @echo " format -- Format the project" @@ -20,9 +39,14 @@ usage: @echo " ps_bridge -- Generate purescript bridge files" @echo " bench -- Generate bench report bench.csv" @echo " bench_check -- Check if bench report is up-to-date" - @echo " scripts -- Export scripts to json files" + @echo " scripts -- Run the agora script server (dev mode)" + @echo " ci -- Run all the CI checks" + +requires_nix_shell: + @ [ "$(IN_NIX_SHELL)" ] || echo "The $(MAKECMDGOALS) target must be run from inside a nix shell" + @ [ "$(IN_NIX_SHELL)" ] || (echo " run 'nix develop' first" && false) -hoogle: +hoogle: requires_nix_shell pkill hoogle || true hoogle generate --local=haddock --database=hoo/local.hoo hoogle server --local -p 8081 >> /dev/null & @@ -30,45 +54,48 @@ hoogle: format: format_haskell format_nix -format_nix: - git ls-tree -r HEAD --full-tree --name-only | grep -E '.*\.nix' | xargs nixpkgs-fmt +format_nix: requires_nix_shell + nixpkgs-fmt $(NIX_SOURCES) -FORMAT_EXTENSIONS := -o -XQuasiQuotes -o -XTemplateHaskell -o -XTypeApplications -o -XImportQualifiedPost -o -XPatternSynonyms -o -XOverloadedRecordDot -format_haskell: - find -name '*.hs' -not -path './dist-*/*' | xargs fourmolu $(FORMAT_EXTENSIONS) -m inplace - git ls-tree -r HEAD --full-tree --name-only | grep -E '.*\.cabal' | xargs cabal-fmt -i +format_haskell: requires_nix_shell + fourmolu $(FORMAT_EXTENSIONS) -m inplace $(HASKELL_SOURCES) + cabal-fmt -i $(CABAL_SOURCES) -format_check: - find -name '*.hs' \ - -not -path './dist*/*' \ - -not -path './haddock/*' \ - | xargs fourmolu $(FORMAT_EXTENSIONS) -m check +format_check: requires_nix_shell + fourmolu $(FORMAT_EXTENSIONS) -m check $(HASKELL_SOURCES) + nixpkgs-fmt --check $(NIX_SOURCES) + cabal-fmt --check $(CABAL_SOURCES) -haddock: +haddock: requires_nix_shell cabal haddock --haddock-html --haddock-hoogle --builddir=haddock -tag: - hasktags -x $(AGORA_TARGETS) +tag: requires_nix_shell + hasktags -x $(HASKELL_SOURCES) -lint: - hlint $(AGORA_TARGETS) +lint: requires_nix_shell + hlint $(HLINT_EXTS) $(HASKELL_SOURCES) -PS_BRIDGE_OUTPUT_DIR := agora-purescript-bridge/ -ps_bridge: +refactor: requires_nix_shell + for src in $(HASKELL_SOURCES) ; do \ + hlint $(HLINT_EXTS) --refactor --refactor-options='-i -s' $$src ;\ + done + +ps_bridge: requires_nix_shell cabal run exe:agora-purescript-bridge -- -o $(PS_BRIDGE_OUTPUT_DIR) -bench: - cabal run agora-bench - -BENCH_TMPDIR := $(shell mktemp -d) -BENCH_TMPFILE := $(BENCH_TMPDIR)/bench.csv -bench_check: - (cabal run agora-bench -- -o "$(BENCH_TMPFILE)" \ - || $(bench) -o "$(BENCH_TMPFILE)") >> /dev/null - diff bench.csv $(BENCH_TMPFILE) \ - || (echo "bench.csv is outdated"; exit 1) - # TODO: do the clean-up even if `diff` fails. - rm -rf $(BENCH_TMPDIR) - -scripts: - cabal run agora-scripts \ No newline at end of file +bench: requires_nix_shell + cabal run agora-bench -- -o $(BENCH_OUTPUT) + +bench_check: requires_nix_shell + cabal -v0 new-run agora-bench | diff bench.csv - + +scripts: requires_nix_shell + cabal run agora-scripts -- -c + +test: requires_nix_shell + cabal test --test-options="--hide-successes -t $(TEST_CASE_TIMEOUT) -j$(THREADS)" + +build: requires_nix_shell + cabal build -j$(THREADS) + +ci: format_check lint build bench_check test haddock diff --git a/README.md b/README.md index c21076b9..6a24af8d 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,4 @@ # Agora :classical_building: -![integrate.yaml badge](https://github.com/Liqwid-Labs/agora/actions/workflows/integrate.yaml/badge.svg?branch=master) Agora is a set of Plutus scripts that compose together to form a governance system. @@ -13,7 +12,7 @@ Goals: Non-goals: - Agora is not a DAO. It doesn't have tokenomics or even a token. It is simply a library for governance. -- Agora doesn't aim to provide any primitive tools for Plutus that are not governance-specific. For this, see [plutus-extra](https://github.com/Liqwid-Labs/plutus-extra/). +- Agora doesn't aim to provide any primitive tools for Plutus that are not governance-specific. For this, see [liqwid-plutarch-extra](https://github.com/Liqwid-Labs/liqwid-plutarch-extra/). ## Project setup @@ -21,6 +20,18 @@ An up to date version of the [Nix package manager](nixos.org) (>=2.3) is require Open a development shell with `nix develop` and build the project with `cabal build`. Those pained by the need to remember to enter a Nix shell may consider using [nix-direnv](https://github.com/nix-community/nix-direnv). +## `agora-scripts` HTTP export server + +To use scripts in a frontend, you can use the `agora-scripts` executable which allows you to query them on-demand. + +The CTL repo [`agora-offchain`](https://github.com/mlabs-haskell/agora-offchain) already has the setup prepared for this feature. + +In order to run the server, simply run the following command: + +```sh +cabal run agora-scripts -- --enable-cors-middleware +``` + ## Documentation Documentation for Agora is hosted on Notion. You can find the specs [here](https://liqwid.notion.site/e85c09d2c9a542b19aac8dd3d6caa98b?v=d863219cd6a14082a661c4959cabd6e7). @@ -55,3 +66,9 @@ Please read [CONTRIBUTING.md](./CONTRIBUTING.md). Additionally, please follow th - [ ] Rewards distribution - [ ] Escrow staking pool solution + +### Available support channels info + +You can find help, more information and ongoing discusion about the project here: + +- The [Agora & Liqwid Libs Discord](https://discord.gg/yGkjxrYueB) - Most Agora discussion happens here. diff --git a/agora-bench/Bench.hs b/agora-bench/Bench.hs index 32cefc2c..d8cdafbb 100644 --- a/agora-bench/Bench.hs +++ b/agora-bench/Bench.hs @@ -8,7 +8,6 @@ import Data.ByteString.Short qualified as SBS import Data.Csv (DefaultOrdered, ToNamedRecord, header, headerOrder, namedRecord, toNamedRecord, (.=)) import Data.List (intercalate) import Data.Text (Text, pack) -import GHC.Generics (Generic) import Plutarch.Evaluate (evalScript) import PlutusLedgerApi.V1 ( ExBudget (ExBudget), diff --git a/agora-bench/Main.hs b/agora-bench/Main.hs index 50e49115..9f665bea 100644 --- a/agora-bench/Main.hs +++ b/agora-bench/Main.hs @@ -3,10 +3,10 @@ module Main (main) where import Bench (specificationTreeToBenchmarks) import Data.Csv (EncodeOptions (encUseCrLf), defaultEncodeOptions, encodeDefaultOrderedByNameWith) import Data.Text.Lazy.Encoding (decodeUtf8) -import Data.Text.Lazy.IO as I (writeFile) +import Data.Text.Lazy.IO as I (putStr, writeFile) import Options (Options (..), parseOptions) import Prettyprinter (defaultLayoutOptions, layoutPretty, pretty) -import Prettyprinter.Render.String (renderString) +import Prettyprinter.Render.Text (renderLazy) import Spec.AuthorityToken qualified as AuthorityToken import Spec.Effect.GovernorMutation qualified as GovernorMutation import Spec.Effect.TreasuryWithdrawal qualified as TreasuryWithdrawal @@ -14,6 +14,7 @@ import Spec.Governor qualified as Governor import Spec.Proposal qualified as Proposal import Spec.Stake qualified as Stake import Spec.Treasury qualified as Treasury +import System.IO (hIsTerminalDevice, stdout) import Test.Specification (group) import Prelude @@ -22,11 +23,14 @@ import Prelude main :: IO () main = do options <- parseOptions + isTTY <- hIsTerminalDevice stdout - I.writeFile options.output $ - (decodeUtf8 . encodeDefaultOrderedByNameWith encodeOptions) res + mapM_ (`I.writeFile` csv) options.output - mapM_ (putStrLn . renderString . layoutPretty defaultLayoutOptions . pretty) res + I.putStr $ + if isTTY + then prettified + else csv where encodeOptions = defaultEncodeOptions @@ -49,3 +53,7 @@ main = do , group "AuthorityToken" AuthorityToken.specs , group "Governor" Governor.specs ] + + csv = decodeUtf8 $ encodeDefaultOrderedByNameWith encodeOptions res + + prettified = renderLazy $ layoutPretty defaultLayoutOptions $ pretty res diff --git a/agora-bench/Options.hs b/agora-bench/Options.hs index d0329999..ce0f593e 100644 --- a/agora-bench/Options.hs +++ b/agora-bench/Options.hs @@ -1,21 +1,22 @@ module Options (Options (..), parseOptions) where +import Control.Applicative (optional) import Options.Applicative ((<**>)) import Options.Applicative qualified as Opt newtype Options = Options - { output :: FilePath + { output :: Maybe FilePath } -outputOpt :: Opt.Parser FilePath +outputOpt :: Opt.Parser (Maybe FilePath) outputOpt = - Opt.strOption - ( Opt.long "output-path" - <> Opt.short 'o' - <> Opt.metavar "OUTPUT_PATH" - <> Opt.value "./bench.csv" - <> Opt.help "The path of the bench report file." - ) + optional $ + Opt.strOption + ( Opt.long "output-path" + <> Opt.short 'o' + <> Opt.metavar "OUTPUT_PATH" + <> Opt.help "The path of the bench report file." + ) benchOpt :: Opt.Parser Options benchOpt = Options <$> outputOpt diff --git a/agora-purescript-bridge/AgoraTypes.hs b/agora-purescript-bridge/AgoraTypes.hs index f4f0afe1..21a41d9c 100644 --- a/agora-purescript-bridge/AgoraTypes.hs +++ b/agora-purescript-bridge/AgoraTypes.hs @@ -15,7 +15,6 @@ import Agora.AuthorityToken qualified as AuthorityToken import Agora.Effect.GovernorMutation qualified as GovernorMutation import Agora.Effect.TreasuryWithdrawal qualified as TreasuryWithdrawalEffect import Agora.Governor qualified as Governor -import Agora.MultiSig qualified as MultiSig import Agora.Proposal qualified as Proposal import Agora.Stake qualified as Stake import Agora.Treasury qualified as Treasury @@ -32,16 +31,12 @@ agoraTypes = , mkSumType (Proxy @Proposal.ProposalVotes) , mkSumType (Proxy @Proposal.ProposalDatum) , mkSumType (Proxy @Proposal.ProposalRedeemer) - , mkSumType (Proxy @Proposal.Proposal) , -- Governor mkSumType (Proxy @Governor.GovernorDatum) , mkSumType (Proxy @Governor.GovernorRedeemer) , mkSumType (Proxy @Governor.Governor) - , -- MultiSig - mkSumType (Proxy @MultiSig.MultiSig) , -- Stake - mkSumType (Proxy @Stake.Stake) - , mkSumType (Proxy @Stake.ProposalLock) + mkSumType (Proxy @Stake.ProposalLock) , mkSumType (Proxy @Stake.StakeRedeemer) , mkSumType (Proxy @Stake.StakeDatum) , -- Treasury diff --git a/agora-scripts/Main.hs b/agora-scripts/Main.hs new file mode 100644 index 00000000..64ee8c39 --- /dev/null +++ b/agora-scripts/Main.hs @@ -0,0 +1,164 @@ +{-# LANGUAGE TemplateHaskell #-} + +{- | Module : Main + Maintainer : emi@haskell.fyi + Description: Export scripts given configuration. + + Export scripts given configuration. +-} +module Main (main) where + +import Agora.Bootstrap qualified as Bootstrap +import Agora.Governor (Governor (..)) +import Agora.SafeMoney (GTTag) +import Agora.Scripts qualified as Scripts +import Agora.Utils (CompiledMintingPolicy (..), CompiledValidator (..)) +import Data.Aeson qualified as Aeson +import Data.Default (def) +import Data.Function ((&)) +import Data.Tagged (Tagged) +import Data.Text (Text) +import Development.GitRev (gitBranch, gitHash) +import GHC.Generics qualified as GHC +import Plutarch (Config (..), TracingMode (DoTracing)) +import PlutusLedgerApi.V1 ( + MintingPolicy (getMintingPolicy), + TxOutRef, + Validator (getValidator), + ) +import PlutusLedgerApi.V1.Value (AssetClass) +import ScriptExport.API (runServer) +import ScriptExport.Options (parseOptions) +import ScriptExport.ScriptInfo (ScriptInfo (..), mkPolicyInfo, mkScriptInfo, mkValidatorInfo) +import ScriptExport.Types (Builders, insertBuilder) + +main :: IO () +main = + parseOptions >>= runServer revision builders + where + -- This encodes the git revision of the server. It's useful for the caller + -- to be able to ensure they are compatible with it. + revision :: Text + revision = $(gitBranch) <> "@" <> $(gitHash) + +{- | Builders for Agora scripts. + + @since 0.2.0 +-} +builders :: Builders +builders = + def + -- Agora scripts + & insertBuilder "governorPolicy" ((.governorPolicyInfo) . agoraScripts) + & insertBuilder "governorValidator" ((.governorValidatorInfo) . agoraScripts) + & insertBuilder "stakePolicy" ((.stakePolicyInfo) . agoraScripts) + & insertBuilder "stakeValidator" ((.stakeValidatorInfo) . agoraScripts) + & insertBuilder "proposalPolicy" ((.proposalPolicyInfo) . agoraScripts) + & insertBuilder "proposalValidator" ((.proposalValidatorInfo) . agoraScripts) + & insertBuilder "treasuryValidator" ((.treasuryValidatorInfo) . agoraScripts) + & insertBuilder "authorityTokenPolicy" ((.authorityTokenPolicyInfo) . agoraScripts) + -- Trivial scripts. These are useful for testing, but they likely aren't useful + -- to you if you are actually interested in deploying to mainnet. + & insertBuilder + "alwaysSucceedsPolicy" + (\() -> mkPolicyInfo $ plam $ \_ _ -> popaque (pconstant ())) + & insertBuilder + "alwaysSucceedsValidator" + (\() -> mkValidatorInfo $ plam $ \_ _ _ -> popaque (pconstant ())) + & insertBuilder + "neverSucceedsPolicy" + (\() -> mkPolicyInfo $ plam $ \_ _ -> perror) + & insertBuilder + "neverSucceedsValidator" + (\() -> mkValidatorInfo $ plam $ \_ _ _ -> perror) + +{- | Create scripts from params. + + @since 0.2.0 +-} +agoraScripts :: ScriptParams -> AgoraScripts +agoraScripts params = + AgoraScripts + { governorPolicyInfo = mkPolicyInfo' scripts.compiledGovernorPolicy + , governorValidatorInfo = mkValidatorInfo' scripts.compiledGovernorValidator + , stakePolicyInfo = mkPolicyInfo' scripts.compiledStakePolicy + , stakeValidatorInfo = mkValidatorInfo' scripts.compiledStakeValidator + , proposalPolicyInfo = mkPolicyInfo' scripts.compiledProposalPolicy + , proposalValidatorInfo = mkValidatorInfo' scripts.compiledProposalValidator + , treasuryValidatorInfo = mkValidatorInfo' scripts.compiledTreasuryValidator + , authorityTokenPolicyInfo = mkPolicyInfo' scripts.compiledAuthorityTokenPolicy + } + where + governor = + Agora.Governor.Governor + params.governorInitialSpend + params.gtClassRef + params.maximumCosigners + + scripts = Bootstrap.agoraScripts plutarchConfig governor + +{- | Params required for creating script export. + + @since 0.2.0 +-} +data ScriptParams where + ScriptParams :: + { governorInitialSpend :: TxOutRef + , gtClassRef :: Tagged GTTag AssetClass + , maximumCosigners :: Integer + } -> + ScriptParams + deriving anyclass (Aeson.ToJSON, Aeson.FromJSON) + deriving stock (Show, Eq, GHC.Generic, Ord) + +{- | Scripts that get exported. + + @since 0.2.0 +-} +data AgoraScripts = AgoraScripts + { governorPolicyInfo :: ScriptInfo + , governorValidatorInfo :: ScriptInfo + , stakePolicyInfo :: ScriptInfo + , stakeValidatorInfo :: ScriptInfo + , proposalPolicyInfo :: ScriptInfo + , proposalValidatorInfo :: ScriptInfo + , treasuryValidatorInfo :: ScriptInfo + , authorityTokenPolicyInfo :: ScriptInfo + } + deriving anyclass + ( -- | @since 0.2.0 + Aeson.ToJSON + , -- | @since 0.2.0 + Aeson.FromJSON + ) + deriving stock + ( -- | @since 0.2.0 + Show + , -- | @since 0.2.0 + Eq + , -- | @since 0.2.0 + GHC.Generic + ) + +{- | Default plutarch configuration for compiling scripts. + + TODO: we should have an option to control this. + + @since 0.2.0 +-} +plutarchConfig :: Config +plutarchConfig = Config {tracingMode = DoTracing} + +{- | Turn a precompiled minting policy to a 'ScriptInfo'. + + @since 0.2.0 +-} +mkPolicyInfo' :: forall redeemer. CompiledMintingPolicy redeemer -> ScriptInfo +mkPolicyInfo' = mkScriptInfo . getMintingPolicy . getCompiledMintingPolicy + +{- | Turn a precompiled validator to a 'ScriptInfo'. + + @since 0.2.0 +-} +mkValidatorInfo' :: forall redeemer datum. CompiledValidator datum redeemer -> ScriptInfo +mkValidatorInfo' = mkScriptInfo . getValidator . getCompiledValidator diff --git a/agora-scripts/Options.hs b/agora-scripts/Options.hs deleted file mode 100644 index e56d09a0..00000000 --- a/agora-scripts/Options.hs +++ /dev/null @@ -1,45 +0,0 @@ -{- | -Module : Options -Maintainer : emi@haskell.fyi -Description: Command line options for 'agora-scripts'. - -Command line options for 'agora-scripts'. --} -module Options (Options (..), parseOptions) where - -import Options.Applicative ((<**>)) -import Options.Applicative qualified as Opt - -data Options = Options - { config :: FilePath - , output :: FilePath - } - deriving stock (Show, Eq) - -opt :: Opt.Parser Options -opt = - Options - <$> Opt.strOption - ( Opt.long "config" - <> Opt.short 'c' - <> Opt.metavar "CONFIG_PATH" - <> Opt.value "./agora-scripts/agora-params.json" - <> Opt.help "The path where the script configuration is." - ) - <*> Opt.strOption - ( Opt.long "output" - <> Opt.short 'o' - <> Opt.metavar "OUTPUT_PATH" - <> Opt.value "./agora-scripts/agora-scripts.json" - <> Opt.help "Output where generated scripts will be." - ) - -parseOptions :: IO Options -parseOptions = Opt.execParser p - where - p = - Opt.info - (opt <**> Opt.helper) - ( Opt.fullDesc - <> Opt.progDesc "Generate Agora scripts for off-chain use." - ) diff --git a/agora-scripts/Scripts.hs b/agora-scripts/Scripts.hs deleted file mode 100644 index 132f5ce3..00000000 --- a/agora-scripts/Scripts.hs +++ /dev/null @@ -1,121 +0,0 @@ -{-# LANGUAGE TemplateHaskell #-} - -{- | -Module : Scripts -Maintainer : emi@haskell.fyi -Description: Export scripts given configuration. - -Export scripts given configuration. --} -module Main (main) where - -import Agora.AuthorityToken (AuthorityToken, authorityTokenPolicy) -import Agora.Governor (Governor (Governor)) -import Agora.Governor qualified as Governor -import Agora.Governor.Scripts ( - authorityTokenFromGovernor, - authorityTokenSymbolFromGovernor, - governorPolicy, - governorValidator, - proposalFromGovernor, - stakeFromGovernor, - ) -import Agora.Proposal (Proposal) -import Agora.Proposal.Scripts (proposalPolicy, proposalValidator) -import Agora.SafeMoney (GTTag) -import Agora.ScriptInfo (PolicyInfo, ValidatorInfo, mkPolicyInfo, mkValidatorInfo) -import Agora.Stake (Stake) -import Agora.Stake.Scripts (stakePolicy, stakeValidator) -import Agora.Treasury (treasuryValidator) -import Control.Monad ((>=>)) -import Data.Aeson qualified as Aeson -import Data.Tagged (Tagged) -import Development.GitRev (gitBranch, gitHash) -import GHC.Generics qualified as GHC -import Options (Options (..), parseOptions) -import Plutarch.Api.V1 (mintingPolicySymbol, mkMintingPolicy) -import PlutusLedgerApi.V1 (TxOutRef) -import PlutusLedgerApi.V1.Value (AssetClass, CurrencySymbol) -import PlutusLedgerApi.V1.Value qualified as Value -import System.Exit (exitFailure) -import Text.Printf (printf) - --- | Params required for creating script export. -data ScriptParams = ScriptParams - { governorInitialSpend :: TxOutRef - , gtClassRef :: Tagged GTTag AssetClass - , maximumCosigners :: Integer - } - deriving anyclass (Aeson.ToJSON, Aeson.FromJSON) - deriving stock (Show, Eq, GHC.Generic) - --- | Scripts that get exported. -data AgoraScripts = AgoraScripts - { gitRev :: String - , governorPolicyInfo :: PolicyInfo - , governorValidatorInfo :: ValidatorInfo - , stakePolicyInfo :: PolicyInfo - , stakeValidatorInfo :: ValidatorInfo - , proposalPolicyInfo :: PolicyInfo - , proposalValidatorInfo :: ValidatorInfo - , treasuryValidatorInfo :: ValidatorInfo - , authorityTokenPolicyInfo :: PolicyInfo - } - deriving anyclass (Aeson.ToJSON, Aeson.FromJSON) - deriving stock (Show, Eq, GHC.Generic) - -main :: IO () -main = do - options <- parseOptions - - params <- - Aeson.eitherDecodeFileStrict @ScriptParams options.config - >>= either (putStrLn >=> const exitFailure) pure - - let scripts = agoraScripts params - - Aeson.encodeFile options.output scripts - - printf "Done! Wrote to %s\n" options.output - --- | Create scripts from params. -agoraScripts :: ScriptParams -> AgoraScripts -agoraScripts params = - AgoraScripts - { gitRev = revision - , governorPolicyInfo = mkPolicyInfo (governorPolicy governor) - , governorValidatorInfo = mkValidatorInfo (governorValidator governor) - , stakePolicyInfo = mkPolicyInfo (stakePolicy params.gtClassRef) - , stakeValidatorInfo = mkValidatorInfo (stakeValidator stake) - , proposalPolicyInfo = mkPolicyInfo (proposalPolicy governorSTAssetClass) - , proposalValidatorInfo = mkValidatorInfo (proposalValidator proposal) - , treasuryValidatorInfo = mkValidatorInfo (treasuryValidator authorityTokenSymbol) - , authorityTokenPolicyInfo = mkPolicyInfo (authorityTokenPolicy authorityToken) - } - where - revision :: String - revision = $(gitBranch) <> "@" <> $(gitHash) - - governor :: Governor - governor = - Governor - { Governor.gstOutRef = params.governorInitialSpend - , Governor.gtClassRef = params.gtClassRef - , Governor.maximumCosigners = params.maximumCosigners - } - - authorityToken :: AuthorityToken - authorityToken = authorityTokenFromGovernor governor - - authorityTokenSymbol :: CurrencySymbol - authorityTokenSymbol = authorityTokenSymbolFromGovernor governor - - governorSTAssetClass :: AssetClass - governorSTAssetClass = - Value.assetClass (mintingPolicySymbol $ mkMintingPolicy $ governorPolicy governor) "" - - proposal :: Proposal - proposal = proposalFromGovernor governor - - stake :: Stake - stake = stakeFromGovernor governor diff --git a/agora-scripts/agora-params.json b/agora-scripts/agora-params.json deleted file mode 100644 index abb0f3d6..00000000 --- a/agora-scripts/agora-params.json +++ /dev/null @@ -1,11 +0,0 @@ -{ - "governorInitialSpend": { - "txOutRefId": "7be688c61c209dd7a9f4948090db0b031b11a8850b0ee4695f786fea85fbfdee", - "txOutRefIdx": 0 - }, - "gtClassRef": [ - "", - "" - ], - "maximumCosigners": 5 -} diff --git a/agora-specs/Property/Generator.hs b/agora-specs/Property/Generator.hs index e7a2f309..a1a26fc2 100644 --- a/agora-specs/Property/Generator.hs +++ b/agora-specs/Property/Generator.hs @@ -114,8 +114,10 @@ genInput = do val <- genSingletonValue return $ input $ - credential cred - . withValue val + mconcat + [ credential cred + , withValue val + ] genOutput :: Builder a => Gen a genOutput = do @@ -123,8 +125,10 @@ genOutput = do val <- genSingletonValue return $ output $ - credential cred - . withValue val + mconcat + [ credential cred + , withValue val + ] genOutRef :: Gen TxOutRef genOutRef = do diff --git a/agora-specs/Property/Governor.hs b/agora-specs/Property/Governor.hs index c4922a82..1da91d8e 100644 --- a/agora-specs/Property/Governor.hs +++ b/agora-specs/Property/Governor.hs @@ -7,7 +7,7 @@ Property model and tests for 'Governor' related functions -} module Property.Governor (props) where -import Agora.Governor (GovernorDatum (..), governorDatumValid) +import Agora.Governor (Governor (gstOutRef), GovernorDatum (..), pisGovernorDatumValid) import Agora.Governor.Scripts (governorPolicy) import Agora.Proposal ( ProposalId (ProposalId), @@ -30,6 +30,7 @@ import Plutarch.Context ( output, script, withDatum, + withMinting, withOutRef, withValue, ) @@ -43,6 +44,7 @@ import PlutusLedgerApi.V1.Value (assetClassValue) import Property.Generator (genInput, genOutput) import Sample.Shared ( govAssetClass, + govSymbol, govValidatorHash, governor, gstUTXORef, @@ -62,8 +64,6 @@ data GovernorDatumCases = ExecuteLE0 | CreateLE0 | VoteLE0 - | CreateLEVote - | ExecuteLVote | Correct deriving stock (Eq, Show) @@ -72,8 +72,6 @@ instance Universe GovernorDatumCases where [ ExecuteLE0 , CreateLE0 , VoteLE0 - , CreateLEVote - , ExecuteLVote , Correct ] @@ -87,15 +85,13 @@ instance Finite GovernorDatumCases where -} governorDatumValidProperty :: Property governorDatumValidProperty = - classifiedPropertyNative gen (const []) expected classifier governorDatumValid + classifiedPropertyNative gen (const []) expected classifier pisGovernorDatumValid where classifier :: GovernorDatum -> GovernorDatumCases classifier (proposalThresholds -> ProposalThresholds e c v) | e < 0 = ExecuteLE0 | c < 0 = CreateLE0 | v < 0 = VoteLE0 - | c > v = CreateLEVote - | v >= e = ExecuteLVote | otherwise = Correct expected :: GovernorDatum -> Maybe Bool @@ -106,7 +102,7 @@ governorDatumValidProperty = thres <- genProposalThresholds c let timing = ProposalTimingConfig 0 0 0 0 - return $ GovernorDatum thres (ProposalId 0) timing (MaxTimeRangeWidth 0) + return $ GovernorDatum thres (ProposalId 0) timing (MaxTimeRangeWidth 1) 3 where taggedInteger p = Tagged <$> chooseInteger p genProposalThresholds :: GovernorDatumCases -> Gen ProposalThresholds @@ -127,16 +123,6 @@ governorDatumValidProperty = VoteLE0 -> -- vote < 0 return $ ProposalThresholds execute create le0 - CreateLEVote -> do - -- c > vote - nv <- taggedInteger (0, untag create - 1) - ne <- taggedInteger (untag nv + 1, 1000000000) - return $ ProposalThresholds ne create nv - ExecuteLVote -> do - -- vote >= execute - ne <- taggedInteger (0, untag vote) - nc <- taggedInteger (0, untag vote) - return $ ProposalThresholds ne nc vote Correct -> do -- c <= vote < execute nv <- taggedInteger (0, untag execute - 1) @@ -171,7 +157,13 @@ governorMintingProperty = -} gst = assetClassValue govAssetClass 1 mintAmount x = mint . mconcat $ replicate x gst - outputToGov = output $ script govValidatorHash . withValue gst . withDatum govDatum + outputToGov = + output $ + mconcat + [ script govValidatorHash + , withValue gst + , withDatum govDatum + ] referencedInput = input $ withOutRef gstUTXORef govDatum :: GovernorDatum @@ -181,6 +173,7 @@ governorMintingProperty = , nextProposalId = ProposalId 0 , proposalTimings = def , createProposalTimeRangeMaxWidth = def + , maximumProposalsPerStake = 3 } gen :: GovernorPolicyCases -> Gen ScriptContext @@ -196,7 +189,7 @@ governorMintingProperty = GovernorOutputNotFound -> referencedInput <> mintAmount 1 GovernorPolicyCorrect -> referencedInput <> outputToGov <> mintAmount 1 - return . buildMintingUnsafe $ inputs <> outputs <> comp + return . buildMintingUnsafe $ inputs <> outputs <> comp <> withMinting govSymbol expected :: ScriptContext -> Maybe () expected sc = @@ -208,7 +201,7 @@ governorMintingProperty = opaqueToUnit = plam $ \_ -> pconstant () actual :: Term s (PScriptContext :--> PUnit) - actual = plam $ \sc -> opaqueToUnit #$ governorPolicy governor # pforgetData (pconstantData ()) # sc + actual = plam $ \sc -> opaqueToUnit #$ governorPolicy governor.gstOutRef # pforgetData (pconstantData ()) # sc classifier :: ScriptContext -> GovernorPolicyCases classifier sc diff --git a/agora-specs/Property/MultiSig.hs b/agora-specs/Property/MultiSig.hs deleted file mode 100644 index 3d0d98cc..00000000 --- a/agora-specs/Property/MultiSig.hs +++ /dev/null @@ -1,107 +0,0 @@ -{- | -Module : Property.MultiSig -Maintainer : seungheon.ooh@gmail.com -Description: Property tests for 'MultiSig' functions - -Property model and tests for 'MultiSig' functions --} -module Property.MultiSig (props) where - -import Agora.MultiSig ( - MultiSig (MultiSig), - PMultiSig, - pvalidatedByMultisig, - ) -import Data.Tagged (Tagged (Tagged)) -import Data.Universe (Finite (..), Universe (..)) -import Plutarch.Api.V1 (PScriptContext) -import Plutarch.Context -import Plutarch.Extra.TermCont (pletC) -import PlutusLedgerApi.V1 ( - ScriptContext (..), - ScriptPurpose (..), - TxInfo (txInfoSignatories), - TxOutRef (..), - ) -import Property.Generator (genPubKeyHash) -import Test.Tasty (TestTree) -import Test.Tasty.Plutarch.Property (classifiedPropertyNative) -import Test.Tasty.QuickCheck ( - Gen, - Property, - chooseInt, - listOf, - testProperty, - vectorOf, - ) - --- | Model for testing multisigs. -type MultiSigModel = (MultiSig, ScriptContext) - --- | Propositions that may hold true of a `MultiSigModel`. -data MultiSigProp - = -- | Sufficient number of signatories in the script context. - MeetsMinSigs - | -- | Insufficient number of signatories in the script context. - DoesNotMeetMinSigs - deriving stock (Eq, Show, Ord) - -instance Universe MultiSigProp where - universe = [MeetsMinSigs, DoesNotMeetMinSigs] - -instance Finite MultiSigProp where - universeF = universe - cardinality = Tagged 2 - --- | Generate model with given proposition. -genMultiSigProp :: MultiSigProp -> Gen MultiSigModel -genMultiSigProp prop = do - size <- chooseInt (4, 20) - pkhs <- vectorOf size genPubKeyHash - minSig <- chooseInt (1, length pkhs) - othersigners <- take 20 <$> listOf genPubKeyHash - - let ms = MultiSig pkhs (toInteger minSig) - - n <- case prop of - MeetsMinSigs -> chooseInt (minSig, length pkhs) - DoesNotMeetMinSigs -> chooseInt (0, minSig - 1) - - let builder :: BaseBuilder - builder = mconcat $ signedWith <$> take n pkhs <> othersigners - txinfo = buildTxInfoUnsafe builder - pure (ms, ScriptContext txinfo (Spending (TxOutRef "" 0))) - --- | Classify model into propositions. -classifyMultiSigProp :: MultiSigModel -> MultiSigProp -classifyMultiSigProp (MultiSig keys (fromIntegral -> minsig), ctx) - | minsig <= length signer = MeetsMinSigs - | otherwise = DoesNotMeetMinSigs - where - signer = filter (`elem` keys) $ txInfoSignatories . scriptContextTxInfo $ ctx - --- | Shrinker. Not used. -shrinkMultiSigProp :: MultiSigModel -> [MultiSigModel] -shrinkMultiSigProp = const [] - --- | Expected behavior of @pvalidatedByMultisig@. -expectedHs :: MultiSigModel -> Maybe Bool -expectedHs model = case classifyMultiSigProp model of - MeetsMinSigs -> Just True - _ -> Just False - --- | Actual implementation of @pvalidatedByMultisig@. -actual :: Term s (PBuiltinPair PMultiSig PScriptContext :--> PBool) -actual = plam $ \x -> unTermCont $ do - ms <- pletC $ pfstBuiltin # x - sc <- pletC $ psndBuiltin # x - pure $ pvalidatedByMultisig # ms # (pfield @"txInfo" # sc) - --- | Proposed property. -prop :: Property -prop = classifiedPropertyNative genMultiSigProp shrinkMultiSigProp expectedHs classifyMultiSigProp actual - -props :: [TestTree] -props = - [ testProperty "MultiSig property" prop - ] diff --git a/agora-specs/Sample/Effect/GovernorMutation.hs b/agora-specs/Sample/Effect/GovernorMutation.hs index 7394b704..75a7a56a 100644 --- a/agora-specs/Sample/Effect/GovernorMutation.hs +++ b/agora-specs/Sample/Effect/GovernorMutation.hs @@ -17,6 +17,7 @@ import Agora.Effect.GovernorMutation ( ) import Agora.Governor (GovernorDatum (..)) import Agora.Proposal (ProposalId (..), ProposalThresholds (..)) +import Agora.Utils (validatorHashToTokenName) import Data.Default.Class (Default (def)) import Data.Tagged (Tagged (..)) import Plutarch.Api.V1 (mkValidator, validatorHash) @@ -24,7 +25,6 @@ import PlutusLedgerApi.V1 ( Address, Datum (..), ToData (..), - TokenName (..), TxInInfo (..), TxInfo (..), TxOut (..), @@ -40,10 +40,11 @@ import PlutusLedgerApi.V1.Value qualified as Value ( singleton, ) import Sample.Shared ( + agoraScripts, authorityTokenSymbol, + deterministicTracingConfing, govAssetClass, govValidatorAddress, - governor, minAda, signer, ) @@ -51,7 +52,7 @@ import Test.Util (datumPair, toDatumHash) -- | The effect validator instance. effectValidator :: Validator -effectValidator = mkValidator $ mutateGovernorValidator governor +effectValidator = mkValidator deterministicTracingConfing $ mutateGovernorValidator agoraScripts -- | The hash of the validator instance. effectValidatorHash :: ValidatorHash @@ -65,17 +66,15 @@ effectValidatorAddress = scriptHashAddress effectValidatorHash atAssetClass :: AssetClass atAssetClass = assetClass authorityTokenSymbol tokenName where - -- TODO: use 'validatorHashToTokenName' - ValidatorHash bs = effectValidatorHash - tokenName = TokenName bs + tokenName = validatorHashToTokenName effectValidatorHash -- | The mock reference of the governor state UTXO. govRef :: TxOutRef -govRef = TxOutRef "614481d2159bfb72350222d61fce17e548e0fc00e5a1f841ff1837c431346ce7" 1 +govRef = TxOutRef "1475e1ee22330dfc55430980e5a6b100ec9d9249bb4b462256a79559" 1 -- | The mock reference of the effect UTXO. effectRef :: TxOutRef -effectRef = TxOutRef "c31164dc11835de7eb6187f67d0e1a19c1dfc0786a456923eef5043189cdb578" 1 +effectRef = TxOutRef "a302d327d8e5553d50b9d017475369753f723d7e999ac1b68da8ad52" 1 -- | The input effect datum in 'mkEffectTransaction'. mkEffectDatum :: GovernorDatum -> MutateGovernorDatum @@ -106,6 +105,7 @@ mkEffectTxInfo newGovDatum = , nextProposalId = ProposalId 0 , proposalTimings = def , createProposalTimeRangeMaxWidth = def + , maximumProposalsPerStake = 3 } governorInputDatum :: Datum governorInputDatum = Datum $ toBuiltinData governorInputDatum' @@ -158,7 +158,7 @@ mkEffectTxInfo newGovDatum = , txInfoValidRange = Interval.always , txInfoSignatories = [signer] , txInfoData = datumPair <$> [governorInputDatum, governorOutputDatum, effectInputDatum] - , txInfoId = "4dae3806cc69615b721d52ed09b758f43f25a8f39b7934d6b28514caf71f5f7b" + , txInfoId = "74c75505691e7baa981fa80e50b9b7e88dbe1eda67d4f062d89d203b" } validNewGovernorDatum :: GovernorDatum @@ -168,6 +168,7 @@ validNewGovernorDatum = , nextProposalId = ProposalId 42 , proposalTimings = def , createProposalTimeRangeMaxWidth = def + , maximumProposalsPerStake = 3 } invalidNewGovernorDatum :: GovernorDatum @@ -180,4 +181,5 @@ invalidNewGovernorDatum = , nextProposalId = ProposalId 42 , proposalTimings = def , createProposalTimeRangeMaxWidth = def + , maximumProposalsPerStake = 3 } diff --git a/agora-specs/Sample/Effect/TreasuryWithdrawal.hs b/agora-specs/Sample/Effect/TreasuryWithdrawal.hs index 7c95bc97..3070e79f 100644 --- a/agora-specs/Sample/Effect/TreasuryWithdrawal.hs +++ b/agora-specs/Sample/Effect/TreasuryWithdrawal.hs @@ -23,17 +23,14 @@ import Agora.Effect.TreasuryWithdrawal ( TreasuryWithdrawalDatum (TreasuryWithdrawalDatum), treasuryWithdrawalValidator, ) -import Crypto.Hash qualified as Crypto -import Data.ByteArray qualified as BA -import Data.ByteString qualified as BS -import Data.ByteString.Char8 qualified as C (pack) +import Data.Default (def) import Plutarch.Api.V1 (mkValidator, validatorHash) import PlutusLedgerApi.V1 ( Address (Address), Credential (..), - CurrencySymbol (CurrencySymbol), + CurrencySymbol, DatumHash (DatumHash), - PubKeyHash (PubKeyHash), + PubKeyHash, ScriptContext (..), ScriptPurpose (Spending), TokenName (TokenName), @@ -56,29 +53,26 @@ import PlutusLedgerApi.V1 ( Validator, ValidatorHash (ValidatorHash), Value, - toBuiltin, ) import PlutusLedgerApi.V1.Interval qualified as Interval (always) import PlutusLedgerApi.V1.Value qualified as Value (singleton) +import Test.Util (scriptCredentials, userCredentials) -- | A sample Currency Symbol. currSymbol :: CurrencySymbol -currSymbol = CurrencySymbol "12312099" +currSymbol = "9c04a69c7133e26061fe5a15adaf4f79cd51e47ef22a2e3c91a36f04" -- | A sample 'PubKeyHash'. signer :: PubKeyHash signer = "8a30896c4fd5e79843e4ca1bd2cdbaa36f8c0bc3be7401214142019c" -blake2b_224 :: BS.ByteString -> BS.ByteString -blake2b_224 = BS.pack . BA.unpack . Crypto.hashWith Crypto.Blake2b_224 - -- | List of users who the effect will pay to. users :: [Credential] -users = PubKeyCredential . PubKeyHash . toBuiltin . blake2b_224 . C.pack . show <$> ([1 ..] :: [Integer]) +users = userCredentials -- | List of users who the effect will pay to. treasuries :: [Credential] -treasuries = ScriptCredential . ValidatorHash . toBuiltin . blake2b_224 . C.pack . show <$> ([1 ..] :: [Integer]) +treasuries = scriptCredentials inputGAT :: TxInInfo inputGAT = @@ -154,7 +148,7 @@ buildReceiversOutputFromDatum (TreasuryWithdrawalDatum xs _) = f <$> xs -- | Effect validator instance. validator :: Validator -validator = mkValidator $ treasuryWithdrawalValidator currSymbol +validator = mkValidator def $ treasuryWithdrawalValidator currSymbol -- | 'TokenName' that represents the hash of the 'Agora.Stake.Stake' validator. validatorHashTN :: TokenName diff --git a/agora-specs/Sample/Governor.hs b/agora-specs/Sample/Governor.hs deleted file mode 100644 index 16416408..00000000 --- a/agora-specs/Sample/Governor.hs +++ /dev/null @@ -1,461 +0,0 @@ -{- | -Module : Spec.Sample.Governor -Maintainer : connor@mlabs.city -Description: Sample based testing for Governor utxos - -This module tests primarily the happy path for Governor interactions --} -module Sample.Governor ( - createProposal, - mutateState, - mintGATs, - mintGST, -) where - -import Agora.Effect.NoOp (noOpValidator) -import Agora.Governor (GovernorDatum (..), getNextProposalId) -import Agora.Proposal ( - ProposalDatum (..), - ProposalId (..), - ProposalStatus (..), - ProposalVotes (..), - ResultTag (..), - emptyVotesFor, - ) -import Agora.Proposal qualified as P (ProposalDatum (proposalId)) -import Agora.Proposal.Time ( - ProposalStartingTime (ProposalStartingTime), - ProposalTimingConfig (..), - ) -import Agora.Stake (ProposalLock (..), Stake (..), StakeDatum (..)) -import Data.Default.Class (Default (def)) -import Data.Tagged (Tagged (..), untag) -import Plutarch.Api.V1 (mkValidator, validatorHash) -import Plutarch.Context ( - MintingBuilder, - SpendingBuilder, - buildMintingUnsafe, - buildSpendingUnsafe, - fee, - input, - mint, - output, - script, - signedWith, - timeRange, - txId, - withDatum, - withRefIndex, - withSpending, - withTxId, - withValue, - ) -import PlutusLedgerApi.V1 ( - BuiltinData (BuiltinData), - Data (I), - Datum (Datum), - ScriptContext, - TokenName (TokenName), - TxOutRef (txOutRefId), - Validator, - ValidatorHash (..), - ) -import PlutusLedgerApi.V1.Value (AssetClass (AssetClass)) -import PlutusLedgerApi.V1.Value qualified as Value ( - assetClassValue, - singleton, - ) -import PlutusTx.AssocMap qualified as AssocMap ( - empty, - fromList, - singleton, - ) -import Sample.Shared ( - authorityTokenSymbol, - govAssetClass, - govValidatorHash, - gstUTXORef, - minAda, - proposalPolicySymbol, - proposalStartingTimeFromTimeRange, - proposalValidatorHash, - signer, - signer2, - stake, - stakeAssetClass, - stakeValidatorHash, - ) -import Test.Util (closedBoundedInterval, toDatumHash) - --- | Unit datum -unitDatum :: Datum -unitDatum = Datum . BuiltinData $ I 0 -- This could be anything, really. It doesn't matter. - -{- | A valid 'ScriptContext' for minting GST. - - - Only the minting policy will be ran in the transaction. - - An arbitrary UTXO is spent to create the token. - - - We call this the "witness" UTXO. - - This UTXO is referenced in the 'Agora.Governor.Governor' parameter - - The minting policy should only be ran once its life time, - cause the GST cannot be minted twice or burnt. - - - The output UTXO must carry a valid 'GovernorDatum'. - - It's worth noticing that the transaction should send the GST to the governor validator, - but unfortunately we can't check it in the policy. The GST will stay at the address of - the governor validator forever once the token is under control of the said validator. - - TODO: tag the output UTXO with the target address. --} -mintGST :: ScriptContext -mintGST = - let gst = Value.assetClassValue govAssetClass 1 - - governorOutputDatum :: GovernorDatum - governorOutputDatum = - GovernorDatum - { proposalThresholds = def - , nextProposalId = ProposalId 0 - , proposalTimings = def - , createProposalTimeRangeMaxWidth = def - } - - witness :: ValidatorHash - witness = "a926a9a72a0963f428e3252caa8354e655603996fb8892d6b8323fd072345924" - - builder :: MintingBuilder - builder = - mconcat - [ txId "90906d3e6b4d6dec2e747dcdd9617940ea8358164c7244694cfa39dec18bd9d4" - , signedWith signer - , mint gst - , input $ - script witness - . withTxId (txOutRefId gstUTXORef) - . withRefIndex 0 - , output $ - script govValidatorHash - . withValue (gst <> minAda) - . withDatum governorOutputDatum - ] - in buildMintingUnsafe builder - -{- | A valid script context to create a proposal. - - Three component will run in the transaction: - TODO: mention redeemers - - - Governor validator - - Stake validator - - Proposal policy - - The components will ensure: - - - The governor state UTXO is spent - - - A new UTXO is paid back to governor validator, which carries the GST. - - The proposal id in the state datum is advanced. - - - A new UTXO is sent to the proposal validator - - - The UTXO contains a newly minted proposal state token. - - It also carries a legal proposal state datum, whose status is set to 'Agora.Proposal.Draft'. - - - A stake is spent to create a proposal - - - The stake owner must sign the transaction. - - The output stake must paid back to the stake validator. - - The output stake is locked by the newly created proposal. --} -createProposal :: ScriptContext -createProposal = - let pst = Value.singleton proposalPolicySymbol "" 1 - gst = Value.assetClassValue govAssetClass 1 - sst = Value.assetClassValue stakeAssetClass 1 - stackedGTs = 424242424242 - thisProposalId = ProposalId 0 - - governorInputDatum :: GovernorDatum - governorInputDatum = - GovernorDatum - { proposalThresholds = def - , nextProposalId = thisProposalId - , proposalTimings = def - , createProposalTimeRangeMaxWidth = def - } - - effects = - AssocMap.fromList - [ (ResultTag 0, AssocMap.empty) - , (ResultTag 1, AssocMap.empty) - ] - proposalDatum :: ProposalDatum - proposalDatum = - ProposalDatum - { P.proposalId = ProposalId 0 - , effects = effects - , status = Draft - , cosigners = [signer] - , thresholds = def - , votes = emptyVotesFor effects - , timingConfig = def - , startingTime = proposalStartingTimeFromTimeRange validTimeRange - } - - stakeInputDatum :: StakeDatum - stakeInputDatum = - StakeDatum - { stakedAmount = Tagged stackedGTs - , owner = signer - , lockedBy = [] - } - - governorOutputDatum :: GovernorDatum - governorOutputDatum = governorInputDatum {nextProposalId = getNextProposalId thisProposalId} - - proposalLocks :: [ProposalLock] - proposalLocks = - [ ProposalLock (ResultTag 0) thisProposalId - , ProposalLock (ResultTag 1) thisProposalId - ] - stakeOutputDatum :: StakeDatum - stakeOutputDatum = stakeInputDatum {lockedBy = proposalLocks} - - validTimeRange = closedBoundedInterval 10 15 - - builder :: SpendingBuilder - builder = - mconcat - [ txId "1ffb9669335c908d9a4774a4bf7aa7bfafec91d015249b4138bc83fde4a3330a" - , fee $ Value.singleton "" "" 2 - , timeRange $ closedBoundedInterval 10 15 - , signedWith signer - , mint pst - , input $ - script govValidatorHash - . withValue gst - . withDatum governorInputDatum - . withTxId "4355a46b19d348dc2f57c046f8ef63d4538ebb936000f3c9ee954a27460dd865" - , input $ - script stakeValidatorHash - . withValue (sst <> Value.assetClassValue (untag stake.gtClassRef) stackedGTs) - . withDatum stakeInputDatum - . withTxId "4262bbd0b3fc926b74eaa8abab5def6ce5e6b94f19cf221c02a16e7da8cd470f" - , output $ - script proposalValidatorHash - . withValue (pst <> minAda) - . withDatum proposalDatum - , output $ - script govValidatorHash - . withValue (gst <> minAda) - . withDatum governorOutputDatum - , output $ - script stakeValidatorHash - . withValue (sst <> Value.assetClassValue (untag stake.gtClassRef) stackedGTs <> minAda) - . withDatum stakeOutputDatum - , withSpending $ - script govValidatorHash - . withValue gst - . withDatum governorInputDatum - ] - in buildSpendingUnsafe builder - -{- This script context should be a valid transaction for minting authority for the effect scrips. - - The following components will run: - - - Governor validator - - Authority policy - - Proposal validator - - There should be only one proposal the transaction. - The validity of the proposal will be checked: - - - It's in 'Agora.Proposal.Locked' state. - - It has a 'winner' effect group, meaning that the votes meet the requirements. - - The system will ensure that for every effect scrips in said effect group, - a newly minted GAT is sent to the corresponding effect, and properly tagged. --} -mintGATs :: ScriptContext -mintGATs = - let pst = Value.singleton proposalPolicySymbol "" 1 - gst = Value.assetClassValue govAssetClass 1 - gat = Value.assetClassValue atAssetClass 1 - - mockEffect :: Validator - mockEffect = mkValidator $ noOpValidator "" - mockEffectHash :: ValidatorHash - mockEffectHash = validatorHash mockEffect - mockEffectOutputDatum :: Datum - mockEffectOutputDatum = unitDatum - atTokenName :: TokenName - atTokenName = TokenName hash - where - ValidatorHash hash = mockEffectHash - atAssetClass :: AssetClass - atAssetClass = AssetClass (authorityTokenSymbol, atTokenName) - - governorInputDatum :: GovernorDatum - governorInputDatum = - GovernorDatum - { proposalThresholds = def - , nextProposalId = ProposalId 5 - , proposalTimings = def - , createProposalTimeRangeMaxWidth = def - } - - effects = - AssocMap.fromList - [ (ResultTag 0, AssocMap.empty) - , (ResultTag 1, AssocMap.singleton mockEffectHash $ toDatumHash mockEffectOutputDatum) - ] - proposalVotes :: ProposalVotes - proposalVotes = - ProposalVotes $ - AssocMap.fromList - [ (ResultTag 0, 100) - , (ResultTag 1, 2000) -- The winner - ] - proposalInputDatum :: ProposalDatum - proposalInputDatum = - ProposalDatum - { P.proposalId = ProposalId 0 - , effects = effects - , status = Locked - , cosigners = [signer, signer2] - , thresholds = def - , votes = proposalVotes - , timingConfig = def - , startingTime = ProposalStartingTime 10 - } - - governorOutputDatum :: GovernorDatum - governorOutputDatum = governorInputDatum - - proposalOutputDatum :: ProposalDatum - proposalOutputDatum = proposalInputDatum {status = Finished} - - validTimeRange = - closedBoundedInterval - ((def :: ProposalTimingConfig).lockingTime + 11) - ((def :: ProposalTimingConfig).executingTime - 11) - - builder :: SpendingBuilder - builder = - mconcat - [ txId "ff755f613c1f7487dfbf231325c67f481f7a97e9faf4d8b09ad41176fd65cbe7" - , signedWith signer - , signedWith signer2 - , timeRange validTimeRange - , fee (Value.singleton "" "" 2) - , mint gat - , input $ - script govValidatorHash - . withValue gst - . withDatum governorInputDatum - . withTxId "4355a46b19d348dc2f57c046f8ef63d4538ebb936000f3c9ee954a27460dd865" - , input $ - script proposalValidatorHash - . withValue pst - . withDatum proposalInputDatum - . withTxId "11b2162f267614b803761032b6333040fc61478ae788c088614ee9487ab0c1b7" - , output $ - script govValidatorHash - . withValue (gst <> minAda) - . withDatum governorOutputDatum - , output $ - script proposalValidatorHash - . withValue (pst <> minAda) - . withDatum proposalOutputDatum - , output $ - script mockEffectHash - . withValue (gat <> minAda) - . withDatum mockEffectOutputDatum - , withSpending $ - script govValidatorHash - . withValue gst - . withDatum governorInputDatum - ] - in buildSpendingUnsafe builder - -{- | A valid script context for changing the state datum of the governor. - - In this case, the following components will run: - - * Governor validator - * Effect script - - The effect script should carry an valid tagged authority token, - and said token will be burnt in the transaction. We use 'noOpValidator' - here as a mock effect, so no actual change is done to the governor state. - TODO: use 'Agora.Effect.GovernorMutation.mutateGovernorEffect' as the mock effect in the future. - - The governor will ensure the new governor state is valid. --} -mutateState :: ScriptContext -mutateState = - let gst = Value.assetClassValue govAssetClass 1 - gat = Value.assetClassValue atAssetClass 1 - burntGAT = Value.assetClassValue atAssetClass (-1) - - -- TODO: Use the *real* effect, see https://github.com/Liqwid-Labs/agora/pull/62 - mockEffect :: Validator - mockEffect = mkValidator $ noOpValidator "" - mockEffectHash :: ValidatorHash - mockEffectHash = validatorHash mockEffect - atTokenName :: TokenName - atTokenName = TokenName hash - where - ValidatorHash hash = mockEffectHash - atAssetClass :: AssetClass - atAssetClass = AssetClass (authorityTokenSymbol, atTokenName) - mockEffectInputDatum :: Datum - mockEffectInputDatum = unitDatum - mockEffectOutputDatum :: Datum - mockEffectOutputDatum = mockEffectInputDatum - - governorInputDatum :: GovernorDatum - governorInputDatum = - GovernorDatum - { proposalThresholds = def - , nextProposalId = ProposalId 5 - , proposalTimings = def - , createProposalTimeRangeMaxWidth = def - } - - governorOutputDatum :: GovernorDatum - governorOutputDatum = governorInputDatum - - builder :: SpendingBuilder - builder = - mconcat - [ txId "9a12a605086a9f866731869a42d0558036fc739c74fea3849aa41562c015aaf9" - , signedWith signer - , mint burntGAT - , fee $ Value.singleton "" "" 2 - , input $ - script govValidatorHash - . withValue gst - . withDatum governorInputDatum - . withTxId "f867238a04597c99a0b9858746557d305025cca3b9f78ea14d5c88c4cfcf58ff" - , input $ - script mockEffectHash - . withValue gat - . withDatum mockEffectInputDatum - . withTxId "ecff06d7cf99089294569cc8b92609e44927278f9901730715d14634fbc10089" - , output $ - script govValidatorHash - . withValue (gst <> minAda) - . withDatum governorOutputDatum - , input $ - script mockEffectHash - . withValue minAda - . withDatum mockEffectOutputDatum - , withSpending $ - script govValidatorHash - . withValue gst - . withDatum governorInputDatum - ] - in buildSpendingUnsafe builder diff --git a/agora-specs/Sample/Governor/Initialize.hs b/agora-specs/Sample/Governor/Initialize.hs new file mode 100644 index 00000000..167cb5ab --- /dev/null +++ b/agora-specs/Sample/Governor/Initialize.hs @@ -0,0 +1,279 @@ +{- | +Module : Sample.Governor.Initialize +Maintainer : connor@mlabs.city +Description: Generate sample data for testing the functionalities of minting GST. + +Sample and utilities for testing the functionalities of minting GST. +-} +module Sample.Governor.Initialize ( + mintGST, + Parameters (..), + totallyValidParameters, + invalidDatumTimingConfigParameters, + invalidDatumMaxTimeRangeWidthParameters, + invalidDatumThresholdsParameters, + withoutGovernorDatumParameters, + witnessNotPresentedParameters, + mintMoreThanOneGSTParameters, + mintGSTWithNoneEmptyNameParameters, + mkTestCase, +) where + +import Agora.Bootstrap (agoraScripts) +import Agora.Governor (Governor (..), GovernorDatum (..)) +import Agora.Proposal (ProposalId (..), ProposalThresholds (..)) +import Agora.Proposal.Time ( + MaxTimeRangeWidth (MaxTimeRangeWidth), + ProposalTimingConfig (ProposalTimingConfig), + ) +import Agora.Scripts ( + AgoraScripts (compiledGovernorPolicy), + governorSTAssetClass, + governorSTSymbol, + governorValidatorHash, + ) +import Data.Default (Default (..)) +import Plutarch.Context ( + input, + mint, + output, + pubKey, + script, + signedWith, + txId, + withDatum, + withOutRef, + withValue, + ) +import PlutusLedgerApi.V1 ( + CurrencySymbol, + TxOutRef (TxOutRef), + ValidatorHash, + ) +import PlutusLedgerApi.V1.Value (AssetClass (..)) +import PlutusLedgerApi.V1.Value qualified as Value +import Sample.Shared ( + minAda, + ) +import Sample.Shared qualified as Shared +import Test.Specification (SpecificationTree, testPolicy) +import Test.Util (CombinableBuilder, mkMinting, pubKeyHashes, sortValue) + +-- | The parameters that control the generation of the transaction. +data Parameters = Parameters + { datumThresholdsValid :: Bool + -- ^ Whether the 'GovernorDatum.proposalThresholds' field of the output + -- governor datum is valid or not. + , datumMaxTimeRangeWidthValid :: Bool + -- ^ Whether the 'GovernorDatum.maximumProposalsPerStake'field of the + -- output governor datum is valid or not. + , datumTimingConfigValid :: Bool + -- ^ Whether the 'GovernorDatum.proposalTimings'field of the output + -- governor datum is valid or not. + , withGovernorDatum :: Bool + , -- Whether the output GST UTxO will carry the governor datum. + presentWitness :: Bool + , -- Whether to spend the UTxO referenced by 'Governor.gstOutRef'. + mintMoreThanOneStateToken :: Bool + , -- More than one GST will be minted if this is set to true. + mintStateTokenWithName :: Bool + -- The token name of the GST won't be empty if this is set to true. + } + +-------------------------------------------------------------------------------- + +validGovernorOutputDatum :: GovernorDatum +validGovernorOutputDatum = + GovernorDatum + { proposalThresholds = def + , nextProposalId = ProposalId 0 + , proposalTimings = def + , createProposalTimeRangeMaxWidth = def + , maximumProposalsPerStake = 3 + } + +invalidProposalThresholds :: ProposalThresholds +invalidProposalThresholds = ProposalThresholds (-1) (-1) (-1) + +invalidMaxTimeRangeWidth :: MaxTimeRangeWidth +invalidMaxTimeRangeWidth = MaxTimeRangeWidth 0 + +invalidProposalTimings :: ProposalTimingConfig +invalidProposalTimings = ProposalTimingConfig (-1) (-1) (-1) (-1) + +witnessRef :: TxOutRef +witnessRef = TxOutRef "b0353c22b0bd6c5296a8eef160ba25d90b5dc82a9bb8bdaa6823ffc19515d6ad" 0 + +governor :: Governor +governor = + Shared.governor + { gstOutRef = witnessRef + } + +scripts :: AgoraScripts +scripts = agoraScripts Shared.deterministicTracingConfing governor + +govAssetClass :: AssetClass +govAssetClass = governorSTAssetClass scripts + +govValidatorHash :: ValidatorHash +govValidatorHash = governorValidatorHash scripts + +govSymbol :: CurrencySymbol +govSymbol = governorSTSymbol scripts + +-------------------------------------------------------------------------------- + +mintGST :: forall b. CombinableBuilder b => Parameters -> b +mintGST ps = builder + where + gstAC = + if ps.mintStateTokenWithName + then AssetClass (govSymbol, "12345") + else govAssetClass + gstCount = + if ps.mintMoreThanOneStateToken + then 10 + else 1 + gst = Value.assetClassValue gstAC gstCount + + --- + + governorOutputDatum = + let th = + if ps.datumThresholdsValid + then def + else invalidProposalThresholds + trw = + if ps.datumMaxTimeRangeWidthValid + then def + else invalidMaxTimeRangeWidth + ptc = + if ps.datumTimingConfigValid + then def + else invalidProposalTimings + in validGovernorOutputDatum + { proposalThresholds = th + , proposalTimings = ptc + , createProposalTimeRangeMaxWidth = trw + } + + governorValue = sortValue $ gst <> minAda + + --- + + witnessValue = minAda + witnessPubKey = head pubKeyHashes + + --- + + witnessBuilder = + if ps.presentWitness + then + mconcat + [ input $ + mconcat + [ pubKey witnessPubKey + , withValue witnessValue + , withOutRef witnessRef + ] + , output $ + mconcat + [ pubKey witnessPubKey + , withValue witnessValue + ] + ] + else mempty + + --- + + govBuilder = + let datum = + if ps.withGovernorDatum + then withDatum governorOutputDatum + else mempty + in output $ + mconcat + [ script govValidatorHash + , withValue governorValue + , datum + ] + -- + builder = + mconcat + [ txId "986b756ffb1c9839fc8d0b22a308ac91d5b5d0ebbfa683a47588c8a5cf70b5af" + , signedWith (pubKeyHashes !! 1) + , mint gst + , govBuilder + , witnessBuilder + ] + +-------------------------------------------------------------------------------- + +totallyValidParameters :: Parameters +totallyValidParameters = + Parameters + { datumThresholdsValid = True + , datumMaxTimeRangeWidthValid = True + , datumTimingConfigValid = True + , withGovernorDatum = True + , presentWitness = True + , mintMoreThanOneStateToken = False + , mintStateTokenWithName = False + } + +invalidDatumThresholdsParameters :: Parameters +invalidDatumThresholdsParameters = + totallyValidParameters + { datumThresholdsValid = False + } + +invalidDatumMaxTimeRangeWidthParameters :: Parameters +invalidDatumMaxTimeRangeWidthParameters = + totallyValidParameters + { datumMaxTimeRangeWidthValid = False + } + +invalidDatumTimingConfigParameters :: Parameters +invalidDatumTimingConfigParameters = + totallyValidParameters + { datumTimingConfigValid = False + } + +withoutGovernorDatumParameters :: Parameters +withoutGovernorDatumParameters = + totallyValidParameters + { withGovernorDatum = False + } + +witnessNotPresentedParameters :: Parameters +witnessNotPresentedParameters = + totallyValidParameters + { presentWitness = False + } + +mintMoreThanOneGSTParameters :: Parameters +mintMoreThanOneGSTParameters = + totallyValidParameters + { mintMoreThanOneStateToken = True + } + +mintGSTWithNoneEmptyNameParameters :: Parameters +mintGSTWithNoneEmptyNameParameters = + totallyValidParameters + { mintStateTokenWithName = True + } + +-------------------------------------------------------------------------------- + +{- | Create a test tree that runs the governor policy to test the initialization + of the governor. +-} +mkTestCase :: String -> Parameters -> Bool -> SpecificationTree +mkTestCase name ps valid = + testPolicy + valid + name + scripts.compiledGovernorPolicy + () + (mkMinting mintGST ps govSymbol) diff --git a/agora-specs/Sample/Governor/Mutate.hs b/agora-specs/Sample/Governor/Mutate.hs new file mode 100644 index 00000000..df8a70c4 --- /dev/null +++ b/agora-specs/Sample/Governor/Mutate.hs @@ -0,0 +1,269 @@ +module Sample.Governor.Mutate ( + -- * Testing Utilities + GovernorOutputDatumValidity (..), + GATValidity (..), + GovernorParameters (..), + MockEffectParameters (..), + ParameterBundle (..), + + -- * Testing Utilities + Validity (..), + mutate, + mkTestCase, + + -- * Parameters Bundles + totallyValidBundle, + invalidBundles, +) where + +import Agora.Effect.NoOp (noOpValidator) +import Agora.Governor (GovernorDatum (..), GovernorRedeemer (MutateGovernor)) +import Agora.Proposal (ProposalId (ProposalId), ProposalThresholds (..)) +import Agora.Scripts (AgoraScripts (..)) +import Agora.Utils (validatorHashToTokenName) +import Data.Default (def) +import Plutarch.Api.V1 (PValidator, mkValidator, validatorHash) +import Plutarch.Context ( + input, + mint, + output, + pubKey, + script, + withDatum, + withOutRef, + withValue, + ) +import PlutusLedgerApi.V1 ( + Data, + TxOutRef (TxOutRef), + ValidatorHash, + Value, + toData, + ) +import PlutusLedgerApi.V1.Value qualified as Value +import Sample.Shared ( + agoraScripts, + authorityTokenSymbol, + govAssetClass, + govValidatorHash, + minAda, + ) +import Test.Specification (SpecificationTree, testValidator) +import Test.Util (CombinableBuilder, mkSpending, pubKeyHashes, sortValue, validatorHashes) + +-------------------------------------------------------------------------------- + +-- | Represent the validity property of the governor output datum. +data GovernorOutputDatumValidity + = DatumValid + | ValueInvalid + | WrongType + | NoDatum + deriving stock (Bounded, Enum) + +-- | Represent the validity property of the authority token UTxO. +data GATValidity + = GATValid + | WrongTag + | NoGAT + deriving stock (Bounded, Enum) + +data GovernorParameters = GovernorParameters + { governorOutputDatumValidity :: GovernorOutputDatumValidity + , stealGST :: Bool + -- ^ Send the GST to somewhere else other than the govenor validator. + } + +data MockEffectParameters = MockEffectParameters + { gatValidity :: GATValidity + , burnGAT :: Bool + -- ^ Whether to burn the GAT in the transaction or not. + } + +data ParameterBundle = ParameterBundle + { governorParameters :: GovernorParameters + , mockEffectParameters :: MockEffectParameters + } + +newtype Validity = Validity {forGovernorValidator :: Bool} + +-------------------------------------------------------------------------------- + +governorInputDatum :: GovernorDatum +governorInputDatum = + GovernorDatum + { proposalThresholds = def + , nextProposalId = ProposalId 0 + , proposalTimings = def + , createProposalTimeRangeMaxWidth = def + , maximumProposalsPerStake = 3 + } + +mkGovernorOutputDatum :: + GovernorOutputDatumValidity -> + Maybe Data +mkGovernorOutputDatum DatumValid = + Just $ + toData $ + governorInputDatum + { maximumProposalsPerStake = 4 + } +mkGovernorOutputDatum ValueInvalid = + let invalidProposalThresholds = + ProposalThresholds + { execute = -1 + , create = -1 + , vote = -1 + } + in Just $ + toData $ + governorInputDatum + { proposalThresholds = + invalidProposalThresholds + } +mkGovernorOutputDatum WrongType = Just $ toData () +mkGovernorOutputDatum NoDatum = Nothing + +governorRef :: TxOutRef +governorRef = + TxOutRef + "6cce6dfbb697f9e2c4fe9786bb576eb7bd6cbcf7801a4ba13d596006c2d5b957" + 1 + +governorRedeemer :: GovernorRedeemer +governorRedeemer = MutateGovernor + +mkGovernorBuilder :: forall b. CombinableBuilder b => GovernorParameters -> b +mkGovernorBuilder ps = + let gst = Value.assetClassValue govAssetClass 1 + value = sortValue $ gst <> minAda + gstOutput = + if ps.stealGST + then pubKey $ head pubKeyHashes + else script govValidatorHash + withGSTDatum = + maybe mempty withDatum $ + mkGovernorOutputDatum ps.governorOutputDatumValidity + in mconcat + [ input $ + mconcat + [ script govValidatorHash + , withDatum governorInputDatum + , withValue value + , withOutRef governorRef + ] + , output $ + mconcat + [ gstOutput + , withGSTDatum + , withValue value + ] + ] + +-------------------------------------------------------------------------------- + +mockEffectValidator :: ClosedTerm PValidator +mockEffectValidator = noOpValidator authorityTokenSymbol + +mockEffectValidatorHash :: ValidatorHash +mockEffectValidatorHash = validatorHash $ mkValidator def mockEffectValidator + +mkGATValue :: GATValidity -> Integer -> Value +mkGATValue NoGAT _ = mempty +mkGATValue v q = + let gatOwner = case v of + GATValid -> mockEffectValidatorHash + WrongTag -> head validatorHashes + in Value.singleton + authorityTokenSymbol + (validatorHashToTokenName gatOwner) + q + +mkMockEffectBuilder :: forall b. CombinableBuilder b => MockEffectParameters -> b +mkMockEffectBuilder ps = + let mkGATValue' = mkGATValue ps.gatValidity + inputValue = mkGATValue' 1 + outputValue = inputValue <> burnt + burnt = + if ps.burnGAT + then mkGATValue' (-1) + else mempty + in mconcat + [ mint burnt + , input $ + mconcat + [ script mockEffectValidatorHash + , withValue inputValue + ] + , output $ + mconcat + [ script mockEffectValidatorHash + , withValue outputValue + ] + ] + +-------------------------------------------------------------------------------- + +mutate :: forall b. CombinableBuilder b => ParameterBundle -> b +mutate pb = + mconcat + [ mkGovernorBuilder pb.governorParameters + , mkMockEffectBuilder pb.mockEffectParameters + ] + +-------------------------------------------------------------------------------- + +-- | Run the governor to test the mutation functionality. +mkTestCase :: String -> ParameterBundle -> Validity -> SpecificationTree +mkTestCase name pb (Validity forGov) = + testValidator + forGov + name + agoraScripts.compiledGovernorValidator + governorInputDatum + governorRedeemer + (mkSpending mutate pb governorRef) + +-------------------------------------------------------------------------------- + +-- | The only one valid combination of all the parameters. +totallyValidBundle :: ParameterBundle +totallyValidBundle = + ParameterBundle + { governorParameters = + GovernorParameters + { governorOutputDatumValidity = DatumValid + , stealGST = False + } + , mockEffectParameters = + MockEffectParameters + { gatValidity = GATValid + , burnGAT = True + } + } + +-------------------------------------------------------------------------------- + +{- | All the invalid combination of the parameters. + TODO: use 'Gen'? +-} +invalidBundles :: [ParameterBundle] +invalidBundles = do + gdv <- enumFrom ValueInvalid + sg <- [True, False] + gtv <- enumFrom WrongTag + bgt <- [True, False] + + pure $ + ParameterBundle + { governorParameters = + GovernorParameters + { governorOutputDatumValidity = gdv + , stealGST = sg + } + , mockEffectParameters = + MockEffectParameters + { gatValidity = gtv + , burnGAT = bgt + } + } diff --git a/agora-specs/Sample/Proposal.hs b/agora-specs/Sample/Proposal.hs deleted file mode 100644 index ac85e7f8..00000000 --- a/agora-specs/Sample/Proposal.hs +++ /dev/null @@ -1,815 +0,0 @@ -{- | -Module : Sample.Proposal -Maintainer : emi@haskell.fyi -Description: Sample based testing for Proposal utxos - -This module tests primarily the happy path for Proposal interactions --} -module Sample.Proposal ( - -- * Script contexts - proposalCreation, - cosignProposal, - proposalRef, - stakeRef, - voteOnProposal, - VotingParameters (..), - advanceProposalSuccess, - advanceProposalFailureTimeout, - TransitionParameters (..), - advanceFinishedProposal, - advanceProposalInsufficientVotes, - advanceProposalWithInvalidOutputStake, -) where - -import Agora.Governor (GovernorDatum (..)) -import Agora.Proposal ( - Proposal (..), - ProposalDatum (..), - ProposalId (..), - ProposalStatus (..), - ProposalThresholds (..), - ProposalVotes (..), - ResultTag (..), - emptyVotesFor, - ) -import Agora.Proposal.Time ( - ProposalStartingTime (ProposalStartingTime), - ProposalTimingConfig (..), - ) -import Agora.Stake ( - ProposalLock (ProposalLock), - Stake (..), - StakeDatum (..), - ) -import Data.Default.Class (Default (def)) -import Data.Tagged (Tagged (..), untag) -import Plutarch.Context ( - BaseBuilder, - MintingBuilder, - buildMintingUnsafe, - buildTxInfoUnsafe, - input, - mint, - output, - script, - signedWith, - timeRange, - txId, - withDatum, - withRefIndex, - withTxId, - withValue, - ) -import PlutusLedgerApi.V1 ( - Datum (Datum), - DatumHash, - POSIXTime, - POSIXTimeRange, - PubKeyHash, - ScriptContext (..), - ToData (toBuiltinData), - TxInInfo (TxInInfo), - TxInfo (..), - TxOut (TxOut, txOutAddress, txOutDatumHash, txOutValue), - TxOutRef (..), - ValidatorHash, - ) -import PlutusLedgerApi.V1.Value qualified as Value ( - assetClassValue, - singleton, - ) -import PlutusTx.AssocMap qualified as AssocMap -import Sample.Proposal.Shared (proposalRef, stakeRef) -import Sample.Shared ( - govValidatorHash, - minAda, - proposal, - proposalPolicySymbol, - proposalStartingTimeFromTimeRange, - proposalValidatorHash, - signer, - signer2, - stake, - stakeAddress, - stakeAssetClass, - stakeValidatorHash, - ) -import Test.Util ( - closedBoundedInterval, - datumPair, - toDatumHash, - updateMap, - ) - -proposalCreation :: ScriptContext -proposalCreation = - let st = Value.singleton proposalPolicySymbol "" 1 -- Proposal ST - effects = - AssocMap.fromList - [ (ResultTag 0, AssocMap.empty) - , (ResultTag 1, AssocMap.empty) - ] - proposalDatum :: ProposalDatum - proposalDatum = - ProposalDatum - { proposalId = ProposalId 0 - , effects = effects - , status = Draft - , cosigners = [signer] - , thresholds = def - , votes = emptyVotesFor effects - , timingConfig = def - , startingTime = proposalStartingTimeFromTimeRange validTimeRange - } - - govBefore :: GovernorDatum - govBefore = - GovernorDatum - { proposalThresholds = def - , nextProposalId = ProposalId 0 - , proposalTimings = def - , createProposalTimeRangeMaxWidth = def - } - - govAfter :: GovernorDatum - govAfter = govBefore {nextProposalId = ProposalId 1} - - validTimeRange = closedBoundedInterval 10 15 - - builder :: MintingBuilder - builder = - mconcat - [ txId "0b2086cbf8b6900f8cb65e012de4516cb66b5cb08a9aaba12a8b88be" - , signedWith signer - , mint st - , input $ - script govValidatorHash - . withValue (Value.assetClassValue proposal.governorSTAssetClass 1) - . withDatum govBefore - . withTxId "0b2086cbf8b6900f8cb65e012de4516cb66b5cb08a9aaba12a8b88be" - , output $ - script proposalValidatorHash - . withValue (st <> Value.singleton "" "" 10_000_000) - . withDatum proposalDatum - , output $ - script govValidatorHash - . withValue - ( Value.assetClassValue proposal.governorSTAssetClass 1 - <> Value.singleton "" "" 10_000_000 - ) - . withDatum govAfter - ] - in buildMintingUnsafe builder - --- | This script context should be a valid transaction. -cosignProposal :: [PubKeyHash] -> TxInfo -cosignProposal newSigners = - let st = Value.singleton proposalPolicySymbol "" 1 -- Proposal ST - effects = - AssocMap.fromList - [ (ResultTag 0, AssocMap.empty) - , (ResultTag 1, AssocMap.empty) - ] - proposalBefore :: ProposalDatum - proposalBefore = - ProposalDatum - { proposalId = ProposalId 0 - , effects = effects - , status = Draft - , cosigners = [signer] - , thresholds = def - , votes = emptyVotesFor effects - , timingConfig = def - , startingTime = ProposalStartingTime 0 - } - stakeDatum :: StakeDatum - stakeDatum = StakeDatum (Tagged 50_000_000) signer2 [] - proposalAfter :: ProposalDatum - proposalAfter = proposalBefore {cosigners = newSigners <> proposalBefore.cosigners} - validTimeRange :: POSIXTimeRange - validTimeRange = - closedBoundedInterval - 10 - ((def :: ProposalTimingConfig).draftTime - 10) - builder :: BaseBuilder - builder = - mconcat - [ txId "0b2086cbf8b6900f8cb65e012de4516cb66b5cb08a9aaba12a8b88be" - , mint st - , mconcat $ signedWith <$> newSigners - , timeRange validTimeRange - , input $ - script proposalValidatorHash - . withValue (st <> Value.singleton "" "" 10_000_000) - . withDatum proposalBefore - . withTxId (txOutRefId proposalRef) - . withRefIndex (txOutRefIdx proposalRef) - , input $ - script stakeValidatorHash - . withValue - ( Value.singleton "" "" 10_000_000 - <> Value.assetClassValue (untag stake.gtClassRef) 50_000_000 - <> Value.assetClassValue stakeAssetClass 1 - ) - . withDatum stakeDatum - . withTxId (txOutRefId stakeRef) - . withRefIndex (txOutRefIdx stakeRef) - , output $ - script proposalValidatorHash - . withValue (st <> Value.singleton "" "" 10_000_000) - . withDatum proposalAfter - , output $ - script stakeValidatorHash - . withValue - ( Value.singleton "" "" 10_000_000 - <> Value.assetClassValue (untag stake.gtClassRef) 50_000_000 - <> Value.assetClassValue stakeAssetClass 1 - ) - . withDatum stakeDatum - ] - in buildTxInfoUnsafe builder - --------------------------------------------------------------------------------- - --- | Parameters for creating a voting transaction. -data VotingParameters = VotingParameters - { voteFor :: ResultTag - -- ^ The outcome the transaction is voting for. - , voteCount :: Integer - -- ^ The count of votes. - } - --- | Create a valid transaction that votes on a propsal, given the parameters. -voteOnProposal :: VotingParameters -> TxInfo -voteOnProposal params = - let pst = Value.singleton proposalPolicySymbol "" 1 - sst = Value.assetClassValue stakeAssetClass 1 - - --- - - stakeOwner = signer - - --- - - effects = - AssocMap.fromList - [ (ResultTag 0, AssocMap.empty) - , (ResultTag 1, AssocMap.empty) - ] - - --- - - initialVotes :: AssocMap.Map ResultTag Integer - initialVotes = - AssocMap.fromList - [ (ResultTag 0, 42) - , (ResultTag 1, 4242) - ] - - --- - - proposalInputDatum :: ProposalDatum - proposalInputDatum = - ProposalDatum - { proposalId = ProposalId 42 - , effects = effects - , status = VotingReady - , cosigners = [stakeOwner] - , thresholds = def - , votes = ProposalVotes initialVotes - , timingConfig = def - , startingTime = ProposalStartingTime 0 - } - - --- - - existingLocks :: [ProposalLock] - existingLocks = - [ ProposalLock (ResultTag 0) (ProposalId 0) - , ProposalLock (ResultTag 2) (ProposalId 1) - ] - - --- - - stakeInputDatum :: StakeDatum - stakeInputDatum = - StakeDatum - { stakedAmount = Tagged params.voteCount - , owner = stakeOwner - , lockedBy = existingLocks - } - - --- - - updatedVotes :: AssocMap.Map ResultTag Integer - updatedVotes = updateMap (Just . (+ params.voteCount)) params.voteFor initialVotes - - --- - - proposalOutputDatum :: ProposalDatum - proposalOutputDatum = - proposalInputDatum - { votes = ProposalVotes updatedVotes - } - - --- - - -- Off-chain code should do exactly like this: prepend new lock toStatus the list. - updatedLocks :: [ProposalLock] - updatedLocks = ProposalLock params.voteFor proposalInputDatum.proposalId : existingLocks - - --- - - stakeOutputDatum :: StakeDatum - stakeOutputDatum = - stakeInputDatum - { lockedBy = updatedLocks - } - - --- - - validTimeRange = - closedBoundedInterval - ((def :: ProposalTimingConfig).draftTime + 1) - ((def :: ProposalTimingConfig).votingTime - 1) - - builder :: BaseBuilder - builder = - mconcat - [ txId "827598fb2d69a896bbd9e645bb14c307df907f422b39eecbe4d6329bc30b428c" - , signedWith stakeOwner - , timeRange validTimeRange - , input $ - script proposalValidatorHash - . withValue pst - . withDatum proposalInputDatum - . withTxId (txOutRefId proposalRef) - . withRefIndex (txOutRefIdx proposalRef) - , input $ - script stakeValidatorHash - . withValue - ( sst - <> Value.assetClassValue (untag stake.gtClassRef) params.voteCount - <> minAda - ) - . withDatum stakeInputDatum - . withTxId (txOutRefId stakeRef) - . withRefIndex (txOutRefIdx stakeRef) - , output $ - script proposalValidatorHash - . withValue pst - . withDatum proposalOutputDatum - , output $ - script stakeValidatorHash - . withValue - ( sst - <> Value.assetClassValue (untag stake.gtClassRef) params.voteCount - <> minAda - ) - . withDatum stakeOutputDatum - ] - in buildTxInfoUnsafe builder - --------------------------------------------------------------------------------- - --- | Parameters for state transition of proposals. -data TransitionParameters = TransitionParameters - { -- The initial status of the proposal. - initialProposalStatus :: ProposalStatus - , -- The starting time of the proposal. - proposalStartingTime :: ProposalStartingTime - } - --- | Create a 'TxInfo' that update the status of a proposal. -mkTransitionTxInfo :: - -- | Initial state of the proposal. - ProposalStatus -> - -- | Next state of the proposal. - ProposalStatus -> - -- | Effects. - AssocMap.Map ResultTag (AssocMap.Map ValidatorHash DatumHash) -> - -- | Votes. - ProposalVotes -> - -- | Starting time of the proposal. - ProposalStartingTime -> - -- | Valid time range of the transaction. - POSIXTimeRange -> - -- | Whether to add an unchanged stake or not. - Bool -> - TxInfo -mkTransitionTxInfo from to effects votes startingTime validTime shouldAddUnchangedStake = - let pst = Value.singleton proposalPolicySymbol "" 1 - sst = Value.assetClassValue stakeAssetClass 1 - - proposalInputDatum :: ProposalDatum - proposalInputDatum = - ProposalDatum - { proposalId = ProposalId 0 - , effects = effects - , status = from - , cosigners = [signer] - , thresholds = def - , votes = votes - , timingConfig = def - , startingTime = startingTime - } - - proposalOutputDatum :: ProposalDatum - proposalOutputDatum = - proposalInputDatum - { status = to - } - - stakeOwner = signer - stakedAmount = 200 - - existingLocks :: [ProposalLock] - existingLocks = - [ ProposalLock (ResultTag 0) (ProposalId 0) - , ProposalLock (ResultTag 2) (ProposalId 1) - ] - - stakeInputDatum :: StakeDatum - stakeInputDatum = - StakeDatum - { stakedAmount = Tagged stakedAmount - , owner = stakeOwner - , lockedBy = existingLocks - } - - stakeOutputDatum :: StakeDatum - stakeOutputDatum = stakeInputDatum - - stakeBuilder :: BaseBuilder - stakeBuilder = - if shouldAddUnchangedStake - then - mconcat - [ input $ - script stakeValidatorHash - . withValue sst - . withDatum stakeInputDatum - . withTxId (txOutRefId stakeRef) - , output $ - script stakeValidatorHash - . withValue (sst <> minAda) - . withDatum stakeOutputDatum - ] - else mempty - - builder :: BaseBuilder - builder = - mconcat - [ txId "95ba4015e30aef16a3461ea97a779f814aeea6b8009d99a94add4b8293be737a" - , signedWith stakeOwner - , timeRange validTime - , input $ - script proposalValidatorHash - . withValue pst - . withDatum proposalInputDatum - . withTxId (txOutRefId proposalRef) - , output $ - script proposalValidatorHash - . withValue (pst <> minAda) - . withDatum proposalOutputDatum - ] - in buildTxInfoUnsafe $ builder <> stakeBuilder - --- | Wrapper around 'advanceProposalSuccess'', with valid stake. -advanceProposalSuccess :: TransitionParameters -> TxInfo -advanceProposalSuccess ps = advanceProposalSuccess' ps True - -{- | Create a valid 'TxInfo' that advances a proposal, given the parameters. - The second parameter determines wherther valid stake should be included. - - Note that 'TransitionParameters.initialProposalStatus' should not be 'Finished'. --} -advanceProposalSuccess' :: TransitionParameters -> Bool -> TxInfo -advanceProposalSuccess' params = - let -- Status of the output proposal. - toStatus :: ProposalStatus - toStatus = case params.initialProposalStatus of - Draft -> VotingReady - VotingReady -> Locked - Locked -> Finished - Finished -> error "Cannot advance 'Finished' proposal" - - effects = - AssocMap.fromList - [ (ResultTag 0, AssocMap.empty) - , (ResultTag 1, AssocMap.empty) - ] - - emptyVotes@(ProposalVotes emptyVotes') = emptyVotesFor effects - - -- Set the vote count of outcome 0 to @def.countingVoting + 1@, - -- meaning that outcome 0 will be the winner. - outcome0WinningVotes = - ProposalVotes $ - updateMap - (\_ -> Just $ untag (def :: ProposalThresholds).execute + 1) - (ResultTag 0) - emptyVotes' - - votes :: ProposalVotes - votes = case params.initialProposalStatus of - Draft -> emptyVotes - -- With sufficient votes - _ -> outcome0WinningVotes - - proposalStartingTime :: POSIXTime - proposalStartingTime = - let (ProposalStartingTime startingTime) = params.proposalStartingTime - in startingTime - - timeRange :: POSIXTimeRange - timeRange = case params.initialProposalStatus of - -- [S + 1, S + D - 1] - Draft -> - closedBoundedInterval - (proposalStartingTime + 1) - (proposalStartingTime + (def :: ProposalTimingConfig).draftTime - 1) - -- [S + D + V + 1, S + D + V + L - 1] - VotingReady -> - closedBoundedInterval - ( proposalStartingTime - + (def :: ProposalTimingConfig).draftTime - + (def :: ProposalTimingConfig).votingTime - + 1 - ) - ( proposalStartingTime - + (def :: ProposalTimingConfig).draftTime - + (def :: ProposalTimingConfig).votingTime - + (def :: ProposalTimingConfig).lockingTime - - 1 - ) - -- [S + D + V + L + 1, S + + D + V + L + E - 1] - Locked -> - closedBoundedInterval - ( proposalStartingTime - + (def :: ProposalTimingConfig).draftTime - + (def :: ProposalTimingConfig).votingTime - + (def :: ProposalTimingConfig).lockingTime - + 1 - ) - ( proposalStartingTime - + (def :: ProposalTimingConfig).draftTime - + (def :: ProposalTimingConfig).votingTime - + (def :: ProposalTimingConfig).lockingTime - + (def :: ProposalTimingConfig).executingTime - 1 - ) - Finished -> error "Cannot advance 'Finished' proposal" - in mkTransitionTxInfo - params.initialProposalStatus - toStatus - effects - votes - params.proposalStartingTime - timeRange - -{- | Create a valid 'TxInfo' that advances a proposal to failed state, given the parameters. - The reason why the proposal fails is the proposal has ran out of time. - Note that 'TransitionParameters.initialProposalStatus' should not be 'Finished'. --} -advanceProposalFailureTimeout :: TransitionParameters -> TxInfo -advanceProposalFailureTimeout params = - let effects = - AssocMap.fromList - [ (ResultTag 0, AssocMap.empty) - , (ResultTag 1, AssocMap.empty) - ] - - emptyVotes@(ProposalVotes emptyVotes') = emptyVotesFor effects - - -- Set the vote count of outcome 0 to @def.countingVoting + 1@, - -- meaning that outcome 0 will be the winner. - outcome0WinningVotes = - ProposalVotes $ - updateMap - (\_ -> Just $ untag (def :: ProposalThresholds).vote + 1) - (ResultTag 0) - emptyVotes' - - votes :: ProposalVotes - votes = case params.initialProposalStatus of - Draft -> emptyVotes - -- With sufficient votes - _ -> outcome0WinningVotes - - proposalStartingTime :: POSIXTime - proposalStartingTime = - let (ProposalStartingTime startingTime) = params.proposalStartingTime - in startingTime - - timeRange :: POSIXTimeRange - timeRange = case params.initialProposalStatus of - -- [S + D + 1, S + D + V - 1] - Draft -> - closedBoundedInterval - (proposalStartingTime + (def :: ProposalTimingConfig).draftTime + 1) - ( proposalStartingTime - + (def :: ProposalTimingConfig).draftTime - + (def :: ProposalTimingConfig).votingTime - 1 - ) - -- [S + D + V + L + 1, S + D + V + L + E -1] - VotingReady -> - closedBoundedInterval - ( proposalStartingTime - + (def :: ProposalTimingConfig).draftTime - + (def :: ProposalTimingConfig).votingTime - + (def :: ProposalTimingConfig).lockingTime - + 1 - ) - ( proposalStartingTime - + (def :: ProposalTimingConfig).draftTime - + (def :: ProposalTimingConfig).votingTime - + (def :: ProposalTimingConfig).lockingTime - + (def :: ProposalTimingConfig).executingTime - - 1 - ) - -- [S + D + V + L + E + 1, S + D + V + L + E + 100] - Locked -> - closedBoundedInterval - ( proposalStartingTime - + (def :: ProposalTimingConfig).draftTime - + (def :: ProposalTimingConfig).votingTime - + (def :: ProposalTimingConfig).lockingTime - + (def :: ProposalTimingConfig).executingTime - + 1 - ) - ( proposalStartingTime - + (def :: ProposalTimingConfig).draftTime - + (def :: ProposalTimingConfig).votingTime - + (def :: ProposalTimingConfig).lockingTime - + (def :: ProposalTimingConfig).executingTime - + 100 - ) - Finished -> error "Cannot advance 'Finished' proposal" - in mkTransitionTxInfo - params.initialProposalStatus - Finished - effects - votes - params.proposalStartingTime - timeRange - True - --- | An invalid 'TxInfo' that tries to advance a 'VotingReady' proposal without sufficient votes. -advanceProposalInsufficientVotes :: TxInfo -advanceProposalInsufficientVotes = - let effects = - AssocMap.fromList - [ (ResultTag 0, AssocMap.empty) - , (ResultTag 1, AssocMap.empty) - ] - - -- Insufficient votes. - votes = - ProposalVotes - ( AssocMap.fromList - [ (ResultTag 0, 1) - , (ResultTag 1, 0) - ] - ) - - proposalStartingTime = 0 - - -- Valid time range. - -- [S + D + 1, S + V + 10] - timeRange = - closedBoundedInterval - ( proposalStartingTime - + (def :: ProposalTimingConfig).draftTime - + (def :: ProposalTimingConfig).votingTime - + 1 - ) - ( proposalStartingTime - + (def :: ProposalTimingConfig).draftTime - + (def :: ProposalTimingConfig).votingTime - + 10 - ) - in mkTransitionTxInfo - VotingReady - Locked - effects - votes - (ProposalStartingTime proposalStartingTime) - timeRange - True - --- | An invalid 'TxInfo' that tries to advance a 'Finished' proposal. -advanceFinishedProposal :: TxInfo -advanceFinishedProposal = - let effects = - AssocMap.fromList - [ (ResultTag 0, AssocMap.empty) - , (ResultTag 1, AssocMap.empty) - ] - - -- Set the vote count of outcome 0 to @def.countingVoting + 1@, - -- meaning that outcome 0 will be the winner. - outcome0WinningVotes = - ProposalVotes $ - AssocMap.fromList - [ (ResultTag 0, untag (def :: ProposalThresholds).vote + 1) - , (ResultTag 1, 0) - ] - - --- - - timeRange = - closedBoundedInterval - ((def :: ProposalTimingConfig).lockingTime + 1) - ((def :: ProposalTimingConfig).executingTime - 1) - in mkTransitionTxInfo - Finished - Finished - effects - outcome0WinningVotes - (ProposalStartingTime 0) - timeRange - True - -{- | An illegal 'TxInfo' that tries to output a changed stake with 'AdvanceProposal'. - From the perspective of stake validator, the transition is totally valid, - so the proposal validator should reject this. --} -advanceProposalWithInvalidOutputStake :: TxInfo -advanceProposalWithInvalidOutputStake = - let templateTxInfo = - advanceProposalSuccess' - TransitionParameters - { initialProposalStatus = VotingReady - , proposalStartingTime = ProposalStartingTime 0 - } - False - - --- - -- Now we create a new lock on an arbitrary stake - - sst = Value.assetClassValue stakeAssetClass 1 - - --- - - stakeOwner = signer - stakedAmount = 200 - - --- - - existingLocks :: [ProposalLock] - existingLocks = - [ ProposalLock (ResultTag 0) (ProposalId 0) - , ProposalLock (ResultTag 2) (ProposalId 1) - ] - - --- - - stakeInputDatum' :: StakeDatum - stakeInputDatum' = - StakeDatum - { stakedAmount = Tagged stakedAmount - , owner = stakeOwner - , lockedBy = existingLocks - } - stakeInputDatum :: Datum - stakeInputDatum = Datum $ toBuiltinData stakeInputDatum' - stakeInput :: TxOut - stakeInput = - TxOut - { txOutAddress = stakeAddress - , txOutValue = - mconcat - [ sst - , Value.assetClassValue (untag stake.gtClassRef) stakedAmount - , minAda - ] - , txOutDatumHash = Just $ toDatumHash stakeInputDatum - } - - --- - - updatedLocks :: [ProposalLock] - updatedLocks = ProposalLock (ResultTag 42) (ProposalId 27) : existingLocks - - --- - - stakeOutputDatum' :: StakeDatum - stakeOutputDatum' = - stakeInputDatum' - { lockedBy = updatedLocks - } - stakeOutputDatum :: Datum - stakeOutputDatum = Datum $ toBuiltinData stakeOutputDatum' - stakeOutput :: TxOut - stakeOutput = - stakeInput - { txOutDatumHash = Just $ toDatumHash stakeOutputDatum - } - in templateTxInfo - { txInfoInputs = TxInInfo stakeRef stakeInput : templateTxInfo.txInfoInputs - , txInfoOutputs = stakeOutput : templateTxInfo.txInfoOutputs - , txInfoData = - (datumPair <$> [stakeInputDatum, stakeOutputDatum]) - <> templateTxInfo.txInfoData - , txInfoSignatories = [stakeOwner] - } diff --git a/agora-specs/Sample/Proposal/Advance.hs b/agora-specs/Sample/Proposal/Advance.hs new file mode 100644 index 00000000..6e7a3f10 --- /dev/null +++ b/agora-specs/Sample/Proposal/Advance.hs @@ -0,0 +1,1083 @@ +{- | +Module : Sample.Proposal.Advance +Maintainer : connor@mlabs.city +Description: Generate sample data for testing the functionalities of advancing proposals + +Sample and utilities for testing the functionalities of advancing proposals. +-} +module Sample.Proposal.Advance ( + -- * Parameters + ParameterBundle (..), + GovernorParameters (..), + AuthorityTokenParameters (..), + ProposalParameters (..), + StakeParameters (..), + Winner (..), + + -- * Testing Utilities + Validity (..), + advance, + mkTestTree, + mkTestTree', + + -- * Parameter Bundles + mkValidToNextStateBundle, + mkValidToNextStateBundles, + mkValidToFailedStateBundles, + mkInsufficientVotesBundle, + mkAmbiguousWinnerBundle, + mkFromFinishedBundles, + mkInsufficientCosignsBundle, + mkToNextStateTooLateBundles, + mkInvalidOutputStakeBundles, + mkMintGATsForWrongEffectsBundle, + mkNoGATMintedBundle, + mkGATsWithWrongDatumBundle, + mkMintGATsWithoutTagBundle, + mkBadGovernorOutputDatumBundle, +) where + +import Agora.Governor ( + Governor (..), + GovernorDatum (..), + GovernorRedeemer (MintGATs), + ) +import Agora.Proposal ( + ProposalDatum (..), + ProposalId (ProposalId), + ProposalRedeemer (AdvanceProposal), + ProposalStatus (..), + ProposalThresholds (..), + ProposalVotes (ProposalVotes), + ResultTag (ResultTag), + emptyVotesFor, + ) +import Agora.Proposal.Time ( + ProposalStartingTime (ProposalStartingTime), + ProposalTimingConfig ( + draftTime, + executingTime, + lockingTime, + votingTime + ), + ) +import Agora.Scripts (AgoraScripts (..)) +import Agora.Stake ( + StakeDatum (..), + StakeRedeemer (WitnessStake), + ) +import Agora.Utils (validatorHashToTokenName) +import Control.Monad.State (execState, modify, when) +import Data.Default (def) +import Data.List (sort) +import Data.Maybe (catMaybes, fromJust) +import Data.Tagged (Tagged (..), untag) +import Plutarch.Context ( + input, + mint, + output, + script, + signedWith, + timeRange, + withDatum, + withOutRef, + withValue, + ) +import Plutarch.Lift (PLifted, PUnsafeLiftDecl) +import PlutusLedgerApi.V1 ( + DatumHash, + POSIXTime, + POSIXTimeRange, + PubKeyHash, + TxOutRef (TxOutRef), + ValidatorHash, + ) +import PlutusLedgerApi.V1.Value (AssetClass (..)) +import PlutusLedgerApi.V1.Value qualified as Value +import PlutusTx.AssocMap qualified as AssocMap +import Sample.Proposal.Shared ( + governorTxRef, + proposalTxRef, + stakeTxRef, + ) +import Sample.Shared ( + agoraScripts, + authorityTokenSymbol, + govAssetClass, + govValidatorHash, + governor, + minAda, + proposalPolicySymbol, + proposalValidatorHash, + signer, + stakeAssetClass, + stakeValidatorHash, + ) +import Test.Specification ( + SpecificationTree, + group, + testPolicy, + testValidator, + ) +import Test.Util ( + CombinableBuilder, + closedBoundedInterval, + datumHash, + groupsOfN, + mkMinting, + mkSpending, + pubKeyHashes, + sortValue, + toDatum, + updateMap, + validatorHashes, + ) + +{- | A bunch of parameters that control the generation of the transaction + context. +-} +data ParameterBundle = ParameterBundle + { proposalParameters :: ProposalParameters + -- ^ Parameters related to the the advancing proposal. + , stakeParameters :: StakeParameters + -- ^ Parameters related to stakes. + , governorParameters :: Maybe GovernorParameters + -- ^ Parameters related to GST moving. If set to 'Nothing', the GST won't + -- be moved, thus the governor validator won't be run in 'mkTestTree'. + , authorityTokenParameters :: Maybe AuthorityTokenParameters + -- ^ Parameters related to GAT minting. If set to 'Nothing', no GAT will + -- be minted, thus the GAT minting policy won't be run in 'mkTestTree'. + , transactionTimeRange :: POSIXTimeRange + -- ^ The value of 'TxInfo.txInfoValidRange', valid range of the generated + -- transaction. + , extraSignature :: Maybe PubKeyHash + -- ^ An extra signator. Intended to be used when + -- 'StakeParametersstakeParameters.transactionSignedByOwners' is set to + -- false. + } + +-- | Everything about the generated governor stuff. +newtype GovernorParameters = GovernorParameters + { invalidGovernorOutputDatum :: Bool + -- ^ The output governor datum will be changed. + } + +-- | Everything about the generated authority token stuff. +data AuthorityTokenParameters = forall + (datum :: Type) + (pdatum :: S -> Type). + ( PUnsafeLiftDecl pdatum + , PLifted pdatum ~ datum + , PIsData pdatum + ) => + AuthorityTokenParameters + { mintGATsFor :: [ValidatorHash] + -- ^ GATs will be minted and sent to the given group of effects. + , carryDatum :: Maybe datum + -- ^ The datum that GAT UTxOs will be carrying. + , invalidTokenName :: Bool + -- ^ If set to true, GATs won't be tagged by their corresponding effect + -- hashes. + } + +-- | Represent the winning effect group(s). +data Winner + = -- | Only one effect at the given index has the highest votes. + EffectAt Index + | -- | All the effects have the same highest votes. + All + +-- | Everything about the generated proposal stuff. +data ProposalParameters = ProposalParameters + { fromStatus :: ProposalStatus + -- ^ What status is the proposal advancing from + , toStatus :: ProposalStatus + -- ^ What status is the proposal advancing to + , effectList :: [AssocMap.Map ValidatorHash DatumHash] + -- ^ The effect groups of the proposal. A neutral effect group is not + -- required here. + , winnerAndVotes :: Maybe (Winner, Integer) + -- ^ Specify the effect group(s) that have the highest votes, and the value + -- of the highest votes. + , numCosigners :: NumStake + -- ^ The number of cosigners. + , invalidProposalOutputDatum :: Bool + -- ^ Whether to make the proposal output datum invalid or not. + } + +-- | Everything about the generated stake stuff. +data StakeParameters = StakeParameters + { numStake :: NumStake + , perStakeGTs :: Integer + , transactionSignedByOwners :: Bool + , invalidStakeOutputDatum :: Bool + } + +-- | Represent the number of stakes or the number of the cosigners. +type NumStake = Int + +-- | Represent an index. +type Index = Int + +{- | The validity of the generated transacrion for variuos componets. + 'True' means valid, 'False' means invalid. +-} +data Validity = Validity + { forProposalValidator :: Bool + , forStakeValidator :: Bool + , forGovernorValidator :: Maybe Bool + , forAuthorityTokenPolicy :: Maybe Bool + } + +-------------------------------------------------------------------------------- + +-- * Proposal + +-- | Mock cosigners. +mkCosigners :: NumStake -> [PubKeyHash] +mkCosigners = sort . flip take pubKeyHashes + +-- | Allocate the result tag for the effect at the given index. +outcomeIdxToResultTag :: Index -> ResultTag +outcomeIdxToResultTag = ResultTag . fromIntegral + +-- | Add a neutral effect group and allocate result tags for the effect groups. +mkEffects :: + ProposalParameters -> + AssocMap.Map ResultTag (AssocMap.Map ValidatorHash DatumHash) +mkEffects ps = + let resultTags = map ResultTag [0 ..] + neutralEffect = AssocMap.empty + finalEffects = ps.effectList <> [neutralEffect] + in AssocMap.fromList $ zip resultTags finalEffects + +-- | Set the votes of the winning group(s). +setWinner :: (Winner, Integer) -> ProposalVotes -> ProposalVotes +setWinner (All, votes) (ProposalVotes m) = + ProposalVotes $ AssocMap.mapMaybe (const $ Just votes) m +setWinner (EffectAt winnerIdx, votes) (ProposalVotes m) = + let winnerResultTag = outcomeIdxToResultTag winnerIdx + in ProposalVotes $ updateMap (const $ Just votes) winnerResultTag m + +-- | Mock votes for the proposal, given the parameters. +mkVotes :: + ProposalParameters -> + ProposalVotes +mkVotes ps = + let effects = mkEffects ps + emptyVotes = emptyVotesFor effects + in maybe emptyVotes (`setWinner` emptyVotes) (ps.winnerAndVotes) + +-- | The starting time of every generated proposal. +proposalStartingTime :: POSIXTime +proposalStartingTime = 0 + +-- | Create the input proposal datum given the parameters. +mkProposalInputDatum :: ProposalParameters -> ProposalDatum +mkProposalInputDatum ps = + let effects = mkEffects ps + votes = mkVotes ps + st = ProposalStartingTime proposalStartingTime + in ProposalDatum + { proposalId = ProposalId 0 + , effects = effects + , status = ps.fromStatus + , cosigners = mkCosigners ps.numCosigners + , thresholds = def + , votes = votes + , timingConfig = def + , startingTime = st + } + +-- | Create the output proposal datum given the parameters. +mkProposalOutputDatum :: ProposalParameters -> ProposalDatum +mkProposalOutputDatum ps = + let inputDatum = mkProposalInputDatum ps + outputCosigners = + if ps.invalidProposalOutputDatum + then [] + else inputDatum.cosigners + in inputDatum + { status = ps.toStatus + , cosigners = outputCosigners + } + +-- | Reference to the proposal UTXO. +proposalRef :: TxOutRef +proposalRef = TxOutRef proposalTxRef 1 + +{- | Create a context builder that contains all the information about the + input/output of the proposal validator, given the paramters. +-} +mkProposalBuilder :: forall b. CombinableBuilder b => ProposalParameters -> b +mkProposalBuilder ps = + let pst = Value.singleton proposalPolicySymbol "" 1 + value = sortValue $ minAda <> pst + in mconcat + [ input $ + mconcat + [ script proposalValidatorHash + , withOutRef proposalRef + , withDatum (mkProposalInputDatum ps) + , withValue value + ] + , output $ + mconcat + [ script proposalValidatorHash + , withDatum (mkProposalOutputDatum ps) + , withValue value + ] + ] + +{- | The proposal redeemer used to spend the proposal UTXO, which is always + 'AdvanceProposal' in this case. +-} +proposalRedeemer :: ProposalRedeemer +proposalRedeemer = AdvanceProposal + +-------------------------------------------------------------------------------- + +-- * Stake + +-- Mock owners of the stakes. +mkStakeOwners :: NumStake -> [PubKeyHash] +mkStakeOwners = mkCosigners + +-- | Create the input stake datums given the parameters. +mkStakeInputDatums :: StakeParameters -> [StakeDatum] +mkStakeInputDatums ps = + let template = + StakeDatum + { stakedAmount = Tagged ps.perStakeGTs + , owner = "" + , delegatedTo = Nothing + , lockedBy = [] + } + in (\owner -> template {owner = owner}) + <$> mkStakeOwners ps.numStake + +-- | Create the output stake datums given the parameters. +mkStakeOutputDatums :: StakeParameters -> [StakeDatum] +mkStakeOutputDatums ps = + let inputDatums = mkStakeInputDatums ps + outputStakedAmount = + Tagged $ + if ps.invalidStakeOutputDatum + then ps.perStakeGTs * 10 + else ps.perStakeGTs + modify inp = inp {stakedAmount = outputStakedAmount} + in modify <$> inputDatums + +{- | Get the input stake datum given the index. The range of the index is + @[0, 'StakeParameters.numStake - 1']@ +-} +getStakeInputDatumAt :: StakeParameters -> Index -> StakeDatum +getStakeInputDatumAt ps = (!!) (mkStakeInputDatums ps) + +-- | Create the reference to a particular stake UTXO. +mkStakeRef :: Index -> TxOutRef +mkStakeRef = TxOutRef stakeTxRef . (+ 3) . fromIntegral + +{- | Create a context builder that contains all the inputs/outputs of the + stake validator. +-} +mkStakeBuilder :: forall b. CombinableBuilder b => StakeParameters -> b +mkStakeBuilder ps = + let perStakeValue = + sortValue $ + minAda + <> Value.assetClassValue stakeAssetClass 1 + <> Value.assetClassValue + (untag governor.gtClassRef) + ps.perStakeGTs + perStake idx i o = + let withSig = + if ps.transactionSignedByOwners + then signedWith i.owner + else mempty + in mconcat + [ withSig + , input $ + mconcat + [ script stakeValidatorHash + , withOutRef (mkStakeRef idx) + , withValue perStakeValue + , withDatum i + ] + , output $ + mconcat + [ script stakeValidatorHash + , withValue perStakeValue + , withDatum o + ] + ] + in mconcat $ + zipWith3 + perStake + [0 :: Index ..] + (mkStakeInputDatums ps) + (mkStakeOutputDatums ps) + +{- | The proposal redeemer used to spend the stake UTXO, which is always + 'WitnessStake' in this case. +-} +stakeRedeemer :: StakeRedeemer +stakeRedeemer = WitnessStake + +-------------------------------------------------------------------------------- + +-- * Governor + +-- | The input governor datum. +governorInputDatum :: GovernorDatum +governorInputDatum = + GovernorDatum + { proposalThresholds = def + , nextProposalId = ProposalId 42 + , proposalTimings = def + , createProposalTimeRangeMaxWidth = def + , maximumProposalsPerStake = 3 + } + +-- | Create the output governor datum given the parameters. +mkGovernorOutputDatum :: GovernorParameters -> GovernorDatum +mkGovernorOutputDatum ps = + if ps.invalidGovernorOutputDatum + then governorInputDatum {maximumProposalsPerStake = 15} + else governorInputDatum + +-- | Reference to the governor UTXO. +governorRef :: TxOutRef +governorRef = TxOutRef governorTxRef 2 + +{- | Create a context builder that contains the input and the output of the + governor validator. +-} +mkGovernorBuilder :: forall b. CombinableBuilder b => GovernorParameters -> b +mkGovernorBuilder ps = + let gst = Value.assetClassValue govAssetClass 1 + value = sortValue $ gst <> minAda + in mconcat + [ input $ + mconcat + [ script govValidatorHash + , withValue value + , withOutRef governorRef + , withDatum governorInputDatum + ] + , output $ + mconcat + [ script govValidatorHash + , withValue value + , withOutRef governorRef + , withDatum (mkGovernorOutputDatum ps) + ] + ] + +{- | The proposal redeemer used to spend the governor UTXO, which is always + 'MintGATs' in this case. +-} +governorRedeemer :: GovernorRedeemer +governorRedeemer = MintGATs + +-------------------------------------------------------------------------------- + +-- * Authority Token + +{- | Create a context builder that contains the infomation about the minted + authority tokens and where they're sent to. +-} +mkAuthorityTokenBuilder :: + forall b. + CombinableBuilder b => + AuthorityTokenParameters -> + b +mkAuthorityTokenBuilder (AuthorityTokenParameters es mdt invalidTokenName) = + foldMap perEffect es + where + perEffect :: ValidatorHash -> b + perEffect vh = + let tn = + if invalidTokenName + then "" + else validatorHashToTokenName vh + ac = AssetClass (authorityTokenSymbol, tn) + minted = Value.assetClassValue ac 1 + value = sortValue $ minAda <> minted + in mconcat + [ mint minted + , output $ + mconcat + [ script vh + , maybe mempty withDatum mdt + , withValue value + ] + ] + +-- | The redeemer used while running the authority token policy. +authorityTokenRedeemer :: () +authorityTokenRedeemer = () + +-------------------------------------------------------------------------------- + +-- | Create a 'TxInfo' that update the status of a proposal. +advance :: + forall b. + CombinableBuilder b => + ParameterBundle -> + b +advance pb = + let mkBuilderMaybe = maybe mempty + in mconcat + [ mkProposalBuilder pb.proposalParameters + , mkStakeBuilder pb.stakeParameters + , mkBuilderMaybe mkGovernorBuilder pb.governorParameters + , mkBuilderMaybe mkAuthorityTokenBuilder pb.authorityTokenParameters + , timeRange pb.transactionTimeRange + , maybe mempty signedWith pb.extraSignature + ] + +-------------------------------------------------------------------------------- + +{- | Create a test tree that runs the relavant componets to test the advancing + functionalities. +-} +mkTestTree :: + String -> + ParameterBundle -> + Validity -> + SpecificationTree +mkTestTree name pb val = + group name $ catMaybes [proposal, stake, governor, authority] + where + spend = mkSpending advance pb + mint = mkMinting advance pb + + proposal = + let proposalInputDatum = mkProposalInputDatum pb.proposalParameters + in Just $ + testValidator + val.forProposalValidator + "proposal" + agoraScripts.compiledProposalValidator + proposalInputDatum + proposalRedeemer + (spend proposalRef) + + stake = + let idx = 0 + in Just $ + testValidator + val.forStakeValidator + "stake" + agoraScripts.compiledStakeValidator + (getStakeInputDatumAt pb.stakeParameters idx) + stakeRedeemer + ( spend (mkStakeRef idx) + ) + + governor = + testValidator + (fromJust val.forGovernorValidator) + "governor" + agoraScripts.compiledGovernorValidator + governorInputDatum + governorRedeemer + (spend governorRef) + <$ pb.governorParameters + + authority = + testPolicy + (fromJust val.forAuthorityTokenPolicy) + "authority" + agoraScripts.compiledAuthorityTokenPolicy + authorityTokenRedeemer + (mint authorityTokenSymbol) + <$ (pb.authorityTokenParameters) + +{- | Create a test tree that runs a bunch of parameter bundles. These bundles + should have the same validity. +-} +mkTestTree' :: + String -> + (ParameterBundle -> String) -> + [ParameterBundle] -> + Validity -> + SpecificationTree +mkTestTree' groupName mkCaseName bundles val = + group groupName $ + (\b -> mkTestTree (mkCaseName b) b val) + <$> bundles + +-------------------------------------------------------------------------------- + +-- Utilities for creating parameter bundles + +{- | Given the proposal status, create a time range that is in time for + advacing to the next state. +-} +mkInTimeTimeRange :: ProposalStatus -> POSIXTimeRange +mkInTimeTimeRange advanceFrom = + case advanceFrom of + -- [S + 1, S + D - 1] + Draft -> + closedBoundedInterval + (proposalStartingTime + 1) + (proposalStartingTime + (def :: ProposalTimingConfig).draftTime - 1) + -- [S + D + V + 1, S + D + V + L - 1] + VotingReady -> + closedBoundedInterval + ( proposalStartingTime + + (def :: ProposalTimingConfig).draftTime + + (def :: ProposalTimingConfig).votingTime + + 1 + ) + ( proposalStartingTime + + (def :: ProposalTimingConfig).draftTime + + (def :: ProposalTimingConfig).votingTime + + (def :: ProposalTimingConfig).lockingTime + - 1 + ) + -- [S + D + V + L + 1, S + + D + V + L + E - 1] + Locked -> + closedBoundedInterval + ( proposalStartingTime + + (def :: ProposalTimingConfig).draftTime + + (def :: ProposalTimingConfig).votingTime + + (def :: ProposalTimingConfig).lockingTime + + 1 + ) + ( proposalStartingTime + + (def :: ProposalTimingConfig).draftTime + + (def :: ProposalTimingConfig).votingTime + + (def :: ProposalTimingConfig).lockingTime + + (def :: ProposalTimingConfig).executingTime - 1 + ) + Finished -> error "Cannot advance 'Finished' proposal" + +{- | Given the proposal status, create a time range that is too time for + advacing to the next state. +-} +mkTooLateTimeRange :: ProposalStatus -> POSIXTimeRange +mkTooLateTimeRange advanceFrom = + case advanceFrom of + -- [S + D + 1, S + D + V - 1] + Draft -> + closedBoundedInterval + (proposalStartingTime + (def :: ProposalTimingConfig).draftTime + 1) + ( proposalStartingTime + + (def :: ProposalTimingConfig).draftTime + + (def :: ProposalTimingConfig).votingTime - 1 + ) + -- [S + D + V + L + 1, S + D + V + L + E -1] + VotingReady -> + closedBoundedInterval + ( proposalStartingTime + + (def :: ProposalTimingConfig).draftTime + + (def :: ProposalTimingConfig).votingTime + + (def :: ProposalTimingConfig).lockingTime + + 1 + ) + ( proposalStartingTime + + (def :: ProposalTimingConfig).draftTime + + (def :: ProposalTimingConfig).votingTime + + (def :: ProposalTimingConfig).lockingTime + + (def :: ProposalTimingConfig).executingTime + - 1 + ) + -- [S + D + V + L + E + 1, S + D + V + L + E + 100] + Locked -> + closedBoundedInterval + ( proposalStartingTime + + (def :: ProposalTimingConfig).draftTime + + (def :: ProposalTimingConfig).votingTime + + (def :: ProposalTimingConfig).lockingTime + + (def :: ProposalTimingConfig).executingTime + + 1 + ) + ( proposalStartingTime + + (def :: ProposalTimingConfig).draftTime + + (def :: ProposalTimingConfig).votingTime + + (def :: ProposalTimingConfig).lockingTime + + (def :: ProposalTimingConfig).executingTime + + 100 + ) + Finished -> error "Cannot advance 'Finished' proposal" + +-- | Next state of the given proposal status. +getNextState :: ProposalStatus -> ProposalStatus +getNextState = \case + Draft -> VotingReady + VotingReady -> Locked + Locked -> Finished + Finished -> error "Cannot advance 'Finished' proposal" + +-- | Calculate the number of GTs per stake in order to exceed the minimum limit. +compPerStakeGTsForDraft :: NumStake -> Integer +compPerStakeGTsForDraft nCosigners = + untag (def :: ProposalThresholds).vote + `div` fromIntegral nCosigners + 1 + +dummyDatum :: () +dummyDatum = () + +dummyDatumHash :: DatumHash +dummyDatumHash = datumHash $ toDatum dummyDatum + +-- | Create given number of effect groups. Each group will have 3 effects. +mkMockEffects :: Int -> [AssocMap.Map ValidatorHash DatumHash] +mkMockEffects = + flip + take + ( AssocMap.fromList + . flip zip (repeat dummyDatumHash) + <$> groupsOfN 3 validatorHashes + ) + +numberOfVotesThatExceedsTheMinimumRequirement :: Integer +numberOfVotesThatExceedsTheMinimumRequirement = + untag (def @ProposalThresholds).execute + 1 + +mkWinnerVotes :: Index -> (Winner, Integer) +mkWinnerVotes idx = + ( EffectAt idx + , numberOfVotesThatExceedsTheMinimumRequirement + ) + +ambiguousWinnerVotes :: (Winner, Integer) +ambiguousWinnerVotes = + ( All + , numberOfVotesThatExceedsTheMinimumRequirement + ) + +-------------------------------------------------------------------------------- + +-- * Parameter Bundles + +--- + +-- * Legal + +defaultWinnerIdx :: Index +defaultWinnerIdx = 0 + +{- | Advance a proposal to the next state, perfectly valid for all the + componets. +-} +mkValidToNextStateBundle :: + -- | Number of cosigners. + Word -> + -- | Number of effects + Word -> + -- | The initial proposal state, should not be 'Finished'. + ProposalStatus -> + ParameterBundle +mkValidToNextStateBundle _ _ Finished = + error "Cannot advance from Finished" +mkValidToNextStateBundle nCosigners nEffects from = + let next = getNextState from + effects = mkMockEffects $ fromIntegral nEffects + winner = defaultWinnerIdx + + template = + ParameterBundle + { proposalParameters = + ProposalParameters + { fromStatus = from + , toStatus = next + , effectList = effects + , winnerAndVotes = Nothing + , numCosigners = fromIntegral nCosigners + , invalidProposalOutputDatum = False + } + , stakeParameters = + StakeParameters + { numStake = 1 + , perStakeGTs = + compPerStakeGTsForDraft $ + fromIntegral nCosigners + , transactionSignedByOwners = False + , invalidStakeOutputDatum = False + } + , governorParameters = Nothing + , authorityTokenParameters = Nothing + , transactionTimeRange = mkInTimeTimeRange from + , extraSignature = Just signer + } + + -- This is my favourite part of the test suite, lol. + modifyTemplate = do + when (from == Draft) $ + modify $ \b -> + b + { stakeParameters = + b.stakeParameters + { transactionSignedByOwners = True + , numStake = fromIntegral nCosigners + } + , extraSignature = Nothing + } + + when (from == VotingReady || from == Locked) $ + modify $ \b -> + b + { proposalParameters = + b.proposalParameters + { winnerAndVotes = Just $ mkWinnerVotes winner + } + } + + when (from == Locked) $ + modify $ \b -> + let aut = + AuthorityTokenParameters + { mintGATsFor = AssocMap.keys $ effects !! winner + , carryDatum = Just dummyDatum + , invalidTokenName = False + } + gov = + GovernorParameters + { invalidGovernorOutputDatum = False + } + in b + { governorParameters = Just gov + , authorityTokenParameters = Just aut + } + in execState modifyTemplate template + +mkValidToNextStateBundles :: + -- | Number of cosigners + Word -> + -- | Number of effects + Word -> + [ParameterBundle] +mkValidToNextStateBundles nCosigners nEffects = + mkValidToNextStateBundle nCosigners nEffects + <$> [ Draft + , VotingReady + , Locked + ] + +mkValidToFailedStateBundles :: + -- | Number of cosigners + Word -> + -- | Number of effects + Word -> + [ParameterBundle] +mkValidToFailedStateBundles nCosigners nEffects = + mkBundle + <$> [ Draft + , VotingReady + , Locked + ] + where + mkBundle from = + let next = Finished + effects = mkMockEffects $ fromIntegral nEffects + in ParameterBundle + { proposalParameters = + ProposalParameters + { fromStatus = from + , toStatus = next + , effectList = effects + , winnerAndVotes = Nothing + , numCosigners = fromIntegral nCosigners + , invalidProposalOutputDatum = False + } + , stakeParameters = + StakeParameters + { numStake = 1 + , perStakeGTs = + compPerStakeGTsForDraft $ + fromIntegral nCosigners + , transactionSignedByOwners = False + , invalidStakeOutputDatum = False + } + , governorParameters = Nothing + , authorityTokenParameters = Nothing + , transactionTimeRange = mkTooLateTimeRange from + , extraSignature = Just signer + } + +-- * Illegal + +mkFromFinishedBundles :: + -- | Number of cosigners + Word -> + -- | Number of effects + Word -> + [ParameterBundle] +mkFromFinishedBundles nCosigners nEffects = + mkBundle + <$> [ Draft + , VotingReady + , Locked + ] + where + mkBundle from = + let template = mkValidToNextStateBundle nCosigners nEffects from + in template + { proposalParameters = + template.proposalParameters + { fromStatus = Finished + , toStatus = Finished + } + } + +mkToNextStateTooLateBundles :: Word -> Word -> [ParameterBundle] +mkToNextStateTooLateBundles nCosigners nEffects = + mkBundle + <$> [ Draft + , VotingReady + , Locked + ] + where + mkBundle from = + let template = mkValidToNextStateBundle nCosigners nEffects from + in template + { transactionTimeRange = mkTooLateTimeRange from + } + +mkInvalidOutputStakeBundles :: Word -> Word -> [ParameterBundle] +mkInvalidOutputStakeBundles nCosigners nEffects = + mkBundle <$> [Draft, VotingReady, Locked] + where + mkBundle from = + let template = mkValidToNextStateBundle nCosigners nEffects from + in template + { stakeParameters = + template.stakeParameters + { invalidStakeOutputDatum = True + } + } + +-- * From Draft + +mkInsufficientCosignsBundle :: Word -> Word -> ParameterBundle +mkInsufficientCosignsBundle nCosigners nEffects = + template + { stakeParameters = + template.stakeParameters + { perStakeGTs = insuffcientPerStakeGTs + } + } + where + insuffcientPerStakeGTs = + untag (def :: ProposalThresholds).vote + `div` fromIntegral nCosigners - 1 + template = mkValidToNextStateBundle nCosigners nEffects Draft + +-- * From VotingReady + +setWinnerAndVotes :: + ParameterBundle -> + Maybe (Winner, Integer) -> + ParameterBundle +setWinnerAndVotes pb wv = + pb + { proposalParameters = + pb.proposalParameters + { winnerAndVotes = wv + } + } + +mkInsufficientVotesBundle :: + Word -> + Word -> + ParameterBundle +mkInsufficientVotesBundle nCosigners nEffects = + mkValidToNextStateBundle nCosigners nEffects VotingReady + `setWinnerAndVotes` Nothing + +mkAmbiguousWinnerBundle :: + Word -> + Word -> + ParameterBundle +mkAmbiguousWinnerBundle nCosigners nEffects = + mkValidToNextStateBundle nCosigners nEffects VotingReady + `setWinnerAndVotes` Just ambiguousWinnerVotes + +-- * From Locked + +mkValidFromLockedBundle :: Word -> Word -> ParameterBundle +mkValidFromLockedBundle nCosigners nEffects = + mkValidToNextStateBundle nCosigners nEffects Locked + +mkMintGATsForWrongEffectsBundle :: + Word -> + Word -> + ParameterBundle +mkMintGATsForWrongEffectsBundle nCosigners nEffects = + template + { authorityTokenParameters = + ( \aut -> + aut + { mintGATsFor = + [ validatorHashes !! 1 + , validatorHashes !! 3 + , validatorHashes !! 5 + , validatorHashes !! 7 + ] + } + ) + <$> template.authorityTokenParameters + } + where + template = mkValidFromLockedBundle nCosigners nEffects + +mkNoGATMintedBundle :: + Word -> + Word -> + ParameterBundle +mkNoGATMintedBundle nCosigners nEffects = + template + { authorityTokenParameters = Nothing + } + where + template = mkValidFromLockedBundle nCosigners nEffects + +mkMintGATsWithoutTagBundle :: + Word -> + Word -> + ParameterBundle +mkMintGATsWithoutTagBundle nCosigners nEffects = + template + { authorityTokenParameters = + ( \aut -> + aut + { invalidTokenName = True + } + ) + <$> template.authorityTokenParameters + } + where + template = mkValidFromLockedBundle nCosigners nEffects + +mkGATsWithWrongDatumBundle :: + Word -> + Word -> + ParameterBundle +mkGATsWithWrongDatumBundle nCosigners nEffects = + template + { authorityTokenParameters = Just newAut + } + where + template = mkValidFromLockedBundle nCosigners nEffects + aut = fromJust template.authorityTokenParameters + newAut = + AuthorityTokenParameters + aut.mintGATsFor + (Just (1 :: Integer)) + False + +mkBadGovernorOutputDatumBundle :: + Word -> + Word -> + ParameterBundle +mkBadGovernorOutputDatumBundle nCosigners nEffects = + template + { governorParameters = Just gov + } + where + template = mkValidFromLockedBundle nCosigners nEffects + gov = GovernorParameters True diff --git a/agora-specs/Sample/Proposal/Cosign.hs b/agora-specs/Sample/Proposal/Cosign.hs new file mode 100644 index 00000000..09f0b67f --- /dev/null +++ b/agora-specs/Sample/Proposal/Cosign.hs @@ -0,0 +1,339 @@ +{- | +Module : Sample.Proposal.Cosign +Maintainer : connor@mlabs.city +Description: Generate sample data for testing the functionalities of cosigning proposals + +Sample and utilities for testing the functionalities of cosigning proposals. +-} +module Sample.Proposal.Cosign ( + Parameters (..), + validCosignNParameters, + duplicateCosignersParameters, + statusNotDraftCosignNParameters, + invalidStakeOutputParameters, + mkTestTree, +) where + +import Agora.Governor (Governor (..)) +import Agora.Proposal ( + ProposalDatum (..), + ProposalId (ProposalId), + ProposalRedeemer (Cosign), + ProposalStatus (..), + ResultTag (ResultTag), + emptyVotesFor, + ) +import Agora.Proposal.Time ( + ProposalStartingTime (ProposalStartingTime), + ProposalTimingConfig (draftTime), + ) +import Agora.SafeMoney (GTTag) +import Agora.Scripts (AgoraScripts (..)) +import Agora.Stake ( + StakeDatum (StakeDatum, owner), + StakeRedeemer (WitnessStake), + stakedAmount, + ) +import Data.Coerce (coerce) +import Data.Default (def) +import Data.List (sort) +import Data.Tagged (Tagged, untag) +import Plutarch.Context ( + input, + output, + script, + signedWith, + timeRange, + txId, + withDatum, + withOutRef, + withTxId, + withValue, + ) +import PlutusLedgerApi.V1 ( + POSIXTimeRange, + PubKeyHash, + TxOutRef (..), + Value, + ) +import PlutusLedgerApi.V1.Value qualified as Value +import PlutusTx.AssocMap qualified as AssocMap +import Sample.Proposal.Shared (proposalTxRef, stakeTxRef) +import Sample.Shared ( + agoraScripts, + governor, + minAda, + proposalPolicySymbol, + proposalValidatorHash, + signer, + stakeAssetClass, + stakeValidatorHash, + ) +import Test.Specification ( + SpecificationTree, + group, + testValidator, + ) +import Test.Util (CombinableBuilder, closedBoundedInterval, mkSpending, pubKeyHashes, sortValue) + +-- | Parameters for cosigning a proposal. +data Parameters = Parameters + { newCosigners :: [PubKeyHash] + -- ^ New cosigners to be added, and the owners of the generated stakes. + , proposalStatus :: ProposalStatus + -- ^ Current state of the proposal. + , alterOutputStakes :: Bool + -- ^ Whether to generate invalid stake outputs. + -- In particular, the 'stakedAmount' of all the stake datums will be set to zero. + } + +-- | Owner of the creator stake, doesn't really matter in this case. +proposalCreator :: PubKeyHash +proposalCreator = signer + +-- | The amount of GTs every generated stake has, doesn't really matter in this case. +perStakedGTs :: Tagged GTTag Integer +perStakedGTs = 5 + +{- | Create input proposal datum given the parameters. + In particular, 'status' is set to 'proposalStstus'. +-} +mkProposalInputDatum :: Parameters -> ProposalDatum +mkProposalInputDatum ps = + let effects = + AssocMap.fromList + [ (ResultTag 0, AssocMap.empty) + , (ResultTag 1, AssocMap.empty) + ] + in ProposalDatum + { proposalId = ProposalId 0 + , effects = effects + , status = ps.proposalStatus + , cosigners = [proposalCreator] + , thresholds = def + , votes = emptyVotesFor effects + , timingConfig = def + , startingTime = ProposalStartingTime 0 + } + +{- | Create the output proposal datum given the parameters. + The 'newCosigners' is added to the exisiting list of cosigners, note the said list should be sorted in + ascending order. +-} +mkProposalOutputDatum :: Parameters -> ProposalDatum +mkProposalOutputDatum ps = + let inputDatum = mkProposalInputDatum ps + in inputDatum + { cosigners = sort $ inputDatum.cosigners <> ps.newCosigners + } + +-- | Create all the input stakes given the parameters. +mkStakeInputDatums :: Parameters -> [StakeDatum] +mkStakeInputDatums = fmap (\pk -> StakeDatum perStakedGTs pk Nothing []) . newCosigners + +-- | Create a 'TxInfo' that tries to cosign a proposal with new cosigners. +cosign :: forall b. CombinableBuilder b => Parameters -> b +cosign ps = builder + where + pst = Value.singleton proposalPolicySymbol "" 1 + sst = Value.assetClassValue stakeAssetClass 1 + + --- + + stakeInputDatums :: [StakeDatum] + stakeInputDatums = mkStakeInputDatums ps + + stakeValue :: Value + stakeValue = + sortValue $ + minAda + <> Value.assetClassValue + (untag governor.gtClassRef) + (untag perStakedGTs) + <> sst + + stakeBuilder = + foldMap + ( \(stakeDatum, refIdx) -> + let stakeOutputDatum = + if ps.alterOutputStakes + then stakeDatum {stakedAmount = 0} + else stakeDatum + in mconcat + [ input $ + mconcat + [ script stakeValidatorHash + , withValue stakeValue + , withDatum stakeDatum + , withTxId stakeTxRef + , withOutRef (mkStakeRef refIdx) + ] + , output $ + mconcat + [ script stakeValidatorHash + , withValue stakeValue + , withDatum stakeOutputDatum + ] + , signedWith stakeDatum.owner + ] + ) + $ zip + stakeInputDatums + [0 ..] + + --- + + proposalInputDatum :: ProposalDatum + proposalInputDatum = mkProposalInputDatum ps + + proposalOutputDatum :: ProposalDatum + proposalOutputDatum = mkProposalOutputDatum ps + + proposalBuilder = + mconcat + [ input $ + mconcat + [ script proposalValidatorHash + , withValue pst + , withDatum proposalInputDatum + , withTxId proposalTxRef + , withOutRef proposalRef + ] + , output $ + mconcat + [ script proposalValidatorHash + , withValue (sortValue (pst <> minAda)) + , withDatum proposalOutputDatum + ] + ] + + validTimeRange :: POSIXTimeRange + validTimeRange = + closedBoundedInterval + (coerce proposalInputDatum.startingTime + 1) + ( coerce proposalInputDatum.startingTime + + proposalInputDatum.timingConfig.draftTime - 1 + ) + + --- + + builder = + mconcat + [ txId "05c67819fc3381a2052b929ab439244b7b5fe3b3bd07f2134055bbbb21bd9e52" + , timeRange validTimeRange + , proposalBuilder + , stakeBuilder + ] + +-- | Reference index of the proposal UTXO. +proposalRefIdx :: Integer +proposalRefIdx = 1 + +-- | Spend the proposal ST. +proposalRef :: TxOutRef +proposalRef = TxOutRef proposalTxRef proposalRefIdx + +-- | Consume the given stake. +mkStakeRef :: Int -> TxOutRef +mkStakeRef idx = + TxOutRef + stakeTxRef + $ proposalRefIdx + 1 + fromIntegral idx + +-- | Create a proposal redeemer which cosigns with the new cosginers. +mkProposalRedeemer :: Parameters -> ProposalRedeemer +mkProposalRedeemer (sort . newCosigners -> cs) = Cosign cs + +-- | Stake redeemer for cosuming all the stakes generated in the module. +stakeRedeemer :: StakeRedeemer +stakeRedeemer = WitnessStake + +--- + +-- | Create a valid parameters that cosign the proposal with a given number of cosigners. +validCosignNParameters :: Int -> Parameters +validCosignNParameters n + | n > 0 = + Parameters + { newCosigners = take n pubKeyHashes + , proposalStatus = Draft + , alterOutputStakes = False + } + | otherwise = error "Number of cosigners should be positive" + +--- + +{- | Parameters that make 'cosign' yield duplicate cosigners. + Invalid for the ptoposal validator, perfectly valid for stake validator. +-} +duplicateCosignersParameters :: Parameters +duplicateCosignersParameters = + Parameters + { newCosigners = [proposalCreator] + , proposalStatus = Draft + , alterOutputStakes = False + } + +--- + +{- | Generate a list of parameters that sets proposal status to something other than 'Draft'. + Invalid for the ptoposal validator, perfectly valid for stake validator. +-} +statusNotDraftCosignNParameters :: Int -> [Parameters] +statusNotDraftCosignNParameters n = + map + ( \st -> + Parameters + { newCosigners = take n pubKeyHashes + , proposalStatus = st + , alterOutputStakes = False + } + ) + [VotingReady, Locked, Finished] + +--- + +{- | Parameters thet change the output stake datums. + Invalid for both proposal validator and stake validator. +-} +invalidStakeOutputParameters :: Parameters +invalidStakeOutputParameters = + (validCosignNParameters 2) + { alterOutputStakes = True + } + +--- + +-- | Create a test tree given the parameters. Both the proposal validator and stake validator will be run. +mkTestTree :: + -- | The name of the test group. + String -> + Parameters -> + -- | Are the parameters valid for the proposal validator? + Bool -> + SpecificationTree +mkTestTree name ps isValid = group name [proposal, stake] + where + spend = mkSpending cosign ps + + proposal = + let proposalInputDatum = mkProposalInputDatum ps + in testValidator + isValid + "proposal" + agoraScripts.compiledProposalValidator + proposalInputDatum + (mkProposalRedeemer ps) + (spend proposalRef) + + stake = + let idx = 0 + stakeInputDatum = mkStakeInputDatums ps !! idx + isValid = not ps.alterOutputStakes + in testValidator + isValid + "stake" + agoraScripts.compiledStakeValidator + stakeInputDatum + stakeRedeemer + (spend $ mkStakeRef idx) diff --git a/agora-specs/Sample/Proposal/Create.hs b/agora-specs/Sample/Proposal/Create.hs new file mode 100644 index 00000000..af356fb9 --- /dev/null +++ b/agora-specs/Sample/Proposal/Create.hs @@ -0,0 +1,458 @@ +{- | +Module : Sample.Proposal.Create +Maintainer : connor@mlabs.city +Description: Generate sample data for testing the functionalities of creating proposals + +Sample and utilities for testing the functionalities of creating proposals. +-} +module Sample.Proposal.Create ( + Parameters (..), + mkTestTree, + totallyValidParameters, + invalidOutputGovernorDatumParameters, + useStakeOwnBySomeoneElseParameters, + invalidOutputStakeParameters, + addInvalidLocksParameters, + exceedMaximumProposalsParameters, + timeRangeNotTightParameters, + timeRangeNotClosedParameters, + invalidProposalStatusParameters, +) where + +import Agora.Governor ( + Governor (..), + GovernorDatum (..), + GovernorRedeemer (CreateProposal), + ) +import Agora.Proposal ( + ProposalDatum (..), + ProposalId (ProposalId), + ProposalStatus (..), + ResultTag (ResultTag), + emptyVotesFor, + ) +import Agora.Proposal.Time (MaxTimeRangeWidth (MaxTimeRangeWidth), ProposalStartingTime (..)) +import Agora.Scripts (AgoraScripts (..)) +import Agora.Stake ( + ProposalLock (..), + StakeDatum (..), + StakeRedeemer (PermitVote), + ) +import Data.Coerce (coerce) +import Data.Default (Default (def)) +import Data.Tagged (Tagged, untag) +import Plutarch.Context ( + input, + mint, + output, + script, + signedWith, + timeRange, + txId, + withDatum, + withOutRef, + withValue, + ) +import PlutusLedgerApi.V1 ( + DatumHash, + POSIXTime (POSIXTime), + POSIXTimeRange, + PubKeyHash, + TxOutRef (TxOutRef), + ValidatorHash, + always, + ) +import PlutusLedgerApi.V1.Value qualified as Value +import PlutusTx.AssocMap qualified as AssocMap +import Sample.Proposal.Shared (stakeTxRef) +import Sample.Shared ( + agoraScripts, + govAssetClass, + govValidatorHash, + governor, + minAda, + proposalPolicySymbol, + proposalStartingTimeFromTimeRange, + proposalValidatorHash, + signer, + signer2, + stakeAssetClass, + stakeValidatorHash, + ) +import Test.Specification (SpecificationTree, group, testPolicy, testValidator) +import Test.Util (CombinableBuilder, closedBoundedInterval, mkMinting, mkSpending, sortValue) + +-- | Parameters for creating a proposal. +data Parameters = Parameters + { advanceNextProposalId :: Bool + -- ^ Whether to advance 'GovernorDatum.nextProposalId'. + , createdMoreThanMaximumProposals :: Bool + -- ^ Try creating more than maximum amount of proposals. + , stakeOwnerSignsTheTransaction :: Bool + -- ^ Should the stake owner sign the transaction? + , invalidNewLocks :: Bool + -- ^ Place invalid new locks on the output stake. + , alterOutputStakeOwner :: Bool + -- ^ Whether to change the 'owner' field of the output stake datum. + , timeRangeTightEnough :: Bool + -- ^ Is 'TxInfo.validTimeRange' tight enough? + , timeRangeClosed :: Bool + -- ^ Is 'TxInfo.validTimeRange' closed? + , proposalStatus :: ProposalStatus + -- ^ The status of the newly created proposal. + } + +-------------------------------------------------------------------------------- + +-- | See 'GovernorDatum.maximumProposalsPerStake'. +maxProposalPerStake :: Integer +maxProposalPerStake = 3 + +-- | The id of the proposal we are creating. +thisProposalId :: ProposalId +thisProposalId = ProposalId 25 + +-- | The arbitrary staked amount. Doesn;t really matter in this case. +stakedGTs :: Tagged _ Integer +stakedGTs = 5 + +-- | The owner of the stake. +stakeOwner :: PubKeyHash +stakeOwner = signer + +{- | The invalid stake owner. If the 'alterOutputStakeOwner' is set to true, + the output stake owner will be set to this. +-} +alteredStakeOwner :: PubKeyHash +alteredStakeOwner = signer2 + +-- | Locks the stake that the input stake already has. +defLocks :: [ProposalLock] +defLocks = [Created (ProposalId 0)] + +-- | The effect of the newly created proposal. +defEffects :: AssocMap.Map ResultTag (AssocMap.Map ValidatorHash DatumHash) +defEffects = + AssocMap.fromList + [ (ResultTag 0, AssocMap.empty) + , (ResultTag 1, AssocMap.empty) + ] + +-------------------------------------------------------------------------------- + +-- | The governor input datum. +governorInputDatum :: GovernorDatum +governorInputDatum = + GovernorDatum + { proposalThresholds = def + , nextProposalId = thisProposalId + , proposalTimings = def + , createProposalTimeRangeMaxWidth = def + , maximumProposalsPerStake = maxProposalPerStake + } + +-- | Create governor output datum given the parameters. +mkGovernorOutputDatum :: Parameters -> GovernorDatum +mkGovernorOutputDatum ps = + let nextPid = + if ps.advanceNextProposalId + then ProposalId $ coerce thisProposalId + 1 + else thisProposalId + in GovernorDatum + { proposalThresholds = def + , nextProposalId = nextPid + , proposalTimings = def + , createProposalTimeRangeMaxWidth = def + , maximumProposalsPerStake = maxProposalPerStake + } + +-------------------------------------------------------------------------------- + +-- | Create the stake input datum given the parameters. +mkStakeInputDatum :: Parameters -> StakeDatum +mkStakeInputDatum ps = + let locks = + if ps.createdMoreThanMaximumProposals + then + Created . ProposalId + <$> take + (fromInteger maxProposalPerStake) + [1 ..] + else defLocks + in StakeDatum + { stakedAmount = stakedGTs + , owner = stakeOwner + , delegatedTo = Nothing + , lockedBy = locks + } + +-- | Create the stake output datum given the parameters. +mkStakeOutputDatum :: Parameters -> StakeDatum +mkStakeOutputDatum ps = + let inputDatum = mkStakeInputDatum ps + newLocks = + if ps.invalidNewLocks + then + [ Voted thisProposalId (ResultTag 0) + , Voted thisProposalId (ResultTag 1) + ] + else [Created thisProposalId] + locks = newLocks <> inputDatum.lockedBy + newOwner = mkOwner ps + in inputDatum + { owner = newOwner + , lockedBy = locks + } + +-------------------------------------------------------------------------------- + +{- | Create the proposal datum for the newly created proposal, given the + parameters. +-} +mkProposalOutputDatum :: Parameters -> ProposalDatum +mkProposalOutputDatum ps = + ProposalDatum + { proposalId = thisProposalId + , effects = defEffects + , status = ps.proposalStatus + , cosigners = [mkOwner ps] + , thresholds = def + , votes = emptyVotesFor defEffects + , timingConfig = def + , startingTime = mkProposalStartingTime ps + } + +-------------------------------------------------------------------------------- + +-- | Create time range for 'TxInfo.validTimeRange'. +mkTimeRange :: Parameters -> POSIXTimeRange +mkTimeRange ps = + if ps.timeRangeClosed + then + let s = 0 + di :: POSIXTime = coerce (def @MaxTimeRangeWidth) + o = if ps.timeRangeTightEnough then (-1) else 1 + in closedBoundedInterval s $ o + di + else always + +-- | Get the starting time of the proposal. +mkProposalStartingTime :: Parameters -> ProposalStartingTime +mkProposalStartingTime ps = + if ps.timeRangeClosed + then proposalStartingTimeFromTimeRange $ mkTimeRange ps + else ProposalStartingTime 0 + +-- | Who should be the 'owner' of the output stake. +mkOwner :: Parameters -> PubKeyHash +mkOwner ps = + if ps.alterOutputStakeOwner + then alteredStakeOwner + else stakeOwner + +-------------------------------------------------------------------------------- + +-- | Reference to the input stake UTXO. +stakeRef :: TxOutRef +stakeRef = TxOutRef stakeTxRef 1 + +-- | Reference to the input governor UTXO. +governorRef :: TxOutRef +governorRef = TxOutRef "0b2086cbf8b6900f8cb65e012de4516cb66b5cb08a9aaba12a8b88be" 3 + +-------------------------------------------------------------------------------- + +-- | Create a 'TxInfo' that spends a stake to create a new proposal. +createProposal :: forall b. CombinableBuilder b => Parameters -> b +createProposal ps = builder + where + pst = Value.singleton proposalPolicySymbol "" 1 + sst = Value.assetClassValue stakeAssetClass 1 + gst = Value.assetClassValue govAssetClass 1 + + --- + + governorValue = sortValue $ gst <> minAda + stakeValue = + sortValue $ + sortValue $ + sst + <> Value.assetClassValue (untag governor.gtClassRef) (untag stakedGTs) + <> minAda + proposalValue = sortValue $ pst <> minAda + + --- + + withSig = + if ps.stakeOwnerSignsTheTransaction + then signedWith stakeOwner + else mempty + + --- + + builder = + mconcat + [ txId "0b2086cbf8b6900f8cb65e012de4516cb66b5cb08a9aaba12a8b88be" + , --- + withSig + , --- + mint pst + , --- + timeRange $ mkTimeRange ps + , input $ + mconcat + [ script govValidatorHash + , withValue governorValue + , withDatum governorInputDatum + , withOutRef governorRef + ] + , output $ + mconcat + [ script govValidatorHash + , withValue governorValue + , withDatum (mkGovernorOutputDatum ps) + ] + , --- + input $ + mconcat + [ script stakeValidatorHash + , withValue stakeValue + , withDatum (mkStakeInputDatum ps) + , withOutRef stakeRef + ] + , output $ + mconcat + [ script stakeValidatorHash + , withValue stakeValue + , withDatum (mkStakeOutputDatum ps) + ] + , --- + output $ + mconcat + [ script proposalValidatorHash + , withValue proposalValue + , withDatum (mkProposalOutputDatum ps) + ] + ] + +-------------------------------------------------------------------------------- + +-- | Spend the stake with the 'PermitVote' redeemer. +stakeRedeemer :: StakeRedeemer +stakeRedeemer = PermitVote + +-- | Spend the governor with the 'CreateProposal' redeemer. +governorRedeemer :: GovernorRedeemer +governorRedeemer = CreateProposal + +-- | Mint the PST with an arbitrary redeemer. Doesn't really matter. +proposalPolicyRedeemer :: () +proposalPolicyRedeemer = () + +-------------------------------------------------------------------------------- + +totallyValidParameters :: Parameters +totallyValidParameters = + Parameters + { advanceNextProposalId = True + , createdMoreThanMaximumProposals = False + , stakeOwnerSignsTheTransaction = True + , invalidNewLocks = False + , alterOutputStakeOwner = False + , timeRangeTightEnough = True + , timeRangeClosed = True + , proposalStatus = Draft + } + +invalidOutputGovernorDatumParameters :: Parameters +invalidOutputGovernorDatumParameters = + totallyValidParameters + { advanceNextProposalId = False + } + +useStakeOwnBySomeoneElseParameters :: Parameters +useStakeOwnBySomeoneElseParameters = + totallyValidParameters + { stakeOwnerSignsTheTransaction = False + } + +invalidOutputStakeParameters :: Parameters +invalidOutputStakeParameters = + totallyValidParameters + { alterOutputStakeOwner = True + } + +addInvalidLocksParameters :: Parameters +addInvalidLocksParameters = + totallyValidParameters + { invalidNewLocks = True + } + +exceedMaximumProposalsParameters :: Parameters +exceedMaximumProposalsParameters = + totallyValidParameters + { createdMoreThanMaximumProposals = True + } + +timeRangeNotTightParameters :: Parameters +timeRangeNotTightParameters = + totallyValidParameters + { timeRangeTightEnough = False + } + +timeRangeNotClosedParameters :: Parameters +timeRangeNotClosedParameters = + totallyValidParameters + { timeRangeClosed = False + } + +invalidProposalStatusParameters :: [Parameters] +invalidProposalStatusParameters = + map + ( \st -> + totallyValidParameters {proposalStatus = st} + ) + [VotingReady, Locked, Finished] + +-------------------------------------------------------------------------------- + +{- | Create a test tree that runs the proposal minting policy, the governor + validator and the stake validator to test the functionalities of creting + proposals +-} +mkTestTree :: String -> Parameters -> Bool -> Bool -> Bool -> SpecificationTree +mkTestTree + name + ps + validForProposalPolicy + validForGovernorValidator + validForStakeValidator = + group name [proposalTest, governorTest, stakeTest] + where + mint = mkMinting createProposal ps + spend = mkSpending createProposal ps + + proposalTest = + testPolicy + validForProposalPolicy + "proposal" + agoraScripts.compiledProposalPolicy + proposalPolicyRedeemer + (mint proposalPolicySymbol) + + governorTest = + testValidator + validForGovernorValidator + "governor" + agoraScripts.compiledGovernorValidator + governorInputDatum + governorRedeemer + (spend governorRef) + + stakeTest = + testValidator + validForStakeValidator + "stake" + agoraScripts.compiledStakeValidator + (mkStakeInputDatum ps) + stakeRedeemer + (spend stakeRef) diff --git a/agora-specs/Sample/Proposal/Shared.hs b/agora-specs/Sample/Proposal/Shared.hs index 1a2ee64e..c73f1c9c 100644 --- a/agora-specs/Sample/Proposal/Shared.hs +++ b/agora-specs/Sample/Proposal/Shared.hs @@ -1,9 +1,21 @@ -module Sample.Proposal.Shared (proposalRef, stakeRef) where +{- | +Module : Sample.Proposal.Shared +Maintainer : connor@mlabs.city +Description: Shared constants for proposal samples -import PlutusLedgerApi.V1 (TxOutRef (..)) +Shared constants for proposal samples. +-} +module Sample.Proposal.Shared (proposalTxRef, stakeTxRef, governorTxRef) where -proposalRef :: TxOutRef -proposalRef = TxOutRef "0b2086cbf8b6900f8cb65e012de4516cb66b5cb08a9aaba12a8b88be" 1 +import PlutusLedgerApi.V1 (TxId) -stakeRef :: TxOutRef -stakeRef = TxOutRef "0ca36f3a357bc69579ab2531aecd1e7d3714d993c7820f40b864be15" 0 +-- | 'TxId' of all the proposal inputs in the samples. +proposalTxRef :: TxId +proposalTxRef = "0b2086cbf8b6900f8cb65e012de4516cb66b5cb08a9aaba12a8b88be" + +-- | 'TxId' of all the stake inputs in the samples. +stakeTxRef :: TxId +stakeTxRef = "0ca36f3a357bc69579ab2531aecd1e7d3714d993c7820f40b864be15" + +governorTxRef :: TxId +governorTxRef = "cb076140e80d240f9c89e478aedbddbe6f4734fecbd0ae3e37404c12e7798c0f" diff --git a/agora-specs/Sample/Proposal/UnlockStake.hs b/agora-specs/Sample/Proposal/UnlockStake.hs index d8ac3964..5e72125a 100644 --- a/agora-specs/Sample/Proposal/UnlockStake.hs +++ b/agora-specs/Sample/Proposal/UnlockStake.hs @@ -1,29 +1,31 @@ +{- | +Module : Sample.Proposal.UnlockStake +Maintainer : connor@mlabs.city +Description: Generate sample data for testing the functionalities of unlocking stake and retracting votes + +Sample and utilities for testing the functionalities of unlocking stake and retracting votes +-} module Sample.Proposal.UnlockStake ( - unlockStake, StakeRole (..), - UnlockStakeParameters (..), - votesTemplate, - emptyEffectFor, - mkProposalInputDatum, - mkStakeInputDatum, - mkProposalValidatorTestCase, + Parameters (..), + unlockStake, + mkTestTree, + mkVoterRetractVotesWhileVotingParameters, + mkVoterCreatorRetractVotesWhileVotingParameters, + mkCreatorRemoveCreatorLocksWhenFinishedParameters, + mkVoterCreatorRemoveAllLocksWhenFinishedParameters, + mkVoterUnlockStakeAfterVotingParameters, + mkVoterCreatorRemoveVoteLocksWhenLockedParameters, + mkRetractVotesWhileNotVoting, + mkUnockIrrelevantStakeParameters, + mkRemoveCreatorLockBeforeFinishedParameters, + mkRetractVotesWithCreatorStakeParamaters, + mkAlterStakeParameters, ) where -------------------------------------------------------------------------------- -import PlutusLedgerApi.V1 ( - DatumHash, - ScriptContext (..), - ScriptPurpose (Spending), - TxInfo (..), - TxOutRef (..), - ValidatorHash, - ) -import PlutusLedgerApi.V1.Value qualified as Value -import PlutusTx.AssocMap qualified as AssocMap - --------------------------------------------------------------------------------- - +import Agora.Governor (Governor (..)) import Agora.Proposal ( ProposalDatum (..), ProposalId (..), @@ -33,29 +35,41 @@ import Agora.Proposal ( ResultTag (..), ) import Agora.Proposal.Time (ProposalStartingTime (ProposalStartingTime)) -import Agora.Stake (ProposalLock (ProposalLock), Stake (..), StakeDatum (..)) +import Agora.Scripts (AgoraScripts (..)) +import Agora.Stake (ProposalLock (..), StakeDatum (..), StakeRedeemer (RetractVotes)) +import Data.Default.Class (Default (def)) +import Data.Tagged (Tagged (..), untag) +import Plutarch.Context ( + input, + output, + script, + signedWith, + txId, + withDatum, + withOutRef, + withValue, + ) +import PlutusLedgerApi.V1 ( + DatumHash, + PubKeyHash, + TxOutRef (..), + ValidatorHash, + ) +import PlutusLedgerApi.V1.Value qualified as Value +import PlutusTx.AssocMap qualified as AssocMap +import Sample.Proposal.Shared (stakeTxRef) import Sample.Shared ( + agoraScripts, + governor, minAda, proposalPolicySymbol, proposalValidatorHash, signer, - stake, stakeAssetClass, stakeValidatorHash, ) -import Test.Util (sortValue, updateMap) - --------------------------------------------------------------------------------- - -import Agora.Proposal.Scripts (proposalValidator) -import Control.Monad (join) -import Data.Coerce (coerce) -import Data.Default.Class (Default (def)) -import Data.Tagged (Tagged (..), untag) -import Plutarch.Context (BaseBuilder, buildTxInfoUnsafe, input, output, script, txId, withDatum, withRefIndex, withTxId, withValue) -import Sample.Proposal.Shared (proposalRef, stakeRef) -import Sample.Shared qualified as Shared -import Test.Specification (SpecificationTree, validatorFailsWith, validatorSucceedsWith) +import Test.Specification (SpecificationTree, group, testValidator) +import Test.Util (CombinableBuilder, mkSpending, sortValue, updateMap) -------------------------------------------------------------------------------- @@ -77,106 +91,131 @@ emptyEffectFor (ProposalVotes vs) = map (,AssocMap.empty) (AssocMap.keys vs) -- | The default vote option that will be used by functions in this module. -defaultVoteFor :: ResultTag -defaultVoteFor = ResultTag 0 +defVoteFor :: ResultTag +defVoteFor = ResultTag 0 -- | The default number of GTs the stake will have. -defaultStakedGTs :: Tagged _ Integer -defaultStakedGTs = Tagged 100000 +defStakedGTs :: Tagged _ Integer +defStakedGTs = 100000 + +{- | If 'Parameters.alterOutputStake' is set to true, the + 'StakeDatum.stakedAmount' will be set to this. +-} +alteredStakedGTs :: Tagged _ Integer +alteredStakedGTs = 100 + +-- | Default owner of the stakes. +defOwner :: PubKeyHash +defOwner = signer -- | How a stake has been used on a particular proposal. data StakeRole = -- | The stake was spent to vote for a paraticular option. Voter - | -- | The stake was used to created the proposal. + | -- | The stake was used to create the proposal. Creator + | -- | The stake was used to both create and vote for the proposal. + Both | -- | The stake has nothing to do with the proposal. Irrelevant + deriving stock (Bounded, Enum, Show) -- | Parameters for creating a 'TxOut' that unlocks a stake. -data UnlockStakeParameters = UnlockStakeParameters +data Parameters = Parameters { proposalCount :: Integer -- ^ The number of proposals in the 'TxOut'. - , stakeUsage :: StakeRole + , stakeRole :: StakeRole -- ^ The role of the stake we're unlocking. , retractVotes :: Bool -- ^ Whether to retract votes or not. + , removeVoterLock :: Bool + -- ^ Remove the voter locks from the input stake. + , removeCreatorLock :: Bool + -- ^ Remove the creator locks from the input stake. , proposalStatus :: ProposalStatus -- ^ The state of all the proposals. + , alterOutputStake :: Bool } -instance Show UnlockStakeParameters where - show p = - let role = case p.stakeUsage of - Voter -> "voter" - Creator -> "creator" - _ -> "irrelevant stake" - - action = - if p.retractVotes - then "unlock stake + retract votes" - else "unlock stake" - - while = show p.proposalStatus - - proposalInfo = mconcat [show p.proposalCount, " proposals"] - in mconcat [proposalInfo, ", ", role, ", ", action, ", ", while] - --- | Generate some input proposals and their corresponding output proposals. -mkProposals :: UnlockStakeParameters -> [(ProposalDatum, ProposalDatum)] -mkProposals p = forEachProposalId p.proposalCount $ mkProposalDatumPair p - -- | Iterate over the proposal id of every proposal, given the number of proposals. -forEachProposalId :: Integer -> (ProposalId -> a) -> [a] -forEachProposalId 0 _ = error "zero proposal" -forEachProposalId n f = f . ProposalId <$> [0 .. n - 1] - --- | Create the input stake and its corresponding output stake. -mkStakeDatumPair :: UnlockStakeParameters -> (StakeDatum, StakeDatum) -mkStakeDatumPair c = - let output = - StakeDatum - { stakedAmount = defaultStakedGTs - , owner = signer - , lockedBy = [] - } - - inputLocks = join $ forEachProposalId c.proposalCount (mkStakeLocks c.stakeUsage) +forEachProposalId :: Parameters -> (ProposalId -> a) -> [a] +forEachProposalId ps = forEachProposalId' ps.proposalCount + where + forEachProposalId' :: Integer -> (ProposalId -> a) -> [a] + forEachProposalId' 0 _ = error "zero proposal" + forEachProposalId' n f = f . ProposalId <$> [0 .. n - 1] - input = output {lockedBy = inputLocks} - in (input, output) +-- | Create locks for the input stake given the parameters. +mkInputStakeLocks :: Parameters -> [ProposalLock] +mkInputStakeLocks ps = mconcat $ forEachProposalId ps $ mkStakeLocksFor ps.stakeRole where - mkStakeLocks :: StakeRole -> ProposalId -> [ProposalLock] - mkStakeLocks Voter pid = [ProposalLock defaultVoteFor pid] - mkStakeLocks Creator pid = - map (`ProposalLock` pid) $ - AssocMap.keys $ getProposalVotes votesTemplate - mkStakeLocks _ _ = [] + mkStakeLocksFor :: StakeRole -> ProposalId -> [ProposalLock] + mkStakeLocksFor sr pid = + let voted = [Voted pid defVoteFor] + created = [Created pid] + in case sr of + Voter -> voted + Creator -> created + Both -> voted <> created + _ -> [] + +-- | Create locks for the output stake by removing locks from the input locks. +mkOutputStakeLocks :: Parameters -> [ProposalLock] +mkOutputStakeLocks ps = + filter + ( \lock -> not $ case lock of + Voted _ _ -> ps.removeVoterLock + Created _ -> ps.removeCreatorLock + ) + inputLocks + where + inputLocks = mkInputStakeLocks ps + +-- | Create the stake input datum given the parameters. +mkStakeInputDatum :: Parameters -> StakeDatum +mkStakeInputDatum ps = + StakeDatum + { stakedAmount = defStakedGTs + , owner = defOwner + , delegatedTo = Nothing + , lockedBy = mkInputStakeLocks ps + } + +-- | Create stake output datum given the parameters. +mkStakeOutputDatum :: Parameters -> StakeDatum +mkStakeOutputDatum ps = + let template = mkStakeInputDatum ps + stakedAmount' = + if ps.alterOutputStake + then alteredStakedGTs + else defStakedGTs + in template + { stakedAmount = stakedAmount' + , lockedBy = mkOutputStakeLocks ps + } + +-- | Generate some input proposals and their corresponding output proposals. +mkProposals :: Parameters -> [(ProposalDatum, ProposalDatum)] +mkProposals ps = forEachProposalId ps $ mkProposalDatumPair ps -- | Create the input proposal datum. -mkProposalInputDatum :: UnlockStakeParameters -> ProposalId -> ProposalDatum +mkProposalInputDatum :: Parameters -> ProposalId -> ProposalDatum mkProposalInputDatum p pid = fst $ mkProposalDatumPair p pid --- | Create the input stake datum. -mkStakeInputDatum :: UnlockStakeParameters -> StakeDatum -mkStakeInputDatum = fst . mkStakeDatumPair - -- | Create a input proposal and its corresponding output proposal. mkProposalDatumPair :: - UnlockStakeParameters -> + Parameters -> ProposalId -> (ProposalDatum, ProposalDatum) mkProposalDatumPair params pid = - let owner = signer - - inputVotes = mkInputVotes params.stakeUsage $ untag defaultStakedGTs + let inputVotes = mkInputVotes params.stakeRole $ untag defStakedGTs input = ProposalDatum { proposalId = pid , effects = emptyEffectFor votesTemplate , status = params.proposalStatus - , cosigners = [owner] + , cosigners = [defOwner] , thresholds = def , votes = inputVotes , timingConfig = def @@ -195,82 +234,317 @@ mkProposalDatumPair params pid = -- The staked amount/votes. Integer -> ProposalVotes - mkInputVotes Voter vc = + mkInputVotes Creator _ = ProposalVotes $ - updateMap (Just . const vc) defaultVoteFor $ + updateMap (Just . const 1000) defVoteFor $ getProposalVotes votesTemplate - mkInputVotes Creator _ = + mkInputVotes Irrelevant _ = votesTemplate + mkInputVotes _ vc = ProposalVotes $ - updateMap (Just . const 1000) defaultVoteFor $ + updateMap (Just . const vc) defVoteFor $ getProposalVotes votesTemplate - mkInputVotes _ _ = votesTemplate -- | Create a 'TxInfo' that tries to unlock a stake. -unlockStake :: UnlockStakeParameters -> TxInfo -unlockStake p = +unlockStake :: forall b. CombinableBuilder b => Parameters -> b +unlockStake ps = let pst = Value.singleton proposalPolicySymbol "" 1 sst = Value.assetClassValue stakeAssetClass 1 - pIODatums = mkProposals p - (sInDatum, sOutDatum) = mkStakeDatumPair p + pIODatums = mkProposals ps proposals = foldMap - ( \(i, o) -> + ( \((i, o), idx) -> mconcat - @BaseBuilder [ input $ - script proposalValidatorHash - . withValue pst - . withDatum i - . withTxId (txOutRefId proposalRef) - . withRefIndex (txOutRefIdx proposalRef + coerce i.proposalId) + mconcat + [ script proposalValidatorHash + , withValue pst + , withDatum i + , withOutRef (mkProposalRef idx) + ] , output $ - script proposalValidatorHash - . withValue (sortValue $ pst <> minAda) - . withDatum o + mconcat + [ script proposalValidatorHash + , withValue (sortValue $ pst <> minAda) + , withDatum o + ] ] ) - pIODatums + (zip pIODatums [0 ..]) stakeValue = sortValue $ mconcat [ Value.assetClassValue - (untag stake.gtClassRef) - (untag defaultStakedGTs) + (untag governor.gtClassRef) + (untag defStakedGTs) , sst , minAda ] + sInDatum = mkStakeInputDatum ps + sOutDatum = mkStakeOutputDatum ps + stakes = - mconcat @BaseBuilder + mconcat [ input $ - script stakeValidatorHash - . withValue stakeValue - . withDatum sInDatum - . withTxId (txOutRefId stakeRef) - . withRefIndex (txOutRefIdx stakeRef) + mconcat + [ script stakeValidatorHash + , withValue stakeValue + , withDatum sInDatum + , withOutRef stakeRef + ] , output $ - script stakeValidatorHash - . withValue stakeValue - . withDatum sOutDatum + mconcat + [ script stakeValidatorHash + , withValue stakeValue + , withDatum sOutDatum + ] ] builder = - mconcat @BaseBuilder + mconcat [ txId "388bc0b897b3dadcd479da4c88291de4113a50b72ddbed001faf7fc03f11bc52" , proposals , stakes + , signedWith defOwner ] - in buildTxInfoUnsafe builder - --- | Create a test case that tests the proposal validator's @'Unlock' _@ redeemer. -mkProposalValidatorTestCase :: UnlockStakeParameters -> Bool -> SpecificationTree -mkProposalValidatorTestCase p shouldSucceed = - let datum = mkProposalInputDatum p $ ProposalId 0 - redeemer = Unlock (ResultTag 0) - name = show p - scriptContext = ScriptContext (unlockStake p) (Spending proposalRef) - f = if shouldSucceed then validatorSucceedsWith else validatorFailsWith - in f name (proposalValidator Shared.proposal) datum redeemer scriptContext + in builder + +-- | Reference to the stake UTXO. +stakeRef :: TxOutRef +stakeRef = TxOutRef stakeTxRef 1 + +-- | Generate the reference to a proposal UTXOs, given the index of the proposal. +mkProposalRef :: Int -> TxOutRef +mkProposalRef offset = TxOutRef stakeTxRef $ 2 + fromIntegral offset + +-- | Proposal redeemer used by 'mkTestTree', in this case it's always 'Unlock'. +proposalRedeemer :: ProposalRedeemer +proposalRedeemer = Unlock + +-- | Stake redeemer used by 'mkTestTree', in this case it's always 'RetractVotes'. +stakeRedeemer :: StakeRedeemer +stakeRedeemer = RetractVotes + +-------------------------------------------------------------------------------- + +{- | Legal parameters that retract votes while the proposals is in 'VotingReady' + state, and also remove voter locks from the stake, which is + used to vote on the proposals. +-} +mkVoterRetractVotesWhileVotingParameters :: Integer -> Parameters +mkVoterRetractVotesWhileVotingParameters nProposals = + Parameters + { proposalCount = nProposals + , stakeRole = Voter + , retractVotes = True + , removeVoterLock = True + , removeCreatorLock = False + , proposalStatus = VotingReady + , alterOutputStake = False + } + +{- | Legal parameters that retract votes while the proposals is in 'VotingReady' + state, and also remove voter locks from the stake, which is + used to both create and vote on the proposals. +-} +mkVoterCreatorRetractVotesWhileVotingParameters :: Integer -> Parameters +mkVoterCreatorRetractVotesWhileVotingParameters nProposals = + Parameters + { proposalCount = nProposals + , stakeRole = Both + , retractVotes = True + , removeVoterLock = True + , removeCreatorLock = False + , proposalStatus = VotingReady + , alterOutputStake = False + } + +{- | Legal parameters that remove creator locks from the stake while the + proposals is in 'Finished' state. The stake was only used for creating + the proposals. +-} +mkCreatorRemoveCreatorLocksWhenFinishedParameters :: Integer -> Parameters +mkCreatorRemoveCreatorLocksWhenFinishedParameters nProposals = + Parameters + { proposalCount = nProposals + , stakeRole = Creator + , retractVotes = False + , removeVoterLock = False + , removeCreatorLock = True + , proposalStatus = Finished + , alterOutputStake = False + } + +{- | Legal parameters that remove voter and creator locks from the stake while + the proposals is in 'Finished' state. The stake was used for creating + and voting on the proposals. +-} +mkVoterCreatorRemoveAllLocksWhenFinishedParameters :: Integer -> Parameters +mkVoterCreatorRemoveAllLocksWhenFinishedParameters nProposals = + Parameters + { proposalCount = nProposals + , stakeRole = Both + , retractVotes = False + , removeVoterLock = True + , removeCreatorLock = True + , proposalStatus = Finished + , alterOutputStake = False + } + +{- Legal parameters that remove voter locks from the stake after the voting + phrase. The stake was used only for voting on the proposals. +-} +mkVoterUnlockStakeAfterVotingParameters :: Integer -> [Parameters] +mkVoterUnlockStakeAfterVotingParameters nProposals = + map + ( \st -> + Parameters + { proposalCount = nProposals + , stakeRole = Voter + , retractVotes = False + , removeVoterLock = True + , removeCreatorLock = False + , proposalStatus = st + , alterOutputStake = False + } + ) + [Locked, Finished] + +{- Legal parameters that remove voter locks whenproposals are in phrase. + The stake was used for crating and voting on the proposals. +-} +mkVoterCreatorRemoveVoteLocksWhenLockedParameters :: Integer -> Parameters +mkVoterCreatorRemoveVoteLocksWhenLockedParameters nProposals = + Parameters + { proposalCount = nProposals + , stakeRole = Both + , retractVotes = False + , removeVoterLock = True + , removeCreatorLock = False + , proposalStatus = Locked + , alterOutputStake = False + } + +{- | Illegal parameters that retract votes when the proposals are not in voting + phrase. +-} +mkRetractVotesWhileNotVoting :: Integer -> [Parameters] +mkRetractVotesWhileNotVoting nProposals = do + role <- enumFrom Voter + status <- [Draft, Locked, Finished] + + pure $ + Parameters + { proposalCount = nProposals + , stakeRole = role + , retractVotes = True + , removeVoterLock = True + , removeCreatorLock = False + , proposalStatus = status + , alterOutputStake = False + } + +{- | Illegal parameter that try to unlock a stake that has nothing to do with + the proposals. +-} +mkUnockIrrelevantStakeParameters :: Integer -> [Parameters] +mkUnockIrrelevantStakeParameters nProposals = do + status <- [Draft, VotingReady, Locked, Finished] + retractVotes <- [True, False] + + pure $ + Parameters + { proposalCount = nProposals + , stakeRole = Irrelevant + , retractVotes = retractVotes + , removeVoterLock = True + , removeCreatorLock = True + , proposalStatus = status + , alterOutputStake = False + } + +{- | Illegal parameters that remove the creator locks before the proposals are + 'Finished'. +-} +mkRemoveCreatorLockBeforeFinishedParameters :: Integer -> [Parameters] +mkRemoveCreatorLockBeforeFinishedParameters nProposals = do + status <- [Draft, VotingReady, Locked] + + pure $ + Parameters + { proposalCount = nProposals + , stakeRole = Creator + , retractVotes = False + , removeVoterLock = False + , removeCreatorLock = True + , proposalStatus = status + , alterOutputStake = False + } + +{- | Illegal parameters that try to retract votes with a stake that was only used + for creating the proposals. +-} +mkRetractVotesWithCreatorStakeParamaters :: Integer -> Parameters +mkRetractVotesWithCreatorStakeParamaters nProposals = + Parameters + { proposalCount = nProposals + , stakeRole = Creator + , retractVotes = True + , removeVoterLock = True + , removeCreatorLock = True + , proposalStatus = VotingReady + , alterOutputStake = False + } + +{- | Illegal parameters that try to change the 'StakeDatum.stakedAmount' field of + the output stake datum. +-} +mkAlterStakeParameters :: Integer -> [Parameters] +mkAlterStakeParameters nProposals = do + role <- enumFrom Voter + status <- [Draft, Locked, Finished] + + pure $ + Parameters + { proposalCount = nProposals + , stakeRole = role + , retractVotes = True + , removeVoterLock = True + , removeCreatorLock = False + , proposalStatus = status + , alterOutputStake = True + } + +-------------------------------------------------------------------------------- + +{- | Create a test tree that runs both the stake validator and the proposal + validator. +-} +mkTestTree :: String -> Parameters -> Bool -> SpecificationTree +mkTestTree name ps isValid = group name [stake, proposal] + where + spend = mkSpending unlockStake ps + + stake = + testValidator + (not ps.alterOutputStake) + "stake" + agoraScripts.compiledStakeValidator + (mkStakeInputDatum ps) + stakeRedeemer + (spend stakeRef) + + proposal = + let idx = 0 + pid = ProposalId $ fromIntegral idx + ref = mkProposalRef idx + in testValidator + isValid + "proposal" + agoraScripts.compiledProposalValidator + (mkProposalInputDatum ps pid) + proposalRedeemer + (spend ref) diff --git a/agora-specs/Sample/Proposal/Vote.hs b/agora-specs/Sample/Proposal/Vote.hs new file mode 100644 index 00000000..937a152b --- /dev/null +++ b/agora-specs/Sample/Proposal/Vote.hs @@ -0,0 +1,292 @@ +{- | +Module : Sample.Proposal.Vote +Maintainer : connor@mlabs.city +Description: Generate sample data for testing the functionalities of voting on proposals. + +Sample and utilities for testing the functionalities of voting on proposals. +-} +module Sample.Proposal.Vote ( + validVoteParameters, + mkTestTree, + validVoteAsDelegateParameters, +) where + +import Agora.Governor (Governor (..)) +import Agora.Proposal ( + ProposalDatum (..), + ProposalId (ProposalId), + ProposalRedeemer (Vote), + ProposalStatus (VotingReady), + ProposalVotes (ProposalVotes), + ResultTag (ResultTag), + ) +import Agora.Proposal.Time ( + ProposalStartingTime (ProposalStartingTime), + ProposalTimingConfig (draftTime, votingTime), + ) +import Agora.Scripts (AgoraScripts (..)) +import Agora.Stake ( + ProposalLock (..), + StakeDatum (..), + StakeRedeemer (PermitVote), + ) +import Data.Default (Default (def)) +import Data.Tagged (Tagged (Tagged), untag) +import Plutarch.Context ( + input, + output, + script, + signedWith, + timeRange, + txId, + withDatum, + withOutRef, + withValue, + ) +import PlutusLedgerApi.V1 ( + PubKeyHash, + TxOutRef (TxOutRef), + ) +import PlutusLedgerApi.V1.Value qualified as Value +import PlutusTx.AssocMap qualified as AssocMap +import Sample.Proposal.Shared (proposalTxRef, stakeTxRef) +import Sample.Shared ( + agoraScripts, + governor, + minAda, + proposalPolicySymbol, + proposalValidatorHash, + signer, + stakeAssetClass, + stakeValidatorHash, + ) +import Test.Specification ( + SpecificationTree, + group, + testValidator, + validatorSucceedsWith, + ) +import Test.Util (CombinableBuilder, closedBoundedInterval, mkSpending, pubKeyHashes, sortValue, updateMap) + +-- | Reference to the proposal UTXO. +proposalRef :: TxOutRef +proposalRef = TxOutRef proposalTxRef 0 + +-- | Reference to the stake UTXO. +stakeRef :: TxOutRef +stakeRef = TxOutRef stakeTxRef 1 + +-- | Parameters for creating a voting transaction. +data Parameters = Parameters + { voteFor :: ResultTag + -- ^ The outcome the transaction is voting for. + , voteCount :: Integer + -- ^ The count of votes. + , voteAsDelegate :: Bool + -- ^ Delegate the stake and use it to vote. + } + +-- | The public key hash of the stake owner. +stakeOwner :: PubKeyHash +stakeOwner = signer + +-- | The votes of the input proposals. +initialVotes :: AssocMap.Map ResultTag Integer +initialVotes = + AssocMap.fromList + [ (ResultTag 0, 42) + , (ResultTag 1, 4242) + ] + +-- | The input proposal datum. +proposalInputDatum :: ProposalDatum +proposalInputDatum = + ProposalDatum + { proposalId = ProposalId 42 + , effects = + AssocMap.fromList + [ (ResultTag 0, AssocMap.empty) + , (ResultTag 1, AssocMap.empty) + ] + , status = VotingReady + , cosigners = [stakeOwner] + , thresholds = def + , votes = ProposalVotes initialVotes + , timingConfig = def + , startingTime = ProposalStartingTime 0 + } + +-- | The locks of the input stake. +existingLocks :: [ProposalLock] +existingLocks = + [ Voted (ProposalId 0) (ResultTag 0) + , Voted (ProposalId 1) (ResultTag 2) + ] + +delegate :: PubKeyHash +delegate = head pubKeyHashes + +{- | Set the 'StakeDatum.stakedAmount' according to the number of votes being + casted. +-} +mkStakeInputDatum :: Parameters -> StakeDatum +mkStakeInputDatum params = + StakeDatum + { stakedAmount = Tagged params.voteCount + , owner = stakeOwner + , delegatedTo = + if params.voteAsDelegate + then Just delegate + else Nothing + , lockedBy = existingLocks + } + +-- | Create the proposal redeemer. In this case @'Vote' _@ will always be used. +mkProposalRedeemer :: Parameters -> ProposalRedeemer +mkProposalRedeemer = Vote . voteFor + +-- | Place new proposal locks on the stake. +mkNewLock :: Parameters -> ProposalLock +mkNewLock = Voted proposalInputDatum.proposalId . voteFor + +{- | The stake redeemer that is used in 'mkTestTree'. In this case it'll always be + 'PermitVote'. +-} +stakeRedeemer :: StakeRedeemer +stakeRedeemer = PermitVote + +-- | Create a valid transaction that votes on a propsal, given the parameters. +vote :: forall b. CombinableBuilder b => Parameters -> b +vote params = + let pst = Value.singleton proposalPolicySymbol "" 1 + sst = Value.assetClassValue stakeAssetClass 1 + + --- + + stakeInputDatum = mkStakeInputDatum params + + --- + + updatedVotes :: AssocMap.Map ResultTag Integer + updatedVotes = updateMap (Just . (+ params.voteCount)) params.voteFor initialVotes + + --- + + proposalOutputDatum :: ProposalDatum + proposalOutputDatum = + proposalInputDatum + { votes = ProposalVotes updatedVotes + } + + --- + + -- Off-chain code should do exactly like this: prepend new lock toStatus the list. + updatedLocks :: [ProposalLock] + updatedLocks = mkNewLock params : existingLocks + + --- + + stakeOutputDatum :: StakeDatum + stakeOutputDatum = + stakeInputDatum + { lockedBy = updatedLocks + } + + --- + + validTimeRange = + closedBoundedInterval + ((def :: ProposalTimingConfig).draftTime + 1) + ((def :: ProposalTimingConfig).votingTime - 1) + + --- + + stakeValue = + sortValue $ + sst + <> Value.assetClassValue (untag governor.gtClassRef) params.voteCount + <> minAda + + signer = + if params.voteAsDelegate + then delegate + else stakeOwner + + builder = + mconcat + [ txId "827598fb2d69a896bbd9e645bb14c307df907f422b39eecbe4d6329bc30b428c" + , signedWith signer + , timeRange validTimeRange + , input $ + mconcat + [ script proposalValidatorHash + , withValue pst + , withDatum proposalInputDatum + , withOutRef proposalRef + ] + , input $ + mconcat + [ script stakeValidatorHash + , withValue stakeValue + , withDatum stakeInputDatum + , withOutRef stakeRef + ] + , output $ + mconcat + [ script proposalValidatorHash + , withValue pst + , withDatum proposalOutputDatum + ] + , output $ + mconcat + [ script stakeValidatorHash + , withValue stakeValue + , withDatum stakeOutputDatum + ] + ] + in builder + +--- + +-- | Valida parameters that vote on the proposal. +validVoteParameters :: Parameters +validVoteParameters = + Parameters + { voteFor = ResultTag 0 + , voteCount = 27 + , voteAsDelegate = False + } + +validVoteAsDelegateParameters :: Parameters +validVoteAsDelegateParameters = + validVoteParameters + { voteAsDelegate = True + } + +--- + +{- | Create a test tree that runs the stake validator and proposal validator to + test the voting functionalities. +-} +mkTestTree :: String -> Parameters -> Bool -> SpecificationTree +mkTestTree name ps isValid = group name [proposal, stake] + where + spend = mkSpending vote ps + + proposal = + testValidator + isValid + "proposal" + agoraScripts.compiledProposalValidator + proposalInputDatum + (mkProposalRedeemer ps) + (spend proposalRef) + + stake = + let stakeInputDatum = mkStakeInputDatum ps + in validatorSucceedsWith + "stake" + agoraScripts.compiledStakeValidator + stakeInputDatum + stakeRedeemer + (spend stakeRef) diff --git a/agora-specs/Sample/Shared.hs b/agora-specs/Sample/Shared.hs index c1197e31..01039db8 100644 --- a/agora-specs/Sample/Shared.hs +++ b/agora-specs/Sample/Shared.hs @@ -12,11 +12,15 @@ module Sample.Shared ( signer, signer2, minAda, + deterministicTracingConfing, + mkEffect, + + -- * Agora Scripts + agoraScripts, -- * Components -- ** Stake - stake, stakeAssetClass, stakeValidatorHash, stakeAddress, @@ -33,14 +37,12 @@ module Sample.Shared ( gstUTXORef, -- ** Proposal - proposal, proposalPolicySymbol, proposalValidatorHash, proposalValidatorAddress, proposalStartingTimeFromTimeRange, -- ** Authority - authorityToken, authorityTokenSymbol, -- ** Treasury @@ -53,38 +55,29 @@ module Sample.Shared ( wrongEffHash, ) where -import Agora.AuthorityToken (AuthorityToken) +import Agora.Bootstrap qualified as Bootstrap import Agora.Effect.NoOp (noOpValidator) import Agora.Governor (Governor (Governor)) -import Agora.Governor.Scripts ( - authorityTokenFromGovernor, - authorityTokenSymbolFromGovernor, - governorPolicy, - governorSTAssetClassFromGovernor, - governorValidator, - governorValidatorHash, - proposalFromGovernor, - proposalSTSymbolFromGovernor, - proposalValidatorHashFromGovernor, - stakeFromGovernor, - stakeSTAssetClassFromGovernor, - stakeSTSymbolFromGovernor, - stakeValidatorHashFromGovernor, - ) -import Agora.Proposal (Proposal (..), ProposalThresholds (..)) +import Agora.Proposal (ProposalThresholds (..)) import Agora.Proposal.Time ( MaxTimeRangeWidth (..), ProposalStartingTime (ProposalStartingTime), ProposalTimingConfig (..), ) -import Agora.Stake (Stake (..)) +import Agora.Scripts qualified as Scripts import Agora.Treasury (treasuryValidator) -import Agora.Utils (validatorHashToTokenName) +import Agora.Utils ( + CompiledEffect (CompiledEffect), + CompiledMintingPolicy (getCompiledMintingPolicy), + CompiledValidator (getCompiledValidator), + validatorHashToTokenName, + ) import Data.Default.Class (Default (..)) import Data.Tagged (Tagged (..)) +import Plutarch (Config (..), TracingMode (DetTracing)) import Plutarch.Api.V1 ( + PValidator, mintingPolicySymbol, - mkMintingPolicy, mkValidator, validatorHash, ) @@ -110,18 +103,36 @@ import PlutusLedgerApi.V1.Value qualified as Value ( assetClass, singleton, ) +import PlutusTx qualified + +-- Plutarch compiler configauration. +-- TODO: add the ability to change this value. Maybe wrap everything in a +-- Reader monad? +deterministicTracingConfing :: Config +deterministicTracingConfing = Config DetTracing + +governor :: Governor +governor = Governor oref gt mc + where + oref = gstUTXORef + gt = + Tagged $ + Value.assetClass + "da8c30857834c6ae7203935b89278c532b3995245295456f993e1d24" + "LQ" + mc = 20 -stake :: Stake -stake = stakeFromGovernor governor +agoraScripts :: Scripts.AgoraScripts +agoraScripts = Bootstrap.agoraScripts deterministicTracingConfing governor stakeSymbol :: CurrencySymbol -stakeSymbol = stakeSTSymbolFromGovernor governor +stakeSymbol = Scripts.stakeSTSymbol agoraScripts stakeAssetClass :: AssetClass -stakeAssetClass = stakeSTAssetClassFromGovernor governor +stakeAssetClass = Scripts.stakeSTAssetClass agoraScripts stakeValidatorHash :: ValidatorHash -stakeValidatorHash = stakeValidatorHashFromGovernor governor +stakeValidatorHash = Scripts.stakeValidatorHash agoraScripts stakeAddress :: Address stakeAddress = Address (ScriptCredential stakeValidatorHash) Nothing @@ -129,40 +140,26 @@ stakeAddress = Address (ScriptCredential stakeValidatorHash) Nothing gstUTXORef :: TxOutRef gstUTXORef = TxOutRef "f28cd7145c24e66fd5bcd2796837aeb19a48a2656e7833c88c62a2d0450bd00d" 0 -governor :: Governor -governor = Governor oref gt mc - where - oref = gstUTXORef - gt = - Tagged $ - Value.assetClass - "da8c30857834c6ae7203935b89278c532b3995245295456f993e1d24" - "LQ" - mc = 6 - govPolicy :: MintingPolicy -govPolicy = mkMintingPolicy (governorPolicy governor) +govPolicy = getCompiledMintingPolicy $ agoraScripts.compiledGovernorPolicy govValidator :: Validator -govValidator = mkValidator (governorValidator governor) +govValidator = getCompiledValidator $ agoraScripts.compiledGovernorValidator govSymbol :: CurrencySymbol govSymbol = mintingPolicySymbol govPolicy govAssetClass :: AssetClass -govAssetClass = governorSTAssetClassFromGovernor governor +govAssetClass = Scripts.governorSTAssetClass agoraScripts govValidatorHash :: ValidatorHash -govValidatorHash = governorValidatorHash governor +govValidatorHash = Scripts.governorValidatorHash agoraScripts govValidatorAddress :: Address govValidatorAddress = scriptHashAddress govValidatorHash -proposal :: Proposal -proposal = proposalFromGovernor governor - proposalPolicySymbol :: CurrencySymbol -proposalPolicySymbol = proposalSTSymbolFromGovernor governor +proposalPolicySymbol = Scripts.proposalSTSymbol agoraScripts -- | A sample 'PubKeyHash'. signer :: PubKeyHash @@ -173,7 +170,7 @@ signer2 :: PubKeyHash signer2 = "8a30896c4fd5e79843e4ca1bd2cdbaa36f8c0bc3be74012141420192" proposalValidatorHash :: ValidatorHash -proposalValidatorHash = proposalValidatorHashFromGovernor governor +proposalValidatorHash = Scripts.proposalValidatoHash agoraScripts proposalValidatorAddress :: Address proposalValidatorAddress = scriptHashAddress proposalValidatorHash @@ -186,14 +183,11 @@ instance Default ProposalThresholds where ProposalThresholds { execute = Tagged 1000 , create = Tagged 1 - , vote = Tagged 10 + , vote = Tagged 100 } -authorityToken :: AuthorityToken -authorityToken = authorityTokenFromGovernor governor - authorityTokenSymbol :: CurrencySymbol -authorityTokenSymbol = authorityTokenSymbolFromGovernor governor +authorityTokenSymbol = Scripts.authorityTokenSymbol agoraScripts {- | Default value of 'Agora.Governor.GovernorDatum.proposalTimings'. For testing purpose only. @@ -222,6 +216,9 @@ proposalStartingTimeFromTimeRange ProposalStartingTime $ (l + u) `div` 2 proposalStartingTimeFromTimeRange _ = error "Given time range should be finite and closed" +mkEffect :: (PlutusTx.ToData datum) => ClosedTerm PValidator -> CompiledEffect datum +mkEffect v = CompiledEffect $ mkValidator deterministicTracingConfing v + ------------------------------------------------------------------ treasuryOut :: TxOut @@ -239,7 +236,7 @@ gatCs :: CurrencySymbol gatCs = "73475cb40a568e8da8a045ced110137e159f890ac4da883b6b17dc651b3a8049" trValidator :: Validator -trValidator = mkValidator (treasuryValidator gatCs) +trValidator = mkValidator def (treasuryValidator gatCs) -- | `ScriptCredential` used for the dummy treasury validator. trCredential :: Credential @@ -251,7 +248,7 @@ gatTn = validatorHashToTokenName $ validatorHash mockTrEffect -- | Mock treasury effect script, used for testing. mockTrEffect :: Validator -mockTrEffect = mkValidator $ noOpValidator gatCs +mockTrEffect = mkValidator def $ noOpValidator gatCs -- | Mock treasury effect validator hash mockTrEffectHash :: ValidatorHash diff --git a/agora-specs/Sample/Stake.hs b/agora-specs/Sample/Stake.hs index 88e5dc77..1d0f2c1e 100644 --- a/agora-specs/Sample/Stake.hs +++ b/agora-specs/Sample/Stake.hs @@ -6,10 +6,8 @@ Description: Sample based testing for Stake utxos This module tests primarily the happy path for Stake creation -} module Sample.Stake ( - stake, stakeAssetClass, stakeSymbol, - validatorHashTN, signer, -- * Script contexts @@ -20,14 +18,12 @@ module Sample.Stake ( DepositWithdrawExample (..), ) where +import Agora.Governor (Governor (gtClassRef)) import Agora.SafeMoney (GTTag) import Agora.Stake ( - Stake (gtClassRef), StakeDatum (StakeDatum, stakedAmount), ) -import Agora.Stake.Scripts (stakeValidator) import Data.Tagged (Tagged, untag) -import Plutarch.Api.V1 (mkValidator, validatorHash) import Plutarch.Context ( MintingBuilder, SpendingBuilder, @@ -40,8 +36,9 @@ import Plutarch.Context ( signedWith, txId, withDatum, - withSpending, - withTxId, + withMinting, + withOutRef, + withSpendingOutRef, withValue, ) import PlutusLedgerApi.V1 ( @@ -49,32 +46,28 @@ import PlutusLedgerApi.V1 ( ScriptContext (..), ScriptPurpose (Minting), ToData (toBuiltinData), - TokenName (TokenName), TxInfo (txInfoData, txInfoSignatories), - ValidatorHash (ValidatorHash), ) +import PlutusLedgerApi.V1.Contexts (TxOutRef (..)) import PlutusLedgerApi.V1.Value qualified as Value ( assetClassValue, singleton, ) import Sample.Shared ( + governor, signer, - stake, stakeAssetClass, stakeSymbol, stakeValidatorHash, ) - --- | 'TokenName' that represents the hash of the 'Stake' validator. -validatorHashTN :: TokenName -validatorHashTN = let ValidatorHash vh = validatorHash (mkValidator $ stakeValidator stake) in TokenName vh +import Test.Util (sortValue) -- | This script context should be a valid transaction. stakeCreation :: ScriptContext stakeCreation = let st = Value.assetClassValue stakeAssetClass 1 -- Stake ST datum :: StakeDatum - datum = StakeDatum 424242424242 signer [] + datum = StakeDatum 424242424242 signer Nothing [] builder :: MintingBuilder builder = @@ -83,9 +76,12 @@ stakeCreation = , signedWith signer , mint st , output $ - script stakeValidatorHash - . withValue (st <> Value.singleton "da8c30857834c6ae7203935b89278c532b3995245295456f993e1d24" "LQ" 424242424242) - . withDatum datum + mconcat + [ script stakeValidatorHash + , withValue (st <> Value.singleton "da8c30857834c6ae7203935b89278c532b3995245295456f993e1d24" "LQ" 424242424242) + , withDatum datum + ] + , withMinting stakeSymbol ] in buildMintingUnsafe builder @@ -93,7 +89,7 @@ stakeCreation = stakeCreationWrongDatum :: ScriptContext stakeCreationWrongDatum = let datum :: Datum - datum = Datum (toBuiltinData $ StakeDatum 4242424242424242 signer []) -- Too much GT + datum = Datum (toBuiltinData $ StakeDatum 4242424242424242 signer Nothing []) -- Too much GT in ScriptContext { scriptContextTxInfo = stakeCreation.scriptContextTxInfo {txInfoData = [("", datum)]} , scriptContextPurpose = Minting stakeSymbol @@ -125,11 +121,14 @@ stakeDepositWithdraw :: DepositWithdrawExample -> ScriptContext stakeDepositWithdraw config = let st = Value.assetClassValue stakeAssetClass 1 -- Stake ST stakeBefore :: StakeDatum - stakeBefore = StakeDatum config.startAmount signer [] + stakeBefore = StakeDatum config.startAmount signer Nothing [] stakeAfter :: StakeDatum stakeAfter = stakeBefore {stakedAmount = stakeBefore.stakedAmount + config.delta} + stakeRef :: TxOutRef + stakeRef = TxOutRef "0ffef57e30cc604342c738e31e0451593837b313e7bfb94b0922b142782f98e6" 1 + builder :: SpendingBuilder builder = mconcat @@ -137,17 +136,26 @@ stakeDepositWithdraw config = , signedWith signer , mint st , input $ - script stakeValidatorHash - . withValue (st <> Value.assetClassValue (untag stake.gtClassRef) (untag stakeBefore.stakedAmount)) - . withDatum stakeAfter - . withTxId "0b2086cbf8b6900f8cb65e012de4516cb66b5cb08a9aaba12a8b88be" + mconcat + [ script stakeValidatorHash + , withValue + ( sortValue $ + st + <> Value.assetClassValue (untag governor.gtClassRef) (untag stakeBefore.stakedAmount) + ) + , withDatum stakeAfter + , withOutRef stakeRef + ] , output $ - script stakeValidatorHash - . withValue (st <> Value.assetClassValue (untag stake.gtClassRef) (untag stakeAfter.stakedAmount)) - . withDatum stakeAfter - , withSpending $ - script stakeValidatorHash - . withValue (st <> Value.assetClassValue (untag stake.gtClassRef) (untag stakeBefore.stakedAmount)) - . withDatum stakeAfter + mconcat + [ script stakeValidatorHash + , withValue + ( sortValue $ + st + <> Value.assetClassValue (untag governor.gtClassRef) (untag stakeAfter.stakedAmount) + ) + , withDatum stakeAfter + ] + , withSpendingOutRef stakeRef ] in buildSpendingUnsafe builder diff --git a/agora-specs/Sample/Stake/SetDelegate.hs b/agora-specs/Sample/Stake/SetDelegate.hs new file mode 100644 index 00000000..9f9f25e0 --- /dev/null +++ b/agora-specs/Sample/Stake/SetDelegate.hs @@ -0,0 +1,209 @@ +{- | +Module : Sample.Stake.SetDelegate +Maintainer : connor@mlabs.city +Description: Generate sample data for testing the functionalities of setting the delegate. + +Sample and utilities for testing the functionalities of setting the delegate. +-} +module Sample.Stake.SetDelegate ( + Parameters (..), + setDelegate, + mkStakeRedeemer, + mkStakeInputDatum, + mkTestCase, + overrideExistingDelegateParameters, + clearDelegateParameters, + setDelegateParameters, + invalidOutputStakeDatumParameters, + ownerDoesntSignParameters, + delegateToOwnerParameters, +) where + +import Agora.Governor (Governor (gtClassRef)) +import Agora.Scripts (AgoraScripts (..)) +import Agora.Stake ( + StakeDatum (..), + StakeRedeemer (ClearDelegate, DelegateTo), + ) +import Data.Tagged (untag) +import Plutarch.Context ( + SpendingBuilder, + buildSpendingUnsafe, + input, + output, + script, + signedWith, + txId, + withDatum, + withOutRef, + withSpendingOutRef, + withValue, + ) +import PlutusLedgerApi.V1 ( + PubKeyHash, + ScriptContext, + TxOutRef (TxOutRef), + ) +import PlutusLedgerApi.V1.Value qualified as Value +import Sample.Shared ( + agoraScripts, + governor, + minAda, + signer, + signer2, + stakeAssetClass, + stakeValidatorHash, + ) +import Test.Specification (SpecificationTree, testValidator) +import Test.Util (pubKeyHashes, sortValue) + +-------------------------------------------------------------------------------- + +-- | Parameters that control the script context generation of 'setDelegate'. +data Parameters = Parameters + { existingDelegate :: Maybe PubKeyHash + -- ^ Whom the stake has been delegated to. + , newDelegate :: Maybe PubKeyHash + -- ^ The new delegate to set to. + , invalidOutputStake :: Bool + -- ^ The output stake datum will be invalid if this is set to true. + , signedByOwner :: Bool + -- ^ Whether the stake owner signs the transaction o not. + } + +-- | Select the correct stake redeemer based on the existence of the new delegate. +mkStakeRedeemer :: Parameters -> StakeRedeemer +mkStakeRedeemer (newDelegate -> d) = maybe ClearDelegate DelegateTo d + +-- | The owner of the input stake. +stakeOwner :: PubKeyHash +stakeOwner = signer + +-- | Create input stake datum given the parameters. +mkStakeInputDatum :: Parameters -> StakeDatum +mkStakeInputDatum ps = + StakeDatum + { stakedAmount = 5 + , owner = stakeOwner + , delegatedTo = ps.existingDelegate + , lockedBy = [] + } + +-- | Generate a 'ScriptContext' that tries to change the delegate of a stake. +setDelegate :: Parameters -> ScriptContext +setDelegate ps = buildSpendingUnsafe builder + where + stakeRef :: TxOutRef + stakeRef = TxOutRef "0ffef57e30cc604342c738e31e0451593837b313e7bfb94b0922b142782f98e6" 1 + + stakeInput = mkStakeInputDatum ps + + stakeOutput = + let stakedAmount = + if ps.invalidOutputStake + then stakeInput.stakedAmount - 1 + else stakeInput.stakedAmount + in stakeInput + { stakedAmount = stakedAmount + , delegatedTo = ps.newDelegate + } + + signer = + if ps.signedByOwner + then stakeInput.owner + else signer2 + + st = Value.assetClassValue stakeAssetClass 1 -- Stake ST + stakeValue = + sortValue $ + mconcat + [ st + , Value.assetClassValue + (untag governor.gtClassRef) + (untag stakeInput.stakedAmount) + , minAda + ] + + builder :: SpendingBuilder + builder = + mconcat + [ txId "0b2086cbf8b6900f8cb65e012de4516cb66b5cb08a9aaba12a8b88be" + , signedWith signer + , input $ + mconcat + [ script stakeValidatorHash + , withValue stakeValue + , withDatum stakeInput + , withOutRef stakeRef + ] + , output $ + mconcat + [ script stakeValidatorHash + , withValue stakeValue + , withDatum stakeOutput + ] + , withSpendingOutRef stakeRef + ] + +-------------------------------------------------------------------------------- + +{- | Create a test case that runs the stake validator to test the functionality + of setting the delegate.P +-} +mkTestCase :: String -> Parameters -> Bool -> SpecificationTree +mkTestCase name ps valid = + testValidator + valid + name + agoraScripts.compiledStakeValidator + (mkStakeInputDatum ps) + (mkStakeRedeemer ps) + (setDelegate ps) + +-------------------------------------------------------------------------------- + +-- * Valid Parameters + +overrideExistingDelegateParameters :: Parameters +overrideExistingDelegateParameters = + Parameters + { existingDelegate = Just $ head pubKeyHashes + , newDelegate = Just $ pubKeyHashes !! 2 + , invalidOutputStake = False + , signedByOwner = True + } + +clearDelegateParameters :: Parameters +clearDelegateParameters = + overrideExistingDelegateParameters + { newDelegate = Nothing + } + +setDelegateParameters :: Parameters +setDelegateParameters = + overrideExistingDelegateParameters + { existingDelegate = Nothing + } + +-------------------------------------------------------------------------------- + +-- * Invalid Parameters + +ownerDoesntSignParameters :: Parameters +ownerDoesntSignParameters = + overrideExistingDelegateParameters + { signedByOwner = False + } + +delegateToOwnerParameters :: Parameters +delegateToOwnerParameters = + overrideExistingDelegateParameters + { existingDelegate = Nothing + , newDelegate = Just stakeOwner + } + +invalidOutputStakeDatumParameters :: Parameters +invalidOutputStakeDatumParameters = + overrideExistingDelegateParameters + { invalidOutputStake = True + } diff --git a/agora-specs/Sample/Treasury.hs b/agora-specs/Sample/Treasury.hs index 632f5593..f314509e 100644 --- a/agora-specs/Sample/Treasury.hs +++ b/agora-specs/Sample/Treasury.hs @@ -19,7 +19,6 @@ module Sample.Treasury ( import Plutarch.Context ( MintingBuilder, - UTXO, buildMintingUnsafe, credential, input, @@ -28,6 +27,7 @@ import Plutarch.Context ( script, signedWith, txId, + withMinting, withTxId, withValue, ) @@ -56,17 +56,19 @@ import Sample.Shared ( baseCtxBuilder :: MintingBuilder baseCtxBuilder = - let treasury :: UTXO -> UTXO - treasury = - credential trCredential - . withValue minAda - . withTxId "73475cb40a568e8da8a045ced110137e159f890ac4da883b6b17dc651b3a8049" + let treasury = + mconcat + [ credential trCredential + , withValue minAda + , withTxId "73475cb40a568e8da8a045ced110137e159f890ac4da883b6b17dc651b3a8049" + ] in mconcat [ txId "73475cb40a568e8da8a045ced110137e159f890ac4da883b6b17dc651b3a8049" , signedWith signer , mint (Value.singleton gatCs gatTn (-1)) , input treasury , output treasury + , withMinting gatCs ] {- | A `ScriptContext` that should be compatible with treasury @@ -79,9 +81,11 @@ validCtx = mconcat [ baseCtxBuilder , input $ - script mockTrEffectHash - . withValue (Value.singleton gatCs gatTn 1 <> minAda) - . withTxId "52b67b60260da3937510ad545c7f46f8d9915bd27e1082e76947fb309f913bd3" + mconcat + [ script mockTrEffectHash + , withValue (Value.singleton gatCs gatTn 1 <> minAda) + , withTxId "52b67b60260da3937510ad545c7f46f8d9915bd27e1082e76947fb309f913bd3" + ] ] in buildMintingUnsafe builder @@ -120,8 +124,10 @@ trCtxGATNameNotAddress = mconcat [ baseCtxBuilder , input $ - script wrongEffHash - . withValue (Value.singleton gatCs gatTn 1 <> minAda) - . withTxId "52b67b60260da3937510ad545c7f46f8d9915bd27e1082e76947fb309f913bd3" + mconcat + [ script wrongEffHash + , withValue (Value.singleton gatCs gatTn 1 <> minAda) + , withTxId "52b67b60260da3937510ad545c7f46f8d9915bd27e1082e76947fb309f913bd3" + ] ] in buildMintingUnsafe builder diff --git a/agora-specs/Spec/AuthorityToken.hs b/agora-specs/Spec/AuthorityToken.hs index 46b74233..909cbce5 100644 --- a/agora-specs/Spec/AuthorityToken.hs +++ b/agora-specs/Spec/AuthorityToken.hs @@ -10,20 +10,20 @@ Tests for Authority token functions module Spec.AuthorityToken (specs) where import Agora.AuthorityToken (singleAuthorityTokenBurned) -import Plutarch (ClosedTerm, POpaque, compile, perror, popaque) +import Plutarch (ClosedTerm, POpaque, perror, popaque) +import Plutarch.Extra.Compile (mustCompile) +import Plutarch.Unsafe (punsafeCoerce) import PlutusLedgerApi.V1 ( Address (Address), Credential (PubKeyCredential, ScriptCredential), CurrencySymbol, Script, TxInInfo (TxInInfo), - TxInfo (..), TxOut (TxOut), TxOutRef (TxOutRef), ValidatorHash (ValidatorHash), Value, ) -import PlutusLedgerApi.V1.Interval qualified as Interval (always) import PlutusLedgerApi.V1.Value qualified as Value ( Value (Value), singleton, @@ -36,44 +36,32 @@ import Test.Specification ( scriptSucceeds, ) import Prelude ( - Functor (fmap), Maybe (Nothing), PBool, Semigroup ((<>)), + fmap, pconstant, - pconstantData, pif, + ($), ) currencySymbol :: CurrencySymbol currencySymbol = "deadbeef" -mkTxInfo :: Value -> [TxOut] -> TxInfo -mkTxInfo mint outs = - TxInfo - { txInfoInputs = fmap (TxInInfo (TxOutRef "" 0)) outs - , txInfoOutputs = [] - , txInfoFee = Value.singleton "" "" 1000 - , txInfoMint = mint - , txInfoDCert = [] - , txInfoWdrl = [] - , txInfoValidRange = Interval.always - , txInfoSignatories = [] - , txInfoData = [] - , txInfoId = "" - } +mkInputs :: [TxOut] -> [TxInInfo] +mkInputs = fmap (TxInInfo (TxOutRef "" 0)) singleAuthorityTokenBurnedTest :: Value -> [TxOut] -> Script singleAuthorityTokenBurnedTest mint outs = let actual :: ClosedTerm PBool - actual = singleAuthorityTokenBurned (pconstant currencySymbol) (pconstantData (mkTxInfo mint outs)) (pconstant mint) + actual = singleAuthorityTokenBurned (pconstant currencySymbol) (punsafeCoerce $ pconstant $ mkInputs outs) (pconstant mint) s :: ClosedTerm POpaque s = pif actual (popaque (pconstant ())) perror - in compile s + in mustCompile s -- | The SpecificationTree exported by this module. specs :: [SpecificationTree] diff --git a/agora-specs/Spec/Effect/GovernorMutation.hs b/agora-specs/Spec/Effect/GovernorMutation.hs index 5bc7b87d..72a17e69 100644 --- a/agora-specs/Spec/Effect/GovernorMutation.hs +++ b/agora-specs/Spec/Effect/GovernorMutation.hs @@ -2,8 +2,8 @@ module Spec.Effect.GovernorMutation (specs) where import Agora.Effect.GovernorMutation (mutateGovernorValidator) import Agora.Governor (GovernorDatum (..), GovernorRedeemer (MutateGovernor)) -import Agora.Governor.Scripts (governorValidator) import Agora.Proposal (ProposalId (..)) +import Agora.Scripts (AgoraScripts (..)) import Data.Default.Class (Default (def)) import PlutusLedgerApi.V1 (ScriptContext (ScriptContext), ScriptPurpose (Spending)) import Sample.Effect.GovernorMutation ( @@ -14,7 +14,7 @@ import Sample.Effect.GovernorMutation ( mkEffectTxInfo, validNewGovernorDatum, ) -import Sample.Shared qualified as Shared +import Sample.Shared (agoraScripts, mkEffect) import Test.Specification ( SpecificationTree, effectFailsWith, @@ -32,12 +32,13 @@ specs = "valid new governor datum" [ validatorSucceedsWith "governor validator should pass" - (governorValidator Shared.governor) + agoraScripts.compiledGovernorValidator ( GovernorDatum def (ProposalId 0) def def + 3 ) MutateGovernor ( ScriptContext @@ -46,7 +47,7 @@ specs = ) , effectSucceedsWith "effect validator should pass" - (mutateGovernorValidator Shared.governor) + (mkEffect $ mutateGovernorValidator agoraScripts) (mkEffectDatum validNewGovernorDatum) (ScriptContext (mkEffectTxInfo validNewGovernorDatum) (Spending effectRef)) ] @@ -54,12 +55,13 @@ specs = "invalid new governor datum" [ validatorFailsWith "governor validator should fail" - (governorValidator Shared.governor) + agoraScripts.compiledGovernorValidator ( GovernorDatum def (ProposalId 0) def def + 3 ) MutateGovernor ( ScriptContext @@ -68,7 +70,7 @@ specs = ) , effectFailsWith "effect validator should fail" - (mutateGovernorValidator Shared.governor) + (mkEffect $ mutateGovernorValidator agoraScripts) (mkEffectDatum validNewGovernorDatum) (ScriptContext (mkEffectTxInfo invalidNewGovernorDatum) (Spending effectRef)) ] diff --git a/agora-specs/Spec/Effect/TreasuryWithdrawal.hs b/agora-specs/Spec/Effect/TreasuryWithdrawal.hs index ea0f67a2..984a49cd 100644 --- a/agora-specs/Spec/Effect/TreasuryWithdrawal.hs +++ b/agora-specs/Spec/Effect/TreasuryWithdrawal.hs @@ -25,12 +25,14 @@ import Sample.Effect.TreasuryWithdrawal ( treasuries, users, ) +import Sample.Shared (mkEffect) import Test.Specification ( SpecificationTree, effectFailsWith, effectSucceedsWith, group, ) +import Test.Util (sortValue) specs :: [SpecificationTree] specs = @@ -38,7 +40,7 @@ specs = "effect" [ effectSucceedsWith "Simple" - (treasuryWithdrawalValidator currSymbol) + (mkEffect $ treasuryWithdrawalValidator currSymbol) datum1 ( buildScriptContext [ inputGAT @@ -50,7 +52,7 @@ specs = ) , effectSucceedsWith "Simple with multiple treasuries " - (treasuryWithdrawalValidator currSymbol) + (mkEffect $ treasuryWithdrawalValidator currSymbol) datum1 ( buildScriptContext [ inputGAT @@ -67,7 +69,7 @@ specs = ) , effectSucceedsWith "Mixed Assets" - (treasuryWithdrawalValidator currSymbol) + (mkEffect $ treasuryWithdrawalValidator currSymbol) datum2 ( buildScriptContext [ inputGAT @@ -82,7 +84,7 @@ specs = ) , effectFailsWith "Pay to uknown 3rd party" - (treasuryWithdrawalValidator currSymbol) + (mkEffect $ treasuryWithdrawalValidator currSymbol) datum2 ( buildScriptContext [ inputGAT @@ -98,7 +100,7 @@ specs = ) , effectFailsWith "Missing receiver" - (treasuryWithdrawalValidator currSymbol) + (mkEffect $ treasuryWithdrawalValidator currSymbol) datum2 ( buildScriptContext [ inputGAT @@ -113,7 +115,7 @@ specs = ) , effectFailsWith "Unauthorized treasury" - (treasuryWithdrawalValidator currSymbol) + (mkEffect $ treasuryWithdrawalValidator currSymbol) datum3 ( buildScriptContext [ inputGAT @@ -125,7 +127,7 @@ specs = ) , effectFailsWith "Prevent transactions besides the withdrawal" - (treasuryWithdrawalValidator currSymbol) + (mkEffect $ treasuryWithdrawalValidator currSymbol) datum3 ( buildScriptContext [ inputGAT @@ -141,8 +143,14 @@ specs = ] ] where - asset1 = Value.singleton "abbc12" "OrangeBottle" - asset2 = Value.singleton "abbc12" "19721121" + asset1 = + Value.singleton + "0d586e057e76238f8c56c0752507bfa45ae13b04f8497a311d4aaa48" + "OrangeBottle" + asset2 = + Value.singleton + "7e6aa764bceeba1f7acf47d20f1a2a85440afa2928f8ae96376f4d85" + "19721121" datum1 = TreasuryWithdrawalDatum [ (head users, asset1 1) @@ -155,8 +163,8 @@ specs = ] datum2 = TreasuryWithdrawalDatum - [ (head users, asset2 5 <> asset1 4) - , (users !! 1, asset2 1 <> asset1 2) + [ (head users, sortValue $ asset2 5 <> asset1 4) + , (users !! 1, sortValue $ asset2 1 <> asset1 2) , (users !! 2, asset1 1) ] [ head treasuries diff --git a/agora-specs/Spec/Governor.hs b/agora-specs/Spec/Governor.hs index b4889282..215cc0aa 100644 --- a/agora-specs/Spec/Governor.hs +++ b/agora-specs/Spec/Governor.hs @@ -13,17 +13,11 @@ TODO: Add negative test cases, see [#76](https://github.com/Liqwid-Labs/agora/is -} module Spec.Governor (specs) where -import Agora.Governor (GovernorDatum (..), GovernorRedeemer (..)) -import Agora.Governor.Scripts (governorPolicy, governorValidator) -import Agora.Proposal (ProposalId (..)) -import Data.Default.Class (Default (def)) -import Sample.Governor (createProposal, mintGATs, mintGST, mutateState) -import Sample.Shared qualified as Shared +import Sample.Governor.Initialize qualified as GST +import Sample.Governor.Mutate qualified as Mutate import Test.Specification ( SpecificationTree, group, - policySucceedsWith, - validatorSucceedsWith, ) -- | The SpecificationTree exported by this module. @@ -31,46 +25,38 @@ specs :: [SpecificationTree] specs = [ group "policy" - [ policySucceedsWith - "GST minting" - (governorPolicy Shared.governor) - () - mintGST + [ GST.mkTestCase "totally legal" GST.totallyValidParameters True + , group + "illegal" + [ GST.mkTestCase "invalid thresholds" GST.invalidDatumThresholdsParameters False + , GST.mkTestCase + "invalid max time range width for proposal creation" + GST.invalidDatumMaxTimeRangeWidthParameters + False + , GST.mkTestCase "invalid timings" GST.invalidDatumTimingConfigParameters False + , GST.mkTestCase "no governor datum" GST.withoutGovernorDatumParameters False + , GST.mkTestCase "no witness UTXO" GST.witnessNotPresentedParameters False + , GST.mkTestCase "mint more than one GST" GST.mintMoreThanOneGSTParameters False + , GST.mkTestCase "GST has non-empty name" GST.mintGSTWithNoneEmptyNameParameters False + ] ] , group "validator" - [ validatorSucceedsWith - "proposal creation" - (governorValidator Shared.governor) - ( GovernorDatum - def - (ProposalId 0) - def - def - ) - CreateProposal - createProposal - , validatorSucceedsWith - "GATs minting" - (governorValidator Shared.governor) - ( GovernorDatum - def - (ProposalId 5) - def - def - ) - MintGATs - mintGATs - , validatorSucceedsWith - "mutate governor state" - (governorValidator Shared.governor) - ( GovernorDatum - def - (ProposalId 5) - def - def - ) - MutateGovernor - mutateState + [ group + "mutate" + [ Mutate.mkTestCase + "legal" + Mutate.totallyValidBundle + (Mutate.Validity True) + , group "illegal" $ + map + ( \b -> + Mutate.mkTestCase + "(negative test)" + b + (Mutate.Validity False) + ) + Mutate.invalidBundles + ] ] ] diff --git a/agora-specs/Spec/Proposal.hs b/agora-specs/Spec/Proposal.hs index 41234a1b..b49dd60f 100644 --- a/agora-specs/Spec/Proposal.hs +++ b/agora-specs/Spec/Proposal.hs @@ -1,5 +1,3 @@ -{-# LANGUAGE QuasiQuotes #-} - {- | Module : Spec.Proposal Maintainer : emi@haskell.fyi @@ -9,441 +7,388 @@ Tests for Proposal policy and validator -} module Spec.Proposal (specs) where -import Agora.Proposal ( - Proposal (..), - ProposalDatum (..), - ProposalId (ProposalId), - ProposalRedeemer (..), - ProposalStatus (..), - ProposalThresholds (..), - ProposalVotes (ProposalVotes), - ResultTag (ResultTag), - cosigners, - effects, - emptyVotesFor, - proposalId, - status, - thresholds, - votes, - ) -import Agora.Proposal.Scripts (proposalPolicy, proposalValidator) -import Agora.Proposal.Time ( - ProposalStartingTime (ProposalStartingTime), - ) -import Agora.Stake ( - ProposalLock (ProposalLock), - StakeDatum (StakeDatum), - StakeRedeemer (PermitVote, WitnessStake), - ) -import Agora.Stake.Scripts (stakeValidator) -import Data.Default.Class (Default (def)) -import Data.Tagged (Tagged (Tagged), untag) -import PlutusLedgerApi.V1 (ScriptContext (..), ScriptPurpose (..)) -import PlutusTx.AssocMap qualified as AssocMap -import Sample.Proposal qualified as Proposal +import Sample.Proposal.Advance qualified as Advance +import Sample.Proposal.Cosign qualified as Cosign +import Sample.Proposal.Create qualified as Create import Sample.Proposal.UnlockStake qualified as UnlockStake -import Sample.Shared (signer, signer2) -import Sample.Shared qualified as Shared (proposal, stake) +import Sample.Proposal.Vote qualified as Vote import Test.Specification ( SpecificationTree, group, - policySucceedsWith, - validatorFailsWith, - validatorSucceedsWith, ) -- | Stake specs. specs :: [SpecificationTree] specs = [ group - "policy" - [ policySucceedsWith - "proposalCreation" - (proposalPolicy Shared.proposal.governorSTAssetClass) - () - Proposal.proposalCreation + "policy (proposal creation)" + [ Create.mkTestTree + "legal" + Create.totallyValidParameters + True + True + True + , group + "illegal" + [ Create.mkTestTree + "invalid next proposal id" + Create.invalidOutputGovernorDatumParameters + True + False + True + , Create.mkTestTree + "use other's stake" + Create.useStakeOwnBySomeoneElseParameters + True + True + False + , Create.mkTestTree + "altered stake" + Create.invalidOutputStakeParameters + True + False + False + , Create.mkTestTree + "invalid stake locks" + Create.addInvalidLocksParameters + True + False + True + , Create.mkTestTree + "has reached maximum proposals limit" + Create.exceedMaximumProposalsParameters + True + False + True + , Create.mkTestTree + "loose time range" + Create.timeRangeNotTightParameters + True + False + True + , Create.mkTestTree + "open time range" + Create.timeRangeNotClosedParameters + True + False + True + , group "invalid proposal status" $ + map + ( \ps -> + Create.mkTestTree + (show ps.proposalStatus) + ps + True + False + True + ) + Create.invalidProposalStatusParameters + ] ] , group "validator" [ group "cosignature" - [ validatorSucceedsWith - "proposal" - (proposalValidator Shared.proposal) - ( ProposalDatum - { proposalId = ProposalId 0 - , effects = - AssocMap.fromList - [ (ResultTag 0, AssocMap.empty) - , (ResultTag 1, AssocMap.empty) - ] - , status = Draft - , cosigners = [signer] - , thresholds = def - , votes = - emptyVotesFor $ - AssocMap.fromList - [ (ResultTag 0, AssocMap.empty) - , (ResultTag 1, AssocMap.empty) - ] - , timingConfig = def - , startingTime = ProposalStartingTime 0 - } - ) - (Cosign [signer2]) - (ScriptContext (Proposal.cosignProposal [signer2]) (Spending Proposal.proposalRef)) - , validatorSucceedsWith - "stake" - (stakeValidator Shared.stake) - (StakeDatum (Tagged 50_000_000) signer2 []) - WitnessStake - (ScriptContext (Proposal.cosignProposal [signer2]) (Spending Proposal.stakeRef)) - ] + $ let cosignerCases = [1, 5, 10] + + mkLegalGroup nCosigners = + Cosign.mkTestTree + (unwords ["with", show nCosigners, "cosigners"]) + (Cosign.validCosignNParameters nCosigners) + True + legalGroup = + group "legal" $ + map mkLegalGroup cosignerCases + + mkIllegalStatusNotDraftGroup nCosigners = + group (unwords ["with", show nCosigners, "cosigners"]) $ + map + ( \ps -> + Cosign.mkTestTree + ("status: " <> show ps.proposalStatus) + ps + False + ) + (Cosign.statusNotDraftCosignNParameters nCosigners) + illegalStatusNotDraftGroup = + group "proposal status not Draft" $ + map mkIllegalStatusNotDraftGroup cosignerCases + + illegalGroup = + group + "illegal" + [ Cosign.mkTestTree + "duplicate cosigners" + Cosign.duplicateCosignersParameters + False + , Cosign.mkTestTree + "altered output stake" + Cosign.invalidStakeOutputParameters + False + , illegalStatusNotDraftGroup + ] + in [legalGroup, illegalGroup] , group "voting" - [ validatorSucceedsWith - "proposal" - (proposalValidator Shared.proposal) - ( ProposalDatum - { proposalId = ProposalId 42 - , effects = - AssocMap.fromList - [ (ResultTag 0, AssocMap.empty) - , (ResultTag 1, AssocMap.empty) - ] - , status = VotingReady - , cosigners = [signer] - , thresholds = def - , votes = - ProposalVotes - ( AssocMap.fromList - [ (ResultTag 0, 42) - , (ResultTag 1, 4242) - ] - ) - , timingConfig = def - , startingTime = ProposalStartingTime 0 - } - ) - (Vote (ResultTag 0)) - ( ScriptContext - ( Proposal.voteOnProposal - Proposal.VotingParameters - { Proposal.voteFor = ResultTag 0 - , Proposal.voteCount = 27 - } - ) - (Spending Proposal.proposalRef) - ) - , validatorSucceedsWith - "stake" - (stakeValidator Shared.stake) - ( StakeDatum - (Tagged 27) - signer - [ ProposalLock (ResultTag 0) (ProposalId 0) - , ProposalLock (ResultTag 2) (ProposalId 1) - ] - ) - (PermitVote $ ProposalLock (ResultTag 0) (ProposalId 42)) - ( ScriptContext - ( Proposal.voteOnProposal - Proposal.VotingParameters - { Proposal.voteFor = ResultTag 0 - , Proposal.voteCount = 27 - } - ) - (Spending Proposal.stakeRef) - ) + [ group + "legal" + [ Vote.mkTestTree "ordinary" Vote.validVoteParameters True + , Vote.mkTestTree "delegate" Vote.validVoteAsDelegateParameters True + ] + -- TODO: add negative test cases ] , group "advancing" - [ group "successfully advance to next state" $ - map - ( \(name, initialState) -> - validatorSucceedsWith - name - (proposalValidator Shared.proposal) - ( ProposalDatum - { proposalId = ProposalId 0 - , effects = - AssocMap.fromList - [ (ResultTag 0, AssocMap.empty) - , (ResultTag 1, AssocMap.empty) - ] - , status = initialState - , cosigners = [signer] - , thresholds = def - , votes = - ProposalVotes - ( AssocMap.fromList - [ - ( ResultTag 0 - , case initialState of - Draft -> 0 - _ -> untag (def :: ProposalThresholds).execute + 1 - ) - , (ResultTag 1, 0) + $ let possibleCosigners = [1, 5, 10] + possibleEffects = [1, 2, 5] + in do + cs <- possibleCosigners + es <- possibleEffects + + let groupName = + unwords + [ "with" + , show cs + , "cosigners" + , "and" + , show es + , "effects" + ] + + pure $ + group + groupName + [ group + "legal" + $ let allValid = + Advance.Validity + { forProposalValidator = True + , forStakeValidator = True + , forGovernorValidator = Just True + , forAuthorityTokenPolicy = Just True + } + mkName b = + unwords + [ "from" + , show b.proposalParameters.fromStatus + , "to" + , show b.proposalParameters.toStatus ] - ) - , timingConfig = def - , startingTime = ProposalStartingTime 0 - } - ) - AdvanceProposal - ( ScriptContext - ( Proposal.advanceProposalSuccess - Proposal.TransitionParameters - { Proposal.initialProposalStatus = initialState - , Proposal.proposalStartingTime = ProposalStartingTime 0 - } - ) - (Spending Proposal.proposalRef) - ) - ) - [ ("Draft -> VotringReady", Draft) - , ("VotingReady -> Locked", VotingReady) - , ("Locked -> Finished", Locked) - ] - , group "successfully advance to failed state: timeout" $ - map - ( \(name, initialState) -> - validatorSucceedsWith - name - (proposalValidator Shared.proposal) - ( ProposalDatum - { proposalId = ProposalId 0 - , effects = - AssocMap.fromList - [ (ResultTag 0, AssocMap.empty) - , (ResultTag 1, AssocMap.empty) + in [ Advance.mkTestTree' + "to next state" + mkName + (Advance.mkValidToNextStateBundles cs es) + allValid + , Advance.mkTestTree' + "to failed state" + mkName + (Advance.mkValidToFailedStateBundles cs es) + allValid ] - , status = initialState - , cosigners = [signer] - , thresholds = def - , votes = - ProposalVotes - ( AssocMap.fromList - [ - ( ResultTag 0 - , case initialState of - Draft -> 0 - _ -> untag (def :: ProposalThresholds).vote + 1 - ) - , (ResultTag 1, 0) - ] - ) - , timingConfig = def - , startingTime = ProposalStartingTime 0 - } - ) - AdvanceProposal - ( ScriptContext - ( Proposal.advanceProposalFailureTimeout - Proposal.TransitionParameters - { Proposal.initialProposalStatus = initialState - , Proposal.proposalStartingTime = ProposalStartingTime 0 + , group + "illegal" + [ Advance.mkTestTree' + "advance finished proposals" + (const "(negative test)") + (Advance.mkFromFinishedBundles cs es) + Advance.Validity + { forProposalValidator = False + , forStakeValidator = True + , forGovernorValidator = Just False + , forAuthorityTokenPolicy = Just True } - ) - (Spending Proposal.proposalRef) - ) - ) - [ ("Draft -> Finished", Draft) - , ("VotingReady -> Finished", VotingReady) - , ("Locked -> Finished", Locked) - ] - , validatorFailsWith - "illegal: insufficient votes" - (proposalValidator Shared.proposal) - ( ProposalDatum - { proposalId = ProposalId 0 - , effects = - AssocMap.fromList - [ (ResultTag 0, AssocMap.empty) - , (ResultTag 1, AssocMap.empty) - ] - , status = VotingReady - , cosigners = [signer] - , thresholds = def - , votes = - ProposalVotes - ( AssocMap.fromList - [ (ResultTag 0, 1) - , (ResultTag 1, 0) - ] - ) - , timingConfig = def - , startingTime = ProposalStartingTime 0 - } - ) - AdvanceProposal - ( ScriptContext - Proposal.advanceProposalInsufficientVotes - (Spending Proposal.proposalRef) - ) - , validatorFailsWith - "illegal: initial state is Finished" - (proposalValidator Shared.proposal) - ( ProposalDatum - { proposalId = ProposalId 0 - , effects = - AssocMap.fromList - [ (ResultTag 0, AssocMap.empty) - , (ResultTag 1, AssocMap.empty) - ] - , status = Finished - , cosigners = [signer] - , thresholds = def - , votes = - ProposalVotes - ( AssocMap.fromList - [ (ResultTag 0, untag (def :: ProposalThresholds).vote + 1) - , (ResultTag 1, 0) - ] - ) - , timingConfig = def - , startingTime = ProposalStartingTime 0 - } - ) - AdvanceProposal - ( ScriptContext - Proposal.advanceFinishedProposal - (Spending Proposal.proposalRef) - ) - , validatorFailsWith - "illegal: with stake input" - (proposalValidator Shared.proposal) - ( ProposalDatum - { proposalId = ProposalId 0 - , effects = - AssocMap.fromList - [ (ResultTag 0, AssocMap.empty) - , (ResultTag 1, AssocMap.empty) - ] - , status = VotingReady - , cosigners = [signer] - , thresholds = def - , votes = - ProposalVotes - ( AssocMap.fromList - [ (ResultTag 0, 0) - , (ResultTag 1, 0) - ] - ) - , timingConfig = def - , startingTime = ProposalStartingTime 0 - } - ) - AdvanceProposal - ( ScriptContext - Proposal.advanceProposalWithInvalidOutputStake - (Spending Proposal.proposalRef) - ) - ] - , group "unlocking" $ do - proposalCount <- [1, 42] - - let legalGroup = group "legal" $ do - let voterRetractVotesAndUnlockStakeWhileVoting = - UnlockStake.mkProposalValidatorTestCase - UnlockStake.UnlockStakeParameters - { UnlockStake.proposalCount = proposalCount - , UnlockStake.stakeUsage = UnlockStake.Voter - , UnlockStake.retractVotes = True - , UnlockStake.proposalStatus = VotingReady - } - True - creatorUnlockStakeWhileFinished = - UnlockStake.mkProposalValidatorTestCase - UnlockStake.UnlockStakeParameters - { UnlockStake.proposalCount = proposalCount - , UnlockStake.stakeUsage = UnlockStake.Creator - , UnlockStake.retractVotes = False - , UnlockStake.proposalStatus = Finished - } - True - - let voterUnlockStakeAfterVoting = group "voter unlocks stake after voting" $ do - status <- [Finished, Locked] + , Advance.mkTestTree + "insufficient cosigns" + (Advance.mkInsufficientCosignsBundle cs es) + Advance.Validity + { forProposalValidator = False + , forStakeValidator = True + , forGovernorValidator = Nothing + , forAuthorityTokenPolicy = Nothing + } + , Advance.mkTestTree + "insufficient votes" + (Advance.mkInsufficientVotesBundle cs es) + Advance.Validity + { forProposalValidator = False + , forStakeValidator = True + , forGovernorValidator = Nothing + , forAuthorityTokenPolicy = Nothing + } + , Advance.mkTestTree + "ambiguous winning effect" + (Advance.mkAmbiguousWinnerBundle cs es) + Advance.Validity + { forProposalValidator = False + , forStakeValidator = True + , forGovernorValidator = Nothing + , forAuthorityTokenPolicy = Nothing + } + , Advance.mkTestTree' + "to next state too late" + (\b -> unwords ["from", show b.proposalParameters.fromStatus]) + (Advance.mkToNextStateTooLateBundles cs es) + Advance.Validity + { forProposalValidator = False + , forStakeValidator = True + , forGovernorValidator = Just True + , forAuthorityTokenPolicy = Just True + } + , Advance.mkTestTree' + "altered output stake datum" + (\b -> unwords ["from", show b.proposalParameters.fromStatus]) + (Advance.mkInvalidOutputStakeBundles cs es) + Advance.Validity + { forProposalValidator = False + , forStakeValidator = False + , forGovernorValidator = Just True + , forAuthorityTokenPolicy = Just True + } + , Advance.mkTestTree + "forget to mint GATs" + (Advance.mkNoGATMintedBundle cs es) + Advance.Validity + { forProposalValidator = True + , forStakeValidator = True + , forGovernorValidator = Just False + , forAuthorityTokenPolicy = Nothing + } + , Advance.mkTestTree + "mint GATs for wrong validators" + (Advance.mkMintGATsForWrongEffectsBundle cs es) + Advance.Validity + { forProposalValidator = True + , forStakeValidator = True + , forGovernorValidator = Just False + , forAuthorityTokenPolicy = Just True + } + , Advance.mkTestTree + "mint GATs with bad token name" + (Advance.mkMintGATsWithoutTagBundle cs es) + Advance.Validity + { forProposalValidator = True + , forStakeValidator = True + , forGovernorValidator = Just False + , forAuthorityTokenPolicy = Just False + } + , Advance.mkTestTree + "wrong GAT datum" + (Advance.mkGATsWithWrongDatumBundle cs es) + Advance.Validity + { forProposalValidator = True + , forStakeValidator = True + , forGovernorValidator = Just False + , forAuthorityTokenPolicy = Just True + } + , Advance.mkTestTree + "invalid governor output datum" + (Advance.mkBadGovernorOutputDatumBundle cs es) + Advance.Validity + { forProposalValidator = True + , forStakeValidator = True + , forGovernorValidator = Just False + , forAuthorityTokenPolicy = Just True + } + ] + ] + , group "unlocking" $ + let proposalCountCases = [1, 5, 10, 42] - pure $ - UnlockStake.mkProposalValidatorTestCase - UnlockStake.UnlockStakeParameters - { UnlockStake.proposalCount = proposalCount - , UnlockStake.stakeUsage = UnlockStake.Voter - , UnlockStake.retractVotes = False - , UnlockStake.proposalStatus = status - } - True + mkSubgroupName nProposals = unwords ["with", show nProposals, "proposals"] - [ voterRetractVotesAndUnlockStakeWhileVoting - , creatorUnlockStakeWhileFinished - , voterUnlockStakeAfterVoting + mkLegalGroup nProposals = + group + (mkSubgroupName nProposals) + [ UnlockStake.mkTestTree + "voter: retract votes while voting" + (UnlockStake.mkVoterRetractVotesWhileVotingParameters nProposals) + True + , UnlockStake.mkTestTree + "voter/creator: retract votes while voting" + (UnlockStake.mkVoterCreatorRetractVotesWhileVotingParameters nProposals) + True + , UnlockStake.mkTestTree + "creator: remove creator locks when finished" + (UnlockStake.mkCreatorRemoveCreatorLocksWhenFinishedParameters nProposals) + True + , UnlockStake.mkTestTree + "voter/creator: remove all locks when finished" + (UnlockStake.mkVoterCreatorRemoveAllLocksWhenFinishedParameters nProposals) + True + , group "voter: unlock after voting" $ + map + ( \ps -> + let name = show ps.proposalStatus + in UnlockStake.mkTestTree name ps True + ) + (UnlockStake.mkVoterUnlockStakeAfterVotingParameters nProposals) + , UnlockStake.mkTestTree + "voter/creator: remove vote locks when locked" + (UnlockStake.mkVoterCreatorRemoveVoteLocksWhenLockedParameters nProposals) + True ] - let illegalGroup = group "illegal" $ do - let retractsVotesWhileNotVotingReady = - group "voter retracts votes while not voting" $ do - status <- [Draft, Locked, Finished] - - pure $ - UnlockStake.mkProposalValidatorTestCase - UnlockStake.UnlockStakeParameters - { UnlockStake.proposalCount = proposalCount - , UnlockStake.stakeUsage = UnlockStake.Voter - , UnlockStake.retractVotes = True - , UnlockStake.proposalStatus = status - } - False - - unlockIrrelevantStake = - group "unlock an irrelevant stake" $ do - status <- [Draft, VotingReady, Locked, Finished] - shouldRetractVotes <- [True, False] - - pure $ - UnlockStake.mkProposalValidatorTestCase - UnlockStake.UnlockStakeParameters - { UnlockStake.proposalCount = proposalCount - , UnlockStake.stakeUsage = UnlockStake.Irrelevant - , UnlockStake.retractVotes = shouldRetractVotes - , UnlockStake.proposalStatus = status - } - False - - unlockCreatorStakeBeforeFinished = - group "unlock creator stake before finished" $ do - status <- [Draft, VotingReady, Locked] - - pure $ - UnlockStake.mkProposalValidatorTestCase - UnlockStake.UnlockStakeParameters - { UnlockStake.proposalCount = proposalCount - , UnlockStake.stakeUsage = UnlockStake.Creator - , UnlockStake.retractVotes = False - , UnlockStake.proposalStatus = status - } - False - retractVotesWithCreatorStake = - group "creator stake retracts votes" $ do - status <- [Draft, VotingReady, Locked, Finished] - - pure $ - UnlockStake.mkProposalValidatorTestCase - UnlockStake.UnlockStakeParameters - { UnlockStake.proposalCount = proposalCount - , UnlockStake.stakeUsage = UnlockStake.Creator - , UnlockStake.retractVotes = True - , UnlockStake.proposalStatus = status - } - False - - [ retractsVotesWhileNotVotingReady - , unlockIrrelevantStake - , unlockCreatorStakeBeforeFinished - , retractVotesWithCreatorStake + mkIllegalGroup nProposals = + group + (mkSubgroupName nProposals) + [ group "retract votes while not voting" $ + map + ( \ps -> + let name = + unwords + [ "role:" + , show ps.stakeRole + , "," + , "status:" + , show ps.proposalStatus + ] + in UnlockStake.mkTestTree name ps False + ) + (UnlockStake.mkRetractVotesWhileNotVoting nProposals) + , group "unlock an irrelevant stake" $ + map + ( \ps -> + let name = + unwords + [ "status:" + , show ps.proposalStatus + , "retract votes:" + , show ps.retractVotes + ] + in UnlockStake.mkTestTree name ps False + ) + (UnlockStake.mkUnockIrrelevantStakeParameters nProposals) + , group "remove creator too early" $ + map + ( \ps -> + let name = + unwords + ["status:", show ps.proposalStatus] + in UnlockStake.mkTestTree name ps False + ) + (UnlockStake.mkRemoveCreatorLockBeforeFinishedParameters nProposals) + , UnlockStake.mkTestTree + "creator: retract votes" + (UnlockStake.mkRetractVotesWithCreatorStakeParamaters nProposals) + False + , group "alter output stake datum" $ + map + ( \ps -> + let name = + unwords + [ "role:" + , show ps.stakeRole + , "," + , "status:" + , show ps.proposalStatus + ] + in UnlockStake.mkTestTree name ps False + ) + (UnlockStake.mkAlterStakeParameters nProposals) ] - [legalGroup, illegalGroup] + legalGroup = group "legal" $ map mkLegalGroup proposalCountCases + illegalGroup = group "illegal" $ map mkIllegalGroup proposalCountCases + in [legalGroup, illegalGroup] ] ] diff --git a/agora-specs/Spec/Stake.hs b/agora-specs/Spec/Stake.hs index e8f0c78a..b9e781f6 100644 --- a/agora-specs/Spec/Stake.hs +++ b/agora-specs/Spec/Stake.hs @@ -9,12 +9,14 @@ Tests for Stake policy and validator -} module Spec.Stake (specs) where +import Agora.Scripts (AgoraScripts (..)) import Agora.Stake ( - Stake (..), StakeDatum (StakeDatum), StakeRedeemer (DepositWithdraw), ) -import Agora.Stake.Scripts (stakePolicy, stakeValidator) +import Data.Bool (Bool (..)) +import Data.Maybe (Maybe (..)) +import Sample.Shared (agoraScripts) import Sample.Stake ( DepositWithdrawExample ( DepositWithdrawExample, @@ -24,12 +26,12 @@ import Sample.Stake ( signer, ) import Sample.Stake qualified as Stake ( - stake, stakeCreation, stakeCreationUnsigned, stakeCreationWrongDatum, stakeDepositWithdraw, ) +import Sample.Stake.SetDelegate qualified as SetDelegate import Test.Specification ( SpecificationTree, group, @@ -38,7 +40,6 @@ import Test.Specification ( validatorFailsWith, validatorSucceedsWith, ) -import Test.Util (toDatum) import Prelude (Num (negate), ($)) -- | The SpecificationTree exported by this module. @@ -48,17 +49,17 @@ specs = "policy" [ policySucceedsWith "stakeCreation" - (stakePolicy Stake.stake.gtClassRef) + agoraScripts.compiledStakePolicy () Stake.stakeCreation , policyFailsWith "stakeCreationWrongDatum" - (stakePolicy Stake.stake.gtClassRef) + agoraScripts.compiledStakePolicy () Stake.stakeCreationWrongDatum , policyFailsWith "stakeCreationUnsigned" - (stakePolicy Stake.stake.gtClassRef) + agoraScripts.compiledStakePolicy () Stake.stakeCreationUnsigned ] @@ -66,21 +67,48 @@ specs = "validator" [ validatorSucceedsWith "stakeDepositWithdraw deposit" - (stakeValidator Stake.stake) - (toDatum $ StakeDatum 100_000 signer []) - (toDatum $ DepositWithdraw 100_000) + agoraScripts.compiledStakeValidator + (StakeDatum 100_000 signer Nothing []) + (DepositWithdraw 100_000) (Stake.stakeDepositWithdraw $ DepositWithdrawExample {startAmount = 100_000, delta = 100_000}) , validatorSucceedsWith "stakeDepositWithdraw withdraw" - (stakeValidator Stake.stake) - (toDatum $ StakeDatum 100_000 signer []) - (toDatum $ DepositWithdraw $ negate 100_000) + agoraScripts.compiledStakeValidator + (StakeDatum 100_000 signer Nothing []) + (DepositWithdraw $ negate 100_000) (Stake.stakeDepositWithdraw $ DepositWithdrawExample {startAmount = 100_000, delta = negate 100_000}) , validatorFailsWith "stakeDepositWithdraw negative GT" - (stakeValidator Stake.stake) - (toDatum $ StakeDatum 100_000 signer []) - (toDatum $ DepositWithdraw 1_000_000) + agoraScripts.compiledStakeValidator + (StakeDatum 100_000 signer Nothing []) + (DepositWithdraw 1_000_000) (Stake.stakeDepositWithdraw $ DepositWithdrawExample {startAmount = 100_000, delta = negate 1_000_000}) + , group + "set delegate" + [ SetDelegate.mkTestCase + "override existing delegate" + SetDelegate.overrideExistingDelegateParameters + True + , SetDelegate.mkTestCase + "remove existing delegate" + SetDelegate.clearDelegateParameters + True + , SetDelegate.mkTestCase + "set delegate to something" + SetDelegate.setDelegateParameters + True + , SetDelegate.mkTestCase + "owner doesn't sign the transaction" + SetDelegate.ownerDoesntSignParameters + False + , SetDelegate.mkTestCase + "delegate to the owner" + SetDelegate.delegateToOwnerParameters + False + , SetDelegate.mkTestCase + "invalid output stake" + SetDelegate.invalidOutputStakeDatumParameters + False + ] ] ] diff --git a/agora-specs/Spec/Treasury.hs b/agora-specs/Spec/Treasury.hs index 6d29bc65..03d60fbd 100644 --- a/agora-specs/Spec/Treasury.hs +++ b/agora-specs/Spec/Treasury.hs @@ -25,6 +25,8 @@ import Agora.Treasury ( TreasuryRedeemer (SpendTreasuryGAT), treasuryValidator, ) +import Agora.Utils (CompiledValidator (CompiledValidator)) +import Plutarch.Api.V1 (mkValidator) import PlutusLedgerApi.V1 (DCert (DCertDelegRegKey)) import PlutusLedgerApi.V1.Contexts ( ScriptContext (scriptContextPurpose, scriptContextTxInfo), @@ -35,7 +37,7 @@ import PlutusLedgerApi.V1.Credential ( StakingCredential (StakingHash), ) import PlutusLedgerApi.V1.Value qualified as Value (singleton) -import Sample.Shared (trCredential) +import Sample.Shared (deterministicTracingConfing, trCredential) import Sample.Treasury ( gatCs, gatTn, @@ -51,6 +53,12 @@ import Test.Specification ( validatorSucceedsWith, ) +compiledTreasuryValidator :: CompiledValidator () TreasuryRedeemer +compiledTreasuryValidator = + CompiledValidator $ + mkValidator deterministicTracingConfing $ + treasuryValidator gatCs + specs :: [SpecificationTree] specs = [ group @@ -59,7 +67,7 @@ specs = "Positive" [ validatorSucceedsWith "Allows for effect changes" - (treasuryValidator gatCs) + compiledTreasuryValidator () SpendTreasuryGAT validCtx @@ -70,7 +78,7 @@ specs = "Fails with ScriptPurpose not Minting" [ validatorFailsWith "Spending" - (treasuryValidator gatCs) + compiledTreasuryValidator () SpendTreasuryGAT validCtx @@ -78,7 +86,7 @@ specs = } , validatorFailsWith "Rewarding" - (treasuryValidator gatCs) + compiledTreasuryValidator () SpendTreasuryGAT validCtx @@ -88,7 +96,7 @@ specs = } , validatorFailsWith "Certifying" - (treasuryValidator gatCs) + compiledTreasuryValidator () SpendTreasuryGAT validCtx @@ -100,7 +108,7 @@ specs = ] , validatorFailsWith -- TODO: Use QuickCheck. "Fails when multiple GATs burned" - (treasuryValidator gatCs) + compiledTreasuryValidator () SpendTreasuryGAT validCtx @@ -115,13 +123,13 @@ specs = } , validatorFailsWith "Fails when GAT token name is not script address" - (treasuryValidator gatCs) + compiledTreasuryValidator () SpendTreasuryGAT trCtxGATNameNotAddress , validatorFailsWith "Fails with wallet as input" - (treasuryValidator gatCs) + compiledTreasuryValidator () SpendTreasuryGAT ( let txInfo = validCtx.scriptContextTxInfo diff --git a/agora-test/Spec.hs b/agora-test/Spec.hs index e11a5e13..ed7b9838 100644 --- a/agora-test/Spec.hs +++ b/agora-test/Spec.hs @@ -8,7 +8,6 @@ import Test.Tasty (defaultMain, testGroup) -------------------------------------------------------------------------------- import Property.Governor qualified as Governer -import Property.MultiSig qualified as MultiSig import Spec.AuthorityToken qualified as AuthorityToken import Spec.Effect.GovernorMutation qualified as GovernorMutation import Spec.Effect.TreasuryWithdrawal qualified as TreasuryWithdrawal @@ -42,7 +41,4 @@ main = do , testGroup "Utility tests" Utils.tests - , testGroup - "Multisig tests" - MultiSig.props ] diff --git a/agora-testlib/Test/Specification.hs b/agora-testlib/Test/Specification.hs index e228a688..2280af96 100644 --- a/agora-testlib/Test/Specification.hs +++ b/agora-testlib/Test/Specification.hs @@ -42,16 +42,25 @@ module Test.Specification ( validatorFailsWith, effectSucceedsWith, effectFailsWith, + testValidator, + testPolicy, -- * Converters toTestTree, ) where -import Plutarch.Api.V1 (PMintingPolicy, PValidator) -import Plutarch.Builtin (pforgetData) +import Agora.Utils (CompiledEffect (..), CompiledMintingPolicy (..), CompiledValidator (..)) +import Control.Composition ((.**), (.***)) +import Data.Coerce (coerce) import Plutarch.Evaluate (evalScript) -import Plutarch.Lift (PUnsafeLiftDecl (PLifted)) -import PlutusLedgerApi.V1 (Script, ScriptContext) +import PlutusLedgerApi.V1 ( + Datum (..), + Redeemer (Redeemer), + Script, + ScriptContext, + ToData (toBuiltinData), + ) +import PlutusLedgerApi.V1.Scripts (Context (..), applyMintingPolicyScript, applyValidator) import PlutusTx.IsData qualified as PlutusTx (ToData) import Test.Tasty (TestTree, testGroup) import Test.Tasty.HUnit (assertFailure, testCase) @@ -150,106 +159,152 @@ scriptSucceeds name script = Terminal $ Specification name Success script scriptFails :: String -> Script -> SpecificationTree scriptFails name script = Terminal $ Specification name Failure script +mkContext :: ScriptContext -> Context +mkContext = Context . toBuiltinData + +mkRedeemer :: + forall redeemer. + (PlutusTx.ToData redeemer) => + redeemer -> + Redeemer +mkRedeemer = Redeemer . toBuiltinData + +mkDatum :: + forall datum. + (PlutusTx.ToData datum) => + datum -> + Datum +mkDatum = Datum . toBuiltinData + +applyMintingPolicy' :: + (PlutusTx.ToData redeemer) => + CompiledMintingPolicy redeemer -> + redeemer -> + ScriptContext -> + Script +applyMintingPolicy' policy redeemer scriptContext = + applyMintingPolicyScript + (mkContext scriptContext) + (getCompiledMintingPolicy policy) + (mkRedeemer redeemer) + +applyValidator' :: + ( PlutusTx.ToData datum + , PlutusTx.ToData redeemer + ) => + CompiledValidator datum redeemer -> + datum -> + redeemer -> + ScriptContext -> + Script +applyValidator' validator datum redeemer scriptContext = + applyValidator + (mkContext scriptContext) + (getCompiledValidator validator) + (mkDatum datum) + (mkRedeemer redeemer) + -- | Check that a policy script succeeds, given a name and arguments. policySucceedsWith :: - ( PLift redeemer - , PlutusTx.ToData (PLifted redeemer) - ) => + (PlutusTx.ToData redeemer) => String -> - ClosedTerm PMintingPolicy -> - PLifted redeemer -> + CompiledMintingPolicy redeemer -> + redeemer -> ScriptContext -> SpecificationTree -policySucceedsWith tag policy redeemer scriptContext = - scriptSucceeds tag $ - compile - ( policy - # pforgetData (pconstantData redeemer) - # pconstant scriptContext - ) +policySucceedsWith tag = + scriptSucceeds tag .** applyMintingPolicy' -- | Check that a policy script fails, given a name and arguments. policyFailsWith :: - ( PLift redeemer - , PlutusTx.ToData (PLifted redeemer) - ) => + (PlutusTx.ToData redeemer) => String -> - ClosedTerm PMintingPolicy -> - PLifted redeemer -> + CompiledMintingPolicy redeemer -> + redeemer -> ScriptContext -> SpecificationTree -policyFailsWith tag policy redeemer scriptContext = - scriptFails tag $ - compile - ( policy - # pforgetData (pconstantData redeemer) - # pconstant scriptContext - ) +policyFailsWith tag = + scriptFails tag .** applyMintingPolicy' -- | Check that a validator script succeeds, given a name and arguments. validatorSucceedsWith :: - ( PLift datum - , PlutusTx.ToData (PLifted datum) - , PLift redeemer - , PlutusTx.ToData (PLifted redeemer) + ( PlutusTx.ToData datum + , PlutusTx.ToData redeemer ) => String -> - ClosedTerm PValidator -> - PLifted datum -> - PLifted redeemer -> + CompiledValidator datum redeemer -> + datum -> + redeemer -> ScriptContext -> SpecificationTree -validatorSucceedsWith tag validator datum redeemer scriptContext = - scriptSucceeds tag $ - compile - ( validator - # pforgetData (pconstantData datum) - # pforgetData (pconstantData redeemer) - # pconstant scriptContext - ) +validatorSucceedsWith tag = + scriptSucceeds tag .*** applyValidator' -- | Check that a validator script fails, given a name and arguments. validatorFailsWith :: - ( PLift datum - , PlutusTx.ToData (PLifted datum) - , PLift redeemer - , PlutusTx.ToData (PLifted redeemer) + ( PlutusTx.ToData datum + , PlutusTx.ToData redeemer ) => String -> - ClosedTerm PValidator -> - PLifted datum -> - PLifted redeemer -> + CompiledValidator datum redeemer -> + datum -> + redeemer -> ScriptContext -> SpecificationTree -validatorFailsWith tag validator datum redeemer scriptContext = - scriptFails tag $ - compile - ( validator - # pforgetData (pconstantData datum) - # pforgetData (pconstantData redeemer) - # pconstant scriptContext - ) +validatorFailsWith tag = + scriptFails tag .*** applyValidator' -- | Check that an effect succeeds, given a name and argument. effectSucceedsWith :: - ( PLift datum - , PlutusTx.ToData (PLifted datum) + ( PlutusTx.ToData datum ) => String -> - ClosedTerm PValidator -> - PLifted datum -> + CompiledEffect datum -> + datum -> ScriptContext -> SpecificationTree -effectSucceedsWith tag eff datum = validatorSucceedsWith tag eff datum () +effectSucceedsWith tag eff datum = validatorSucceedsWith tag (coerce eff) datum () -- | Check that an effect fails, given a name and argument. effectFailsWith :: - ( PLift datum - , PlutusTx.ToData (PLifted datum) + ( PlutusTx.ToData datum ) => String -> - ClosedTerm PValidator -> - PLifted datum -> + CompiledEffect datum -> + datum -> + ScriptContext -> + SpecificationTree +effectFailsWith tag eff datum = validatorFailsWith tag (coerce eff) datum () + +-- | Test a validator, given the expectation as a boolean value. +testValidator :: + forall datum redeemer. + (PlutusTx.ToData datum, PlutusTx.ToData redeemer) => + -- | Is this test case expected to succeed? + Bool -> + String -> + CompiledValidator datum redeemer -> + datum -> + redeemer -> + ScriptContext -> + SpecificationTree +testValidator isValid = + if isValid + then validatorSucceedsWith + else validatorFailsWith + +-- | Test a policy, given the expectation as a boolean value. +testPolicy :: + forall redeemer. + (PlutusTx.ToData redeemer) => + -- | Is this test case expected to succeed? + Bool -> + String -> + CompiledMintingPolicy redeemer -> + redeemer -> ScriptContext -> SpecificationTree -effectFailsWith tag eff datum = validatorFailsWith tag eff datum () +testPolicy isValid = + if isValid + then policySucceedsWith + else policyFailsWith diff --git a/agora-testlib/Test/Util.hs b/agora-testlib/Test/Util.hs index 78600a55..d0b0a7bb 100644 --- a/agora-testlib/Test/Util.hs +++ b/agora-testlib/Test/Util.hs @@ -13,22 +13,46 @@ module Test.Util ( updateMap, sortMap, sortValue, + blake2b_224, + pubKeyHashes, + userCredentials, + scriptCredentials, + validatorHashes, + groupsOfN, + mkSpending, + mkMinting, + CombinableBuilder, ) where -------------------------------------------------------------------------------- -import Prelude - --------------------------------------------------------------------------------- - import Codec.Serialise (serialise) -import Data.ByteString.Lazy qualified as ByteString.Lazy - --------------------------------------------------------------------------------- - +import Crypto.Hash qualified as Crypto import Data.Bifunctor (second) +import Data.ByteArray qualified as BA +import Data.ByteString qualified as BS +import Data.ByteString.Char8 qualified as C +import Data.ByteString.Lazy qualified as ByteString.Lazy import Data.List (sortOn) +import Plutarch.Context ( + Builder, + buildMintingUnsafe, + buildSpendingUnsafe, + withMinting, + withSpendingOutRef, + ) import Plutarch.Crypto (pblake2b_256) +import PlutusLedgerApi.V1 ( + Credential ( + PubKeyCredential, + ScriptCredential + ), + CurrencySymbol, + PubKeyHash (..), + ScriptContext, + TxOutRef, + ValidatorHash (ValidatorHash), + ) import PlutusLedgerApi.V1.Interval qualified as PlutusTx import PlutusLedgerApi.V1.Scripts (Datum (Datum), DatumHash (DatumHash)) import PlutusLedgerApi.V1.Value (Value (..)) @@ -36,6 +60,7 @@ import PlutusTx.AssocMap qualified as AssocMap import PlutusTx.Builtins qualified as PlutusTx import PlutusTx.IsData qualified as PlutusTx import PlutusTx.Ord qualified as PlutusTx +import Prelude -------------------------------------------------------------------------------- @@ -92,12 +117,16 @@ updateMap f k = -------------------------------------------------------------------------------- +-- | Sort the given 'AssocMap.Map' by keys in ascending order. sortMap :: forall k v. Ord k => AssocMap.Map k v -> AssocMap.Map k v sortMap = AssocMap.fromList . sortOn fst . AssocMap.toList +{- | Sort the given 'Value' in ascending order. Some plutarch functions that + work with plutarch's 'Sorted' 'PMap' require this to work correctly. +-} sortValue :: Value -> Value sortValue = Value @@ -106,3 +135,75 @@ sortValue = . fmap (second sortMap) . AssocMap.toList . getValue + +-------------------------------------------------------------------------------- + +-- | Compute the hash of a given byte string using blake2b_224 algorithm. +blake2b_224 :: BS.ByteString -> BS.ByteString +blake2b_224 = BS.pack . BA.unpack . Crypto.hashWith Crypto.Blake2b_224 + +-- | An infinite list of blake2b_224 hashes. +blake2b_224Hashes :: [BS.ByteString] +blake2b_224Hashes = blake2b_224 . C.pack . show @Integer <$> [0 ..] + +-- | An infinite list of *valid* 'PubKeyHash'. +pubKeyHashes :: [PubKeyHash] +pubKeyHashes = PubKeyHash . PlutusTx.toBuiltin <$> blake2b_224Hashes + +-- | An infinite list of *valid* user credentials. +userCredentials :: [Credential] +userCredentials = PubKeyCredential <$> pubKeyHashes + +-- | An infinite list of *valid* validator hashes. +validatorHashes :: [ValidatorHash] +validatorHashes = ValidatorHash . PlutusTx.toBuiltin <$> blake2b_224Hashes + +-- | An infinite list of *valid* script credentials. +scriptCredentials :: [Credential] +scriptCredentials = ScriptCredential <$> validatorHashes + +-------------------------------------------------------------------------------- + +-- | Turn the given list in to groups which have the given length. +groupsOfN :: Int -> [a] -> [[a]] +groupsOfN _ [] = [] +groupsOfN n xs = + let (nextGroup, rest) = next n xs + in nextGroup : groupsOfN n rest + where + next :: Int -> [a] -> ([a], [a]) + next _ [] = ([], []) + next 0 xs = ([], xs) + next n (x : xs) = + let (xs', rest) = next (n - 1) xs + in (x : xs', rest) + +-------------------------------------------------------------------------------- + +{- | Given the builder generator and the parameters, create a 'ScriptContext' + that spends the UTXO that referenced by the given 'TxOutRef'. +-} +mkSpending :: + forall ps. + (forall b. (Monoid b, Builder b) => ps -> b) -> + ps -> + TxOutRef -> + ScriptContext +mkSpending mkBuilder ps oref = + buildSpendingUnsafe $ + mkBuilder ps <> withSpendingOutRef oref + +{- | Given the builder generator and the parameters, create a 'ScriptContext' + that mints the token of the given currency symbol. +-} +mkMinting :: + forall ps. + (forall b. (Monoid b, Builder b) => ps -> b) -> + ps -> + CurrencySymbol -> + ScriptContext +mkMinting mkBuilder ps cs = + buildMintingUnsafe $ + mkBuilder ps <> withMinting cs + +type CombinableBuilder b = (Monoid b, Builder b) diff --git a/agora.cabal b/agora.cabal index 8e8ba53d..d9819e16 100644 --- a/agora.cabal +++ b/agora.cabal @@ -1,6 +1,6 @@ cabal-version: 3.0 name: agora -version: 0.1.0 +version: 0.2.0 extra-source-files: CHANGELOG.md author: Emily Martins license: Apache-2.0 @@ -12,11 +12,11 @@ license: Apache-2.0 common lang ghc-options: - -Wall -Wcompat -Wincomplete-uni-patterns -Wno-unused-do-bind - -Wno-partial-type-signatures -Wmissing-export-lists - -Wincomplete-record-updates -Wmissing-deriving-strategies - -Wno-name-shadowing -Wunused-foralls -fprint-explicit-foralls - -fprint-explicit-kinds -Werror + -Werror -Wall -Wcompat -Wincomplete-uni-patterns + -Wno-unused-do-bind -Wno-partial-type-signatures + -Wmissing-export-lists -Wincomplete-record-updates + -Wmissing-deriving-strategies -Wno-name-shadowing -Wunused-foralls + -fprint-explicit-foralls -fprint-explicit-kinds -Wunused-do-bind mixins: base hiding (Prelude), @@ -39,6 +39,7 @@ common lang DerivingStrategies DerivingVia DoAndIfThenElse + DuplicateRecordFields EmptyCase EmptyDataDecls EmptyDataDeriving @@ -88,10 +89,13 @@ common deps build-depends: , aeson , ansi-terminal - , base >=4.14 && <5 + , base >=4.14 && <5 , base-compat + , base16 , bytestring + , cardano-binary , cardano-prelude + , composition-prelude , containers , data-default , data-default-class @@ -100,6 +104,7 @@ common deps , plutarch , plutarch-numeric , plutarch-safe-money + , plutarch-script-export , plutus-core , plutus-ledger-api , plutus-tx @@ -137,28 +142,27 @@ common exe-opts library import: lang, deps exposed-modules: + Agora.Aeson.Orphans Agora.AuthorityToken + Agora.Bootstrap Agora.Effect Agora.Effect.GovernorMutation Agora.Effect.NoOp Agora.Effect.TreasuryWithdrawal Agora.Governor Agora.Governor.Scripts - Agora.MultiSig + Agora.Plutarch.Orphans Agora.Proposal Agora.Proposal.Scripts Agora.Proposal.Time Agora.SafeMoney - Agora.ScriptInfo + Agora.Scripts Agora.Stake Agora.Stake.Scripts Agora.Treasury Agora.Utils other-modules: - Agora.Aeson.Orphans - Agora.Plutarch.Orphans - hs-source-dirs: agora library pprelude @@ -182,15 +186,19 @@ library agora-specs exposed-modules: Property.Generator Property.Governor - Property.MultiSig Sample.Effect.GovernorMutation Sample.Effect.TreasuryWithdrawal - Sample.Governor - Sample.Proposal + Sample.Governor.Initialize + Sample.Governor.Mutate + Sample.Proposal.Advance + Sample.Proposal.Cosign + Sample.Proposal.Create Sample.Proposal.Shared Sample.Proposal.UnlockStake + Sample.Proposal.Vote Sample.Shared Sample.Stake + Sample.Stake.SetDelegate Sample.Treasury Spec.AuthorityToken Spec.Effect.GovernorMutation @@ -232,13 +240,12 @@ benchmark agora-bench executable agora-scripts import: lang, deps, exe-opts - main-is: Scripts.hs + main-is: Main.hs hs-source-dirs: agora-scripts - other-modules: Options + other-modules: build-depends: , agora , gitrev - , optparse-applicative executable agora-purescript-bridge import: lang, deps, exe-opts diff --git a/agora/Agora/Aeson/Orphans.hs b/agora/Agora/Aeson/Orphans.hs index 75ff1aff..2408add3 100644 --- a/agora/Agora/Aeson/Orphans.hs +++ b/agora/Agora/Aeson/Orphans.hs @@ -20,6 +20,7 @@ import Data.Text.Encoding qualified as T import PlutusLedgerApi.V1 qualified as Plutus import PlutusLedgerApi.V1.Bytes qualified as Plutus +import PlutusLedgerApi.V1.Scripts qualified as Plutus import PlutusLedgerApi.V1.Value qualified as Plutus -------------------------------------------------------------------------------- @@ -109,6 +110,24 @@ deriving via instance (Aeson.FromJSON Plutus.ValidatorHash) +deriving via + (AsBase16Bytes Plutus.ScriptHash) + instance + (Aeson.ToJSON Plutus.ScriptHash) +deriving via + (AsBase16Bytes Plutus.ScriptHash) + instance + (Aeson.FromJSON Plutus.ScriptHash) + +deriving via + (AsBase16Bytes Plutus.BuiltinByteString) + instance + (Aeson.ToJSON Plutus.BuiltinByteString) +deriving via + (AsBase16Bytes Plutus.BuiltinByteString) + instance + (Aeson.FromJSON Plutus.BuiltinByteString) + deriving via (AsBase16Codec Plutus.Validator) instance diff --git a/agora/Agora/AuthorityToken.hs b/agora/Agora/AuthorityToken.hs index af97e96e..630c07dd 100644 --- a/agora/Agora/AuthorityToken.hs +++ b/agora/Agora/AuthorityToken.hs @@ -12,7 +12,6 @@ module Agora.AuthorityToken ( AuthorityToken (..), ) where -import GHC.Generics qualified as GHC import Plutarch.Api.V1 ( AmountGuarantees, KeyGuarantees, @@ -33,7 +32,7 @@ import "liqwid-plutarch-extra" Plutarch.Api.V1.Value (psymbolValueOf) import "plutarch" Plutarch.Api.V1.Value (PValue (PValue)) import Plutarch.Builtin (pforgetData) import Plutarch.Extra.List (plookup) -import Plutarch.Extra.TermCont (pguardC, pmatchC) +import Plutarch.Extra.TermCont (pguardC, pletFieldsC, pmatchC) import PlutusLedgerApi.V1.Value (AssetClass (AssetClass)) -------------------------------------------------------------------------------- @@ -53,7 +52,7 @@ newtype AuthorityToken = AuthorityToken } deriving stock ( -- | @since 0.1.0 - GHC.Generic + Generic ) -------------------------------------------------------------------------------- @@ -73,7 +72,7 @@ authorityTokensValidIn :: Term s (PCurrencySymbol :--> PTxOut :--> PBool) authorityTokensValidIn = phoistAcyclic $ plam $ \authorityTokenSym txOut'' -> unTermCont $ do PTxOut txOut' <- pmatchC txOut'' - txOut <- tcont $ pletFields @'["address", "value"] $ txOut' + txOut <- pletFieldsC @'["address", "value"] $ txOut' PAddress address <- pmatchC txOut.address PValue value' <- pmatchC txOut.value PMap value <- pmatchC value' @@ -100,20 +99,18 @@ authorityTokensValidIn = phoistAcyclic $ {- | Assert that a single authority token has been burned. - @since 0.1.0 + @since 0.2.0 -} singleAuthorityTokenBurned :: forall (keys :: KeyGuarantees) (amounts :: AmountGuarantees) (s :: S). Term s PCurrencySymbol -> - Term s (PAsData PTxInfo) -> + Term s (PBuiltinList PTxInInfo) -> Term s (PValue keys amounts) -> Term s PBool -singleAuthorityTokenBurned gatCs txInfo mint = unTermCont $ do +singleAuthorityTokenBurned gatCs inputs mint = unTermCont $ do let gatAmountMinted :: Term _ PInteger gatAmountMinted = psymbolValueOf # gatCs # mint - txInfoF <- tcont $ pletFields @'["inputs"] $ txInfo - pure $ foldr1 (#&&) @@ -122,11 +119,11 @@ singleAuthorityTokenBurned gatCs txInfo mint = unTermCont $ do pall # plam ( \txInInfo' -> unTermCont $ do - PTxInInfo txInInfo <- pmatchC (pfromData txInInfo') + PTxInInfo txInInfo <- pmatchC txInInfo' let txOut' = pfield @"resolved" # txInInfo pure $ authorityTokensValidIn # gatCs # pfromData txOut' ) - # txInfoF.inputs + # inputs ] {- | Policy given 'AuthorityToken' params. @@ -137,9 +134,9 @@ authorityTokenPolicy :: AuthorityToken -> ClosedTerm PMintingPolicy authorityTokenPolicy params = plam $ \_redeemer ctx' -> pmatch ctx' $ \(PScriptContext ctx') -> unTermCont $ do - ctx <- tcont $ pletFields @'["txInfo", "purpose"] ctx' + ctx <- pletFieldsC @'["txInfo", "purpose"] ctx' PTxInfo txInfo' <- pmatchC $ pfromData ctx.txInfo - txInfo <- tcont $ pletFields @'["inputs", "mint", "outputs"] txInfo' + txInfo <- pletFieldsC @'["inputs", "mint", "outputs"] txInfo' let inputs = txInfo.inputs mintedValue = pfromData txInfo.mint AssetClass (govCs, govTn) = params.authority @@ -158,9 +155,7 @@ authorityTokenPolicy params = pguardC "All outputs only emit valid GATs" $ pall # plam - ( (authorityTokensValidIn # ownSymbol #) - . pfromData - ) + (authorityTokensValidIn # ownSymbol #) # txInfo.outputs pure $ popaque $ pconstant () ) diff --git a/agora/Agora/Bootstrap.hs b/agora/Agora/Bootstrap.hs new file mode 100644 index 00000000..17d97d3c --- /dev/null +++ b/agora/Agora/Bootstrap.hs @@ -0,0 +1,67 @@ +{- | Module : Agora.Bootstrap + Maintainer : connor@mlabs.city + Description: Initialize a governance system + + Initialize a governance system +-} +module Agora.Bootstrap (agoraScripts) where + +import Agora.AuthorityToken (AuthorityToken (..), authorityTokenPolicy) +import Agora.Governor (Governor (..)) +import Agora.Governor.Scripts (governorPolicy, governorValidator) +import Agora.Proposal.Scripts (proposalPolicy, proposalValidator) +import Agora.Scripts (AgoraScripts (AgoraScripts)) +import Agora.Scripts qualified as Scripts +import Agora.Stake.Scripts (stakePolicy, stakeValidator) +import Agora.Treasury (treasuryValidator) +import Agora.Utils ( + CompiledMintingPolicy (..), + CompiledValidator (..), + ) +import Plutarch (Config) +import Plutarch.Api.V1 ( + mintingPolicySymbol, + mkMintingPolicy, + mkValidator, + ) +import PlutusLedgerApi.V1.Value (AssetClass (..)) + +{- | Parameterize and precompiled core scripts, given the + 'Agora.Governor.Governor' parameters and plutarch configurations. + + @since 0.2.0 +-} +agoraScripts :: Config -> Governor -> AgoraScripts +agoraScripts conf gov = scripts + where + mkMintingPolicy' = mkMintingPolicy conf + mkValidator' = mkValidator conf + + compiledGovernorPolicy = mkMintingPolicy' $ governorPolicy gov.gstOutRef + compiledGovernorValidator = mkValidator' $ governorValidator scripts + governorSymbol = mintingPolicySymbol compiledGovernorPolicy + governorAssetClass = AssetClass (governorSymbol, "") + + authority = AuthorityToken governorAssetClass + compiledAuthorityPolicy = mkMintingPolicy' $ authorityTokenPolicy authority + authorityTokenSymbol = mintingPolicySymbol compiledAuthorityPolicy + + compiledProposalPolicy = mkMintingPolicy' $ proposalPolicy governorAssetClass + compiledProposalValidator = mkValidator' $ proposalValidator scripts gov.maximumCosigners + + compiledStakePolicy = mkMintingPolicy' $ stakePolicy gov.gtClassRef + compiledStakeValidator = mkValidator' $ stakeValidator scripts gov.gtClassRef + + compiledTreasuryValidator = mkValidator' $ treasuryValidator authorityTokenSymbol + + scripts = + AgoraScripts + { Scripts.compiledGovernorPolicy = CompiledMintingPolicy compiledGovernorPolicy + , Scripts.compiledGovernorValidator = CompiledValidator compiledGovernorValidator + , Scripts.compiledStakePolicy = CompiledMintingPolicy compiledStakePolicy + , Scripts.compiledStakeValidator = CompiledValidator compiledStakeValidator + , Scripts.compiledProposalPolicy = CompiledMintingPolicy compiledProposalPolicy + , Scripts.compiledProposalValidator = CompiledValidator compiledProposalValidator + , Scripts.compiledTreasuryValidator = CompiledValidator compiledTreasuryValidator + , Scripts.compiledAuthorityTokenPolicy = CompiledMintingPolicy compiledAuthorityPolicy + } diff --git a/agora/Agora/Effect.hs b/agora/Agora/Effect.hs index 3a56ed02..4f94426a 100644 --- a/agora/Agora/Effect.hs +++ b/agora/Agora/Effect.hs @@ -8,8 +8,15 @@ Helpers for constructing effects. module Agora.Effect (makeEffect) where import Agora.AuthorityToken (singleAuthorityTokenBurned) -import Plutarch.Api.V1 (PCurrencySymbol, PScriptPurpose (PSpending), PTxInfo, PTxOutRef, PValidator, PValue) -import Plutarch.Extra.TermCont (pguardC, pletC, pmatchC, ptryFromC) +import Plutarch.Api.V1 ( + PCurrencySymbol, + PScriptPurpose (PSpending), + PTxInfo, + PTxOutRef, + PValidator, + PValue, + ) +import Plutarch.Extra.TermCont (pguardC, pletC, pletFieldsC, pmatchC, ptryFromC) import Plutarch.TryFrom () import PlutusLedgerApi.V1.Value (CurrencySymbol) @@ -23,33 +30,32 @@ import PlutusLedgerApi.V1.Value (CurrencySymbol) -} makeEffect :: forall (datum :: PType). - (PIsData datum, PTryFrom PData (PAsData datum)) => + (PTryFrom PData datum, PIsData datum) => CurrencySymbol -> (forall (s :: S). Term s PCurrencySymbol -> Term s datum -> Term s PTxOutRef -> Term s (PAsData PTxInfo) -> Term s POpaque) -> ClosedTerm PValidator makeEffect gatCs' f = plam $ \datum _redeemer ctx' -> unTermCont $ do - ctx <- tcont $ pletFields @'["txInfo", "purpose"] ctx' - txInfo' <- pletC ctx.txInfo + ctx <- pletFieldsC @'["txInfo", "purpose"] ctx' -- convert input datum, PData, into desierable type -- the way this conversion is performed should be defined -- by PTryFrom for each datum in effect script. - (pfromData -> datum', _) <- ptryFromC datum + (datum', _) <- ptryFromC datum -- ensure purpose is Spending. PSpending txOutRef <- pmatchC $ pfromData ctx.purpose txOutRef' <- pletC (pfield @"_0" # txOutRef) -- fetch minted values to ensure single GAT is burned - txInfo <- tcont $ pletFields @'["mint"] txInfo' + txInfo <- pletFieldsC @'["mint", "inputs"] ctx.txInfo let mint :: Term _ (PValue _ _) mint = txInfo.mint -- fetch script context gatCs <- pletC $ pconstant gatCs' - pguardC "A single authority token has been burned" $ singleAuthorityTokenBurned gatCs txInfo' mint + pguardC "A single authority token has been burned" $ singleAuthorityTokenBurned gatCs txInfo.inputs mint -- run effect function - pure $ f gatCs datum' txOutRef' txInfo' + pure $ f gatCs datum' txOutRef' ctx.txInfo diff --git a/agora/Agora/Effect/GovernorMutation.hs b/agora/Agora/Effect/GovernorMutation.hs index 1dbd550c..22f539c8 100644 --- a/agora/Agora/Effect/GovernorMutation.hs +++ b/agora/Agora/Effect/GovernorMutation.hs @@ -20,36 +20,28 @@ module Agora.Effect.GovernorMutation ( import Agora.Effect (makeEffect) import Agora.Governor ( - Governor, GovernorDatum, PGovernorDatum, - governorDatumValid, - ) -import Agora.Governor.Scripts ( - authorityTokenSymbolFromGovernor, - governorSTAssetClassFromGovernor, + pisGovernorDatumValid, ) import Agora.Plutarch.Orphans () -import Agora.Utils ( - isScriptAddress, - mustBePDJust, - mustBePJust, - ) -import GHC.Generics qualified as GHC -import Generics.SOP (Generic, I (I)) +import Agora.Scripts (AgoraScripts, authorityTokenSymbol, governorSTAssetClass) import Plutarch.Api.V1 ( PTxOutRef, PValidator, PValue, ) -import Plutarch.Api.V1.ScriptContext (ptryFindDatum) +import Plutarch.Api.V1.ScriptContext (pisScriptAddress, ptryFindDatum) import "liqwid-plutarch-extra" Plutarch.Api.V1.Value (pvalueOf) import Plutarch.DataRepr ( DerivePConstantViaData (..), PDataFields, - PIsDataReprInstances (PIsDataReprInstances), ) -import Plutarch.Extra.TermCont (pguardC) +import Plutarch.Extra.Maybe ( + passertPDJust, + passertPJust, + ) +import Plutarch.Extra.TermCont (pguardC, pletFieldsC) import Plutarch.Lift (PConstantDecl, PLifted, PUnsafeLiftDecl) import PlutusLedgerApi.V1 (TxOutRef) import PlutusLedgerApi.V1.Value (AssetClass (..)) @@ -67,8 +59,12 @@ data MutateGovernorDatum = MutateGovernorDatum , newDatum :: GovernorDatum -- ^ The new settings for the governor. } - deriving stock (Show, GHC.Generic) - deriving anyclass (Generic) + deriving stock + ( -- | @since 0.1.ç + Show + , -- | @since 0.1.ç + Generic + ) PlutusTx.makeIsDataIndexed ''MutateGovernorDatum [('MutateGovernorDatum, 0)] @@ -89,18 +85,10 @@ newtype PMutateGovernorDatum (s :: S) ) ) deriving stock - ( -- | @since 0.1.0 - GHC.Generic - ) - deriving anyclass ( -- | @since 0.1.0 Generic ) deriving anyclass - ( -- | @since 0.1.0 - PIsDataRepr - ) - deriving ( -- | @since 0.1.0 PlutusType , -- | @since 0.1.0 @@ -110,7 +98,9 @@ newtype PMutateGovernorDatum (s :: S) , -- | @since 0.1.0 PEq ) - via (PIsDataReprInstances PMutateGovernorDatum) + +instance DerivePlutusType PMutateGovernorDatum where + type DPTStrat _ = PlutusTypeData -- | @since 0.1.0 instance PUnsafeLiftDecl PMutateGovernorDatum where type PLifted PMutateGovernorDatum = MutateGovernorDatum @@ -119,7 +109,7 @@ instance PUnsafeLiftDecl PMutateGovernorDatum where type PLifted PMutateGovernor deriving via (DerivePConstantViaData MutateGovernorDatum PMutateGovernorDatum) instance (PConstantDecl MutateGovernorDatum) -- | @since 0.1.0 -deriving via PAsData (PIsDataReprInstances PMutateGovernorDatum) instance PTryFrom PData (PAsData PMutateGovernorDatum) +deriving anyclass instance PTryFrom PData PMutateGovernorDatum -------------------------------------------------------------------------------- @@ -148,11 +138,14 @@ deriving via PAsData (PIsDataReprInstances PMutateGovernorDatum) instance PTryFr @since 0.1.0 -} -mutateGovernorValidator :: Governor -> ClosedTerm PValidator -mutateGovernorValidator gov = makeEffect (authorityTokenSymbolFromGovernor gov) $ +mutateGovernorValidator :: + -- | Lazy precompiled scripts. This is beacuse we need the symbol of GST. + AgoraScripts -> + ClosedTerm PValidator +mutateGovernorValidator as = makeEffect (authorityTokenSymbol as) $ \_gatCs (datum :: Term _ PMutateGovernorDatum) _ txInfo -> unTermCont $ do - datumF <- tcont $ pletFields @'["newDatum", "governorRef"] datum - txInfoF <- tcont $ pletFields @'["mint", "inputs", "outputs", "datums"] txInfo + datumF <- pletFieldsC @'["newDatum", "governorRef"] datum + txInfoF <- pletFieldsC @'["mint", "inputs", "outputs", "datums"] txInfo let mint :: Term _ (PBuiltinList _) mint = pto $ pto $ pto $ pfromData txInfoF.mint @@ -167,7 +160,7 @@ mutateGovernorValidator gov = makeEffect (authorityTokenSymbolFromGovernor gov) ( plam $ \inInfo count -> let address = pfield @"address" #$ pfield @"resolved" # inInfo in pif - (isScriptAddress # address) + (pisScriptAddress # address) (count + 1) count ) @@ -177,7 +170,7 @@ mutateGovernorValidator gov = makeEffect (authorityTokenSymbolFromGovernor gov) -- Find the governor input by looking for GST. let inputWithGST = - mustBePJust # "Governor input not found" #$ pfind + passertPJust # "Governor input not found" #$ pfind # phoistAcyclic ( plam $ \inInfo -> let value = pfield @"value" #$ pfield @"resolved" # inInfo @@ -185,7 +178,7 @@ mutateGovernorValidator gov = makeEffect (authorityTokenSymbolFromGovernor gov) ) # pfromData txInfoF.inputs - govInInfo <- tcont $ pletFields @'["outRef", "resolved"] $ inputWithGST + govInInfo <- pletFieldsC @'["outRef", "resolved"] $ inputWithGST -- The effect can only modify the governor UTXO referenced in the datum. pguardC "Can only modify the pinned governor" $ @@ -196,9 +189,9 @@ mutateGovernorValidator gov = makeEffect (authorityTokenSymbolFromGovernor gov) plength # pfromData txInfoF.outputs #== 1 let govAddress = pfield @"address" #$ govInInfo.resolved - govOutput' = pfromData $ phead # pfromData txInfoF.outputs + govOutput' = phead # pfromData txInfoF.outputs - govOutput <- tcont $ pletFields @'["address", "value", "datumHash"] govOutput' + govOutput <- pletFieldsC @'["address", "value", "datumHash"] govOutput' pguardC "No output to the governor" $ govOutput.address #== govAddress @@ -207,15 +200,14 @@ mutateGovernorValidator gov = makeEffect (authorityTokenSymbolFromGovernor gov) gstValueOf # govOutput.value #== 1 let governorOutputDatumHash = - mustBePDJust # "Governor output doesn't have datum" # govOutput.datumHash + passertPDJust # "Governor output doesn't have datum" # govOutput.datumHash governorOutputDatum = - pfromData @PGovernorDatum $ - mustBePJust # "Governor output datum not found" - #$ ptryFindDatum # governorOutputDatumHash # txInfoF.datums + passertPJust @PGovernorDatum # "Governor output datum not found" + #$ ptryFindDatum # governorOutputDatumHash # txInfoF.datums -- Ensure the output governor datum is what we want. pguardC "Unexpected governor datum" $ datumF.newDatum #== governorOutputDatum - pguardC "New governor datum should be valid" $ governorDatumValid # governorOutputDatum + pguardC "New governor datum should be valid" $ pisGovernorDatumValid # governorOutputDatum return $ popaque $ pconstant () where @@ -223,4 +215,4 @@ mutateGovernorValidator gov = makeEffect (authorityTokenSymbolFromGovernor gov) gstValueOf :: Term s (PValue _ _ :--> PInteger) gstValueOf = phoistAcyclic $ plam $ \v -> pvalueOf # v # pconstant cs # pconstant tn where - AssetClass (cs, tn) = governorSTAssetClassFromGovernor gov + AssetClass (cs, tn) = governorSTAssetClass as diff --git a/agora/Agora/Effect/NoOp.hs b/agora/Agora/Effect/NoOp.hs index 0ff1dc68..4027a6cd 100644 --- a/agora/Agora/Effect/NoOp.hs +++ b/agora/Agora/Effect/NoOp.hs @@ -7,11 +7,9 @@ A dumb effect that only burns its GAT. -} module Agora.Effect.NoOp (noOpValidator, PNoOp) where -import Control.Applicative (Const) - import Agora.Effect (makeEffect) +import Agora.Plutarch.Orphans () import Plutarch.Api.V1 (PValidator) -import Plutarch.TryFrom (PTryFrom (..)) import PlutusLedgerApi.V1.Value (CurrencySymbol) {- | Dummy datum for NoOp effect. @@ -19,22 +17,23 @@ import PlutusLedgerApi.V1.Value (CurrencySymbol) @since 0.1.0 -} newtype PNoOp (s :: S) = PNoOp (Term s PUnit) - deriving + deriving stock + ( -- | @since 0.2.0 + Generic + ) + deriving anyclass ( -- | @since 0.1.0 PlutusType , -- | @since 0.1.0 PIsData ) - via (DerivePNewtype PNoOp PUnit) --- | @since 0.1.0 -instance PTryFrom PData (PAsData PNoOp) where - type PTryFromExcess PData (PAsData PNoOp) = Const () - ptryFrom' _ cont = - -- JUSTIFICATION: - -- We don't care anything about data. - -- It should always be reduced to Unit. - cont (pdata $ pcon $ PNoOp (pconstant ()), ()) +-- | @since 0.2.0 +instance DerivePlutusType PNoOp where + type DPTStrat _ = PlutusTypeNewtype + +-- | @since 0.2.0 +instance PTryFrom PData (PAsData PNoOp) {- | Dummy effect which can only burn its GAT. @@ -42,4 +41,4 @@ instance PTryFrom PData (PAsData PNoOp) where -} noOpValidator :: CurrencySymbol -> ClosedTerm PValidator noOpValidator curr = makeEffect curr $ - \_ (_datum :: Term s PNoOp) _ _ -> popaque (pconstant ()) + \_ (_datum :: Term s (PAsData PNoOp)) _ _ -> popaque (pconstant ()) diff --git a/agora/Agora/Effect/TreasuryWithdrawal.hs b/agora/Agora/Effect/TreasuryWithdrawal.hs index 7c5da3eb..3bb058b2 100644 --- a/agora/Agora/Effect/TreasuryWithdrawal.hs +++ b/agora/Agora/Effect/TreasuryWithdrawal.hs @@ -15,9 +15,6 @@ module Agora.Effect.TreasuryWithdrawal ( import Agora.Effect (makeEffect) import Agora.Plutarch.Orphans () -import Agora.Utils (isPubKey) -import GHC.Generics qualified as GHC -import Generics.SOP (Generic, I (I)) import Plutarch.Api.V1 ( AmountGuarantees (Positive), KeyGuarantees (Sorted), @@ -27,14 +24,13 @@ import Plutarch.Api.V1 ( PValue, ptuple, ) -import Plutarch.Api.V1.ScriptContext (pfindTxInByTxOutRef) +import Plutarch.Api.V1.ScriptContext (pfindTxInByTxOutRef, pisPubKey) import "plutarch" Plutarch.Api.V1.Value (pnormalize) import Plutarch.DataRepr ( DerivePConstantViaData (..), PDataFields, - PIsDataReprInstances (..), ) -import Plutarch.Extra.TermCont (pguardC, pletC, pmatchC) +import Plutarch.Extra.TermCont (pguardC, pletC, pletFieldsC, pmatchC) import Plutarch.Lift (PConstantDecl, PUnsafeLiftDecl (..)) import PlutusLedgerApi.V1.Credential (Credential) import PlutusLedgerApi.V1.Value (CurrencySymbol, Value) @@ -58,10 +54,6 @@ data TreasuryWithdrawalDatum = TreasuryWithdrawalDatum ( -- | @since 0.1.0 Show , -- | @since 0.1.0 - GHC.Generic - ) - deriving anyclass - ( -- | @since 0.1.0 Generic ) @@ -86,16 +78,10 @@ newtype PTreasuryWithdrawalDatum (s :: S) ) ) deriving stock - ( -- | @since 0.1.0 - GHC.Generic - ) - deriving anyclass ( -- | @since 0.1.0 Generic - , -- | @since 0.1.0 - PIsDataRepr ) - deriving + deriving anyclass ( -- | @since 0.1.0 PlutusType , -- | @since 0.1.0 @@ -103,7 +89,9 @@ newtype PTreasuryWithdrawalDatum (s :: S) , -- | @since 0.1.0 PDataFields ) - via PIsDataReprInstances PTreasuryWithdrawalDatum + +instance DerivePlutusType PTreasuryWithdrawalDatum where + type DPTStrat _ = PlutusTypeData -- | @since 0.1.0 instance PUnsafeLiftDecl PTreasuryWithdrawalDatum where @@ -116,10 +104,7 @@ deriving via (PConstantDecl TreasuryWithdrawalDatum) -- | @since 0.1.0 -deriving via - PAsData (PIsDataReprInstances PTreasuryWithdrawalDatum) - instance - PTryFrom PData (PAsData PTreasuryWithdrawalDatum) +instance PTryFrom PData PTreasuryWithdrawalDatum {- | Withdraws given list of values to specific target addresses. It can be evoked by burning GAT. The transaction should have correct @@ -143,26 +128,26 @@ deriving via treasuryWithdrawalValidator :: forall {s :: S}. CurrencySymbol -> Term s PValidator treasuryWithdrawalValidator currSymbol = makeEffect currSymbol $ \_cs (datum' :: Term _ PTreasuryWithdrawalDatum) txOutRef' txInfo' -> unTermCont $ do - datum <- tcont $ pletFields @'["receivers", "treasuries"] datum' - txInfo <- tcont $ pletFields @'["outputs", "inputs"] txInfo' + datum <- pletFieldsC @'["receivers", "treasuries"] datum' + txInfo <- pletFieldsC @'["outputs", "inputs"] txInfo' PJust ((pfield @"resolved" #) -> txOut) <- pmatchC $ pfindTxInByTxOutRef # txOutRef' # pfromData txInfo.inputs - effInput <- tcont $ pletFields @'["address", "value"] $ txOut + effInput <- pletFieldsC @'["address", "value"] $ txOut outputValues <- pletC $ pmap # plam - ( \(pfromData -> txOut') -> unTermCont $ do - txOut <- tcont $ pletFields @'["address", "value"] $ txOut' + ( \txOut' -> unTermCont $ do + txOut <- pletFieldsC @'["address", "value"] $ txOut' let cred = pfield @"credential" # pfromData txOut.address pure . pdata $ ptuple # cred # txOut.value ) - # txInfo.outputs + # pfromData txInfo.outputs inputValues <- pletC $ pmap # plam - ( \((pfield @"resolved" #) . pfromData -> txOut') -> unTermCont $ do - txOut <- tcont $ pletFields @'["address", "value"] $ txOut' + ( \((pfield @"resolved" #) -> txOut') -> unTermCont $ do + txOut <- pletFieldsC @'["address", "value"] $ txOut' let cred = pfield @"credential" # pfromData txOut.address pure . pdata $ ptuple # cred # txOut.value ) @@ -190,7 +175,7 @@ treasuryWithdrawalValidator currSymbol = makeEffect currSymbol $ pnot #$ pany # plam ( \x -> - effInput.address #== pfield @"address" # pfromData x + effInput.address #== pfield @"address" # x ) # pfromData txInfo.outputs inputsAreOnlyTreasuriesOrCollateral = @@ -199,7 +184,7 @@ treasuryWithdrawalValidator currSymbol = makeEffect currSymbol $ ( \((pfield @"_0" #) . pfromData -> cred) -> cred #== pfield @"credential" # effInput.address #|| pelem # cred # datum.treasuries - #|| isPubKey # pfromData cred + #|| pisPubKey # pfromData cred ) # inputValues diff --git a/agora/Agora/Governor.hs b/agora/Agora/Governor.hs index b25fe4dc..6d594ed2 100644 --- a/agora/Agora/Governor.hs +++ b/agora/Agora/Governor.hs @@ -20,7 +20,7 @@ module Agora.Governor ( -- * Utilities pgetNextProposalId, getNextProposalId, - governorDatumValid, + pisGovernorDatumValid, ) where import Agora.Proposal ( @@ -28,26 +28,29 @@ import Agora.Proposal ( PProposalThresholds (..), ProposalId (ProposalId), ProposalThresholds, + pisProposalThresholdsValid, ) import Agora.Proposal.Time ( MaxTimeRangeWidth, PMaxTimeRangeWidth, PProposalTimingConfig, ProposalTimingConfig, + pisMaxTimeRangeWidthValid, + pisProposalTimingConfigValid, ) import Agora.SafeMoney (GTTag) import Data.Tagged (Tagged (..)) -import GHC.Generics qualified as GHC -import Generics.SOP (Generic, I (I)) import Plutarch.DataRepr ( DerivePConstantViaData (..), PDataFields, - PIsDataReprInstances (PIsDataReprInstances), ) -import Plutarch.Extra.Comonad (pextract) -import Plutarch.Extra.TermCont (pletC, pmatchC) +import Plutarch.Extra.IsData ( + DerivePConstantViaEnum (..), + EnumIsData (..), + PlutusTypeEnumData, + ) +import Plutarch.Extra.TermCont (pletFieldsC) import Plutarch.Lift (PConstantDecl, PUnsafeLiftDecl (..)) -import Plutarch.SafeMoney (PDiscrete (..)) import PlutusLedgerApi.V1 (TxOutRef) import PlutusLedgerApi.V1.Value (AssetClass (..)) import PlutusTx qualified @@ -68,8 +71,16 @@ data GovernorDatum = GovernorDatum -- Will get copied over upon the creation of proposals. , createProposalTimeRangeMaxWidth :: MaxTimeRangeWidth -- ^ The maximum valid duration of a transaction that creats a proposal. + , maximumProposalsPerStake :: Integer + -- ^ The maximum number of unfinished proposals that a stake is allowed to be + -- associated to. } - deriving stock (Show, GHC.Generic) + deriving stock + ( -- | @since 0.1.0 + Show + , -- | @since 0.1.0 + Generic + ) -- | @since 0.1.0 PlutusTx.makeIsDataIndexed ''GovernorDatum [('GovernorDatum, 0)] @@ -92,15 +103,23 @@ data GovernorRedeemer MintGATs | -- | Allows effects to mutate the parameters. MutateGovernor - deriving stock (Show, GHC.Generic) - --- | @since 0.1.0 -PlutusTx.makeIsDataIndexed - ''GovernorRedeemer - [ ('CreateProposal, 0) - , ('MintGATs, 1) - , ('MutateGovernor, 2) - ] + deriving stock + ( -- | @since 0.1.0 + Show + , -- | @since 0.1.0 + Generic + , -- | @since 0.2.0 + Enum + , -- | @since 0.2.0 + Bounded + ) + deriving + ( -- | @since 0.1.0 + PlutusTx.ToData + , -- | @since 0.1.0 + PlutusTx.FromData + ) + via (EnumIsData GovernorRedeemer) {- | Parameters for creating Governor scripts. @@ -115,7 +134,12 @@ data Governor = Governor -- ^ Arbitrary limit for maximum amount of cosigners on a proposal. -- See `Agora.Proposal.proposalDatumValid`. } - deriving stock (GHC.Generic) + deriving stock + ( -- | @since 0.1.0 + Generic + , -- | @since 0.2.0 + Show + ) -------------------------------------------------------------------------------- @@ -132,22 +156,15 @@ newtype PGovernorDatum (s :: S) = PGovernorDatum , "nextProposalId" ':= PProposalId , "proposalTimings" ':= PProposalTimingConfig , "createProposalTimeRangeMaxWidth" ':= PMaxTimeRangeWidth + , "maximumProposalsPerStake" ':= PInteger ] ) } deriving stock - ( -- | @since 0.1.0 - GHC.Generic - ) - deriving anyclass ( -- | @since 0.1.0 Generic ) deriving anyclass - ( -- | @since 0.1.0 - PIsDataRepr - ) - deriving ( -- | @since 0.1.0 PlutusType , -- | @since 0.1.0 @@ -157,7 +174,10 @@ newtype PGovernorDatum (s :: S) = PGovernorDatum , -- | @since 0.1.0 PEq ) - via PIsDataReprInstances PGovernorDatum + +-- | @since 0.2.0 +instance DerivePlutusType PGovernorDatum where + type DPTStrat _ = PlutusTypeData -- | @since 0.1.0 instance PUnsafeLiftDecl PGovernorDatum where type PLifted PGovernorDatum = GovernorDatum @@ -166,44 +186,45 @@ instance PUnsafeLiftDecl PGovernorDatum where type PLifted PGovernorDatum = Gove deriving via (DerivePConstantViaData GovernorDatum PGovernorDatum) instance (PConstantDecl GovernorDatum) -- | @since 0.1.0 -deriving via PAsData (PIsDataReprInstances PGovernorDatum) instance PTryFrom PData (PAsData PGovernorDatum) +deriving anyclass instance PTryFrom PData PGovernorDatum {- | Plutarch-level version of 'GovernorRedeemer'. @since 0.1.0 -} data PGovernorRedeemer (s :: S) - = PCreateProposal (Term s (PDataRecord '[])) - | PMintGATs (Term s (PDataRecord '[])) - | PMutateGovernor (Term s (PDataRecord '[])) + = PCreateProposal + | PMintGATs + | PMutateGovernor deriving stock - ( -- | @since 0.1.0 - GHC.Generic - ) - deriving anyclass ( -- | @since 0.1.0 Generic + , -- | @since 0.2.0 + Enum + , -- | @since 0.2.0 + Bounded ) deriving anyclass - ( -- | @since 0.1.0 - PIsDataRepr - ) - deriving ( -- | @since 0.1.0 PlutusType , -- | @since 0.1.0 PIsData + , -- | @since 0.2.0 + PEq ) - via PIsDataReprInstances PGovernorRedeemer --- | @since 0.1.0 -instance PUnsafeLiftDecl PGovernorRedeemer where type PLifted PGovernorRedeemer = GovernorRedeemer +-- | @since 0.2.0 +instance PTryFrom PData (PAsData PGovernorRedeemer) + +-- | @since 0.2.0 +instance DerivePlutusType PGovernorRedeemer where + type DPTStrat _ = PlutusTypeEnumData -- | @since 0.1.0 -deriving via (DerivePConstantViaData GovernorRedeemer PGovernorRedeemer) instance (PConstantDecl GovernorRedeemer) +instance PUnsafeLiftDecl PGovernorRedeemer where type PLifted PGovernorRedeemer = GovernorRedeemer -- | @since 0.1.0 -deriving via PAsData (PIsDataReprInstances PGovernorRedeemer) instance PTryFrom PData (PAsData PGovernorRedeemer) +deriving via (DerivePConstantViaEnum GovernorRedeemer PGovernorRedeemer) instance (PConstantDecl GovernorRedeemer) -------------------------------------------------------------------------------- @@ -227,28 +248,24 @@ getNextProposalId (ProposalId pid) = ProposalId $ pid + 1 @since 0.1.0 -} -governorDatumValid :: Term s (PGovernorDatum :--> PBool) -governorDatumValid = phoistAcyclic $ +pisGovernorDatumValid :: Term s (PGovernorDatum :--> PBool) +pisGovernorDatumValid = phoistAcyclic $ plam $ \datum -> unTermCont $ do - thresholds <- - tcont $ - pletFields @'["execute", "create", "vote"] $ - pfield @"proposalThresholds" # datum - - PDiscrete execute' <- pmatchC thresholds.execute - PDiscrete draft' <- pmatchC thresholds.create - PDiscrete vote' <- pmatchC thresholds.vote - - execute <- pletC $ pextract # execute' - draft <- pletC $ pextract # draft' - vote <- pletC $ pextract # vote' + datumF <- + pletFieldsC + @'[ "proposalThresholds" + , "proposalTimings" + , "createProposalTimeRangeMaxWidth" + ] + datum pure $ foldr1 (#&&) - [ ptraceIfFalse "Execute threshold is less than or equal to" $ 0 #<= execute - , ptraceIfFalse "Draft threshold is less than or equal to " $ 0 #<= draft - , ptraceIfFalse "Vote threshold is less than or equal to " $ 0 #<= vote - , ptraceIfFalse "Draft threshold is less than vote threshold" $ draft #<= vote - , ptraceIfFalse "Execute threshold is less than vote threshold" $ vote #< execute + [ ptraceIfFalse "thresholds valid" $ + pisProposalThresholdsValid # pfromData datumF.proposalThresholds + , ptraceIfFalse "timings valid" $ + pisProposalTimingConfigValid # pfromData datumF.proposalTimings + , ptraceIfFalse "time range valid" $ + pisMaxTimeRangeWidthValid # datumF.createProposalTimeRangeMaxWidth ] diff --git a/agora/Agora/Governor/Scripts.hs b/agora/Agora/Governor/Scripts.hs index b2639a8f..683815eb 100644 --- a/agora/Agora/Governor/Scripts.hs +++ b/agora/Agora/Governor/Scripts.hs @@ -12,79 +12,40 @@ module Agora.Governor.Scripts ( -- * Scripts governorPolicy, governorValidator, - - -- * Bridges - governorSTSymbolFromGovernor, - governorSTAssetClassFromGovernor, - proposalSTAssetClassFromGovernor, - stakeSTSymbolFromGovernor, - stakeFromGovernor, - stakeValidatorHashFromGovernor, - proposalFromGovernor, - proposalValidatorHashFromGovernor, - proposalSTSymbolFromGovernor, - stakeSTAssetClassFromGovernor, - governorValidatorHash, - authorityTokenFromGovernor, - authorityTokenSymbolFromGovernor, ) where -------------------------------------------------------------------------------- import Agora.AuthorityToken ( - AuthorityToken (..), - authorityTokenPolicy, authorityTokensValidIn, singleAuthorityTokenBurned, ) import Agora.Governor ( - Governor (gstOutRef, gtClassRef, maximumCosigners), + GovernorRedeemer (..), PGovernorDatum (PGovernorDatum), - PGovernorRedeemer (PCreateProposal, PMintGATs, PMutateGovernor), - governorDatumValid, pgetNextProposalId, + pisGovernorDatumValid, ) import Agora.Proposal ( PProposalDatum (..), - PProposalId (..), - PProposalStatus (PFinished), - PResultTag, - Proposal (..), ProposalStatus (Draft, Locked), - pemptyVotesFor, + phasNeutralEffect, + pisEffectsVotesCompatible, + pisVotesEmpty, pneutralOption, - proposalDatumValid, pwinner, ) -import Agora.Proposal.Scripts ( - proposalPolicy, - proposalValidator, - ) import Agora.Proposal.Time (createProposalStartingTime) -import Agora.SafeMoney (GTTag) +import Agora.Scripts (AgoraScripts, authorityTokenSymbol, governorSTSymbol, proposalSTSymbol, proposalValidatoHash, stakeSTSymbol) import Agora.Stake ( PProposalLock (..), PStakeDatum (..), - Stake (..), - ) -import Agora.Stake.Scripts ( - stakePolicy, - stakeValidator, + pnumCreatedProposals, ) import Agora.Utils ( - findOutputsToAddress, - hasOnlyOneTokenOfCurrencySymbol, - mustBePDJust, - mustBePJust, mustFindDatum', - scriptHashFromAddress, validatorHashToAddress, - validatorHashToTokenName, ) -import Plutarch.Extra.Record - --------------------------------------------------------------------------------- - import Plutarch.Api.V1 ( PAddress, PCurrencySymbol, @@ -95,38 +56,31 @@ import Plutarch.Api.V1 ( PTxOut, PValidator, PValidatorHash, - PValue, - mintingPolicySymbol, - mkMintingPolicy, - mkValidator, - validatorHash, ) import Plutarch.Api.V1.AssetClass ( passetClass, passetClassValueOf, ) +import Plutarch.Api.V1.ScriptContext ( + pfindOutputsToAddress, + pfindTxInByTxOutRef, + pisUTXOSpent, + pscriptHashFromAddress, + ptryFindDatum, + pvalueSpent, + ) +import "liqwid-plutarch-extra" Plutarch.Api.V1.Value (phasOnlyOneTokenOfCurrencySymbol, psymbolValueOf) +import Plutarch.Extra.Field (pletAllC) +import Plutarch.Extra.IsData (pmatchEnumFromData) +import Plutarch.Extra.List (pfirstJust) import Plutarch.Extra.Map ( - pkeys, plookup, plookup', ) -import Plutarch.SafeMoney (PDiscrete (..), pvalueDiscrete') -import Plutarch.TryFrom () - --------------------------------------------------------------------------------- - -import Plutarch.Api.V1.ScriptContext (pfindTxInByTxOutRef, pisUTXOSpent, ptryFindDatum, ptxSignedBy, pvalueSpent) -import "liqwid-plutarch-extra" Plutarch.Api.V1.Value (psymbolValueOf) -import Plutarch.Extra.Maybe (pisDJust) -import Plutarch.Extra.TermCont -import PlutusLedgerApi.V1 ( - CurrencySymbol (..), - MintingPolicy, - ) -import PlutusLedgerApi.V1.Scripts (ValidatorHash (..)) -import PlutusLedgerApi.V1.Value ( - AssetClass (..), - ) +import Plutarch.Extra.Maybe (passertPDJust, passertPJust, pfromJust, pisDJust) +import Plutarch.Extra.Record (mkRecordConstr, (.&), (.=)) +import Plutarch.Extra.TermCont (pguardC, pletC, pletFieldsC, pmatchC, ptryFromC) +import PlutusLedgerApi.V1 (TxOutRef) -------------------------------------------------------------------------------- @@ -157,16 +111,16 @@ import PlutusLedgerApi.V1.Value ( @since 0.1.0 -} -governorPolicy :: Governor -> ClosedTerm PMintingPolicy -governorPolicy gov = +governorPolicy :: TxOutRef -> ClosedTerm PMintingPolicy +governorPolicy initialSpend = plam $ \_ ctx' -> unTermCont $ do - let oref = pconstant gov.gstOutRef + let oref = pconstant initialSpend PMinting ((pfield @"_0" #) -> ownSymbol) <- pmatchC (pfromData $ pfield @"purpose" # ctx') let ownAssetClass = passetClass # ownSymbol # pconstant "" txInfo = pfromData $ pfield @"txInfo" # ctx' - txInfoF <- tcont $ pletFields @'["mint", "inputs", "outputs", "datums", "validRange"] txInfo + txInfoF <- pletFieldsC @'["mint", "inputs", "outputs", "datums", "validRange"] txInfo pguardC "Referenced utxo should be spent" $ pisUTXOSpent # oref # txInfoF.inputs @@ -177,19 +131,21 @@ governorPolicy gov = govOutput <- pletC $ - mustBePJust + passertPJust # "Governor output not found" #$ pfind # plam - ( \((pfield @"value" #) . pfromData -> value) -> + ( \((pfield @"value" #) -> value) -> psymbolValueOf # ownSymbol # value #== 1 ) # pfromData txInfoF.outputs - let datumHash = pfield @"datumHash" # pfromData govOutput + let datumHash = pfield @"datumHash" # govOutput datum = mustFindDatum' @PGovernorDatum # datumHash # txInfoF.datums - pure $ popaque $ governorDatumValid # datum + pguardC "Governor output datum valid" $ pisGovernorDatumValid # datum + + pure $ popaque $ pconstant () {- | Validator for Governors. @@ -277,62 +233,56 @@ governorPolicy gov = @since 0.1.0 -} -governorValidator :: Governor -> ClosedTerm PValidator -governorValidator gov = +governorValidator :: + -- | Lazy precompiled scripts. + AgoraScripts -> + ClosedTerm PValidator +governorValidator as = plam $ \datum' redeemer' ctx' -> unTermCont $ do - (pfromData -> redeemer, _) <- tcont $ ptryFrom redeemer' - ctxF <- tcont $ pletFields @'["txInfo", "purpose"] ctx' + ctxF <- pletAllC ctx' txInfo' <- pletC $ pfromData $ ctxF.txInfo - txInfoF <- tcont $ pletFields @'["mint", "inputs", "outputs", "datums", "signatories", "validRange"] txInfo' + txInfoF <- pletFieldsC @'["mint", "inputs", "outputs", "datums", "signatories", "validRange"] txInfo' PSpending (pfromData . (pfield @"_0" #) -> ownInputRef) <- pmatchC $ pfromData ctxF.purpose ((pfield @"resolved" #) -> ownInput) <- pletC $ - mustBePJust # "Own input not found" + passertPJust # "Own input not found" #$ pfindTxInByTxOutRef # ownInputRef # txInfoF.inputs - ownInputF <- tcont $ pletFields @'["address", "value"] ownInput + ownInputF <- pletFieldsC @'["address", "value"] ownInput let ownAddress = pfromData $ ownInputF.address - (pfromData -> (oldGovernorDatum :: Term _ PGovernorDatum), _) <- tcont $ ptryFrom datum' - oldGovernorDatumF <- - tcont $ - pletFields - @'[ "proposalThresholds" - , "nextProposalId" - , "proposalTimings" - , "createProposalTimeRangeMaxWidth" - ] - oldGovernorDatum + (oldGovernorDatum :: Term _ PGovernorDatum, _) <- ptryFromC datum' + oldGovernorDatumF <- pletAllC oldGovernorDatum -- Check that GST will be returned to the governor. let ownInputGSTAmount = psymbolValueOf # pgstSymbol # ownInputF.value pguardC "Own input should have exactly one state token" $ ownInputGSTAmount #== 1 - ownOutputs <- pletC $ findOutputsToAddress # txInfoF.outputs # ownAddress + ownOutputs <- pletC $ pfindOutputsToAddress # txInfoF.outputs # ownAddress pguardC "Exactly one utxo should be sent to the governor" $ plength # ownOutputs #== 1 - ownOutput <- tcont $ pletFields @'["value", "datumHash"] $ phead # ownOutputs + ownOutput <- pletFieldsC @'["value", "datumHash"] $ phead # ownOutputs let ownOuputGSTAmount = psymbolValueOf # pgstSymbol # ownOutput.value pguardC "State token should stay at governor's address" $ ownOuputGSTAmount #== 1 -- Check that own output have datum of type 'GovernorDatum'. let outputGovernorStateDatumHash = - mustBePDJust # "Governor output doesn't have datum" # ownOutput.datumHash + passertPDJust # "Governor output doesn't have datum" # ownOutput.datumHash newGovernorDatum <- pletC $ - pfromData $ - mustBePJust # "Ouput governor state datum not found" - #$ ptryFindDatum # outputGovernorStateDatumHash # txInfoF.datums - pguardC "New datum is not valid" $ governorDatumValid # newGovernorDatum + passertPJust # "Ouput governor state datum not found" + #$ ptryFindDatum # outputGovernorStateDatumHash # txInfoF.datums + + pguardC "New datum is valid" $ pisGovernorDatumValid # newGovernorDatum pure $ - pmatch redeemer $ \case - PCreateProposal _ -> unTermCont $ do + pmatchEnumFromData redeemer' $ \case + Just CreateProposal -> unTermCont $ do -- Check that the transaction advances proposal id. let expectedNextProposalId = pgetNextProposalId # oldGovernorDatumF.nextProposalId @@ -344,6 +294,8 @@ governorValidator gov = .& #proposalTimings .= oldGovernorDatumF.proposalTimings .& #createProposalTimeRangeMaxWidth .= oldGovernorDatumF.createProposalTimeRangeMaxWidth + .& #maximumProposalsPerStake + .= oldGovernorDatumF.maximumProposalsPerStake ) pguardC "Unexpected governor state datum" $ newGovernorDatum #== expectedNewDatum @@ -351,41 +303,38 @@ governorValidator gov = -- Check that exactly one proposal token is being minted. pguardC "Exactly one proposal token must be minted" $ - hasOnlyOneTokenOfCurrencySymbol # ppstSymbol # txInfoF.mint + phasOnlyOneTokenOfCurrencySymbol # ppstSymbol # txInfoF.mint -- Check that a stake is spent to create the propsal, -- and the value it contains meets the requirement. - stakeInput <- + stakeInputs <- pletC $ - mustBePJust # "Stake input not found" #$ pfind + pfilter # phoistAcyclic ( plam $ - \((pfield @"resolved" #) -> txOut') -> unTermCont $ do - txOut <- tcont $ pletFields @'["address", "value"] txOut' - - pure $ - txOut.address #== pdata pstakeValidatorAddress - #&& psymbolValueOf # psstSymbol # txOut.value #== 1 + \((pfield @"value" #) . (pfield @"resolved" #) -> value) -> + psymbolValueOf # psstSymbol # value #== 1 ) # pfromData txInfoF.inputs - stakeInputF <- tcont $ pletFields @'["datumHash", "value"] $ pfield @"resolved" # stakeInput + pguardC "Can process only one stake" $ + plength # stakeInputs #== 1 + + stakeInput <- pletC $ phead # stakeInputs + + stakeInputF <- pletFieldsC @'["datumHash", "value"] $ pfield @"resolved" # stakeInput pguardC "Stake input doesn't have datum" $ pisDJust # stakeInputF.datumHash - let stakeInputDatum = mustFindDatum' @PStakeDatum # stakeInputF.datumHash # txInfoF.datums - - stakeInputDatumF <- - tcont $ pletFields @["stakedAmount", "owner", "lockedBy"] stakeInputDatum + let stakeInputDatum = mustFindDatum' @(PAsData PStakeDatum) # stakeInputF.datumHash # txInfoF.datums - pguardC "Required amount of stake GTs should be presented" $ - stakeInputDatumF.stakedAmount #== (pgtValueOf # stakeInputF.value) + stakeInputDatumF <- pletAllC $ pto $ pfromData stakeInputDatum - -- TODO: Is this required? - pguardC "Tx should be signed by the stake owner" $ - ptxSignedBy # txInfoF.signatories # stakeInputDatumF.owner + pguardC "Proposals created by the stake must not exceed the number stored in the governor." $ + pnumCreatedProposals # stakeInputDatumF.lockedBy + #< oldGovernorDatumF.maximumProposalsPerStake -- Check that the newly minted PST is sent to the proposal validator, -- and the datum it carries is legal. @@ -396,7 +345,7 @@ governorValidator gov = # phoistAcyclic ( plam $ \txOut' -> unTermCont $ do - txOut <- tcont $ pletFields @'["address", "value"] txOut' + txOut <- pletFieldsC @'["address", "value"] txOut' pure $ txOut.address #== pdata pproposalValidatorAddress @@ -411,114 +360,89 @@ governorValidator gov = proposalOutputDatum' <- pletC $ - mustFindDatum' @PProposalDatum + mustFindDatum' @(PAsData PProposalDatum) # outputDatumHash # txInfoF.datums - pguardC "Proposal datum must be valid" $ - proposalDatumValid' # proposalOutputDatum' - - proposalOutputDatum <- - tcont $ - pletFields - @'["effects", "cosigners", "proposalId", "votes"] - proposalOutputDatum' + proposalOutputDatum <- pletAllC $ pto $ pfromData proposalOutputDatum' - pguardC "Proposal should have only one cosigner" $ - plength # pfromData proposalOutputDatum.cosigners #== 1 - - let -- Votes should be empty at this point - expectedVotes = pemptyVotesFor # pfromData proposalOutputDatum.effects - expectedStartingTime = - createProposalStartingTime + let expectedStartingTime = + pfromJust #$ createProposalStartingTime # oldGovernorDatumF.createProposalTimeRangeMaxWidth # txInfoF.validRange - -- Id, thresholds and timings should be copied from the old governor state datum. - expectedProposalOut = - mkRecordConstr - PProposalDatum - ( #proposalId .= oldGovernorDatumF.nextProposalId - .& #effects .= proposalOutputDatum.effects - .& #status .= pconstantData Draft - .& #cosigners .= proposalOutputDatum.cosigners - .& #thresholds .= oldGovernorDatumF.proposalThresholds - .& #votes .= pdata expectedVotes - .& #timingConfig .= oldGovernorDatumF.proposalTimings - .& #startingTime .= pdata expectedStartingTime - ) - - pguardC "Datum correct" $ expectedProposalOut #== proposalOutputDatum' - let cosigner = phead # pfromData proposalOutputDatum.cosigners - - pguardC "Cosigner should be the stake owner" $ - pdata stakeInputDatumF.owner #== cosigner + expectedCosigners = psingleton @PBuiltinList # stakeInputDatumF.owner + + pguardC "Proposal datum correct" $ + foldl1 + (#&&) + [ ptraceIfFalse "has neutral effect" $ + phasNeutralEffect # proposalOutputDatum.effects + , ptraceIfFalse "votes have valid shape" $ + pisEffectsVotesCompatible # proposalOutputDatum.effects # proposalOutputDatum.votes + , ptraceIfFalse "votes are empty" $ + pisVotesEmpty # proposalOutputDatum.votes + , ptraceIfFalse "id correct" $ + proposalOutputDatum.proposalId #== oldGovernorDatumF.nextProposalId + , ptraceIfFalse "status is Draft" $ + proposalOutputDatum.status #== pconstantData Draft + , ptraceIfFalse "cosigners correct" $ + plistEquals # pfromData proposalOutputDatum.cosigners # expectedCosigners + , ptraceIfFalse "starting time correct" $ + proposalOutputDatum.startingTime #== expectedStartingTime + , ptraceIfFalse "copy over configurations" $ + proposalOutputDatum.thresholds #== oldGovernorDatumF.proposalThresholds + #&& proposalOutputDatum.timingConfig #== oldGovernorDatumF.proposalTimings + ] -- Check the output stake has been proposly updated. - - stakeOutput <- - pletC $ - mustBePJust - # "Stake output not found" - #$ pfind - # phoistAcyclic - ( plam $ - \txOut' -> unTermCont $ do - txOut <- tcont $ pletFields @'["address", "value"] txOut' - - pure $ - txOut.address #== pdata pstakeValidatorAddress - #&& psymbolValueOf # psstSymbol # txOut.value #== 1 - ) - # pfromData txInfoF.outputs - - stakeOutputF <- tcont $ pletFields @'["datumHash", "value"] $ stakeOutput - - pguardC "Staked GTs should be sent back to stake validator" $ - stakeInputDatumF.stakedAmount #== (pgtValueOf # stakeOutputF.value) - - let stakeOutputDatumHash = mustBePDJust # "Stake output should have datum" # stakeOutputF.datumHash + let stakeOutputDatumHash = + passertPJust # "Output stake should be presented" + #$ pfirstJust + # phoistAcyclic + ( plam + ( \txOut -> unTermCont $ do + txOutF <- pletFieldsC @'["datumHash", "value"] txOut + + pure $ + pif + (psymbolValueOf # psstSymbol # txOutF.value #== 1) + ( pcon $ + PJust $ + passertPDJust # "Output stake datum should be presented" + # txOutF.datumHash + ) + (pcon PNothing) + ) + ) + # pfromData txInfoF.outputs stakeOutputDatum = - mustBePJust # "Stake output not found" #$ ptryFindDatum # stakeOutputDatumHash # txInfoF.datums + passertPJust @(PAsData PStakeDatum) # "Stake output datum presented" + #$ ptryFindDatum # stakeOutputDatumHash # txInfoF.datums - -- The stake should be locked by the newly created proposal. + stakeOutputLocks = + pfromData $ pfield @"lockedBy" #$ pto $ pfromData stakeOutputDatum - let possibleVoteResults = pkeys #$ pto $ pfromData proposalOutputDatum.votes - - mkProposalLock :: Term _ (PProposalId :--> PAsData PResultTag :--> PAsData PProposalLock) - mkProposalLock = - phoistAcyclic $ - plam - ( \pid rt' -> - pdata $ - mkRecordConstr - PProposalLock - ( #vote .= rt' .& #proposalTag .= pdata pid - ) - ) + -- The stake should be locked by the newly created proposal. + newLock = + mkRecordConstr + PCreated + ( #created .= oldGovernorDatumF.nextProposalId + ) -- Append new locks to existing locks expectedProposalLocks = - pconcat # stakeInputDatumF.lockedBy - #$ pmap # (mkProposalLock # proposalOutputDatum.proposalId) # possibleVoteResults - - expectedStakeOutputDatum = - pdata $ - mkRecordConstr - PStakeDatum - ( #stakedAmount .= stakeInputDatumF.stakedAmount - .& #owner .= stakeInputDatumF.owner - .& #lockedBy .= pdata expectedProposalLocks - ) + pcons # pdata newLock # stakeInputDatumF.lockedBy - pguardC "Unexpected stake output datum" $ expectedStakeOutputDatum #== stakeOutputDatum + pguardC "Stake output locks correct" $ + plistEquals # stakeOutputLocks # expectedProposalLocks pure $ popaque $ pconstant () -------------------------------------------------------------------------- - PMintGATs _ -> unTermCont $ do + Just MintGATs -> unTermCont $ do pguardC "Governor state should not be changed" $ newGovernorDatum #== oldGovernorDatum -- Filter out proposal inputs and ouputs using PST and the address of proposal validator. @@ -527,78 +451,36 @@ governorValidator gov = (psymbolValueOf # ppstSymbol #$ pvalueSpent # txInfoF.inputs) #== 1 proposalInputF <- - tcont $ - pletFields @'["datumHash"] $ - pfield @"resolved" - #$ pfromData - $ mustBePJust - # "Proposal input not found" - #$ pfind - # plam - ( \((pfield @"resolved" #) -> txOut) -> unTermCont $ do - txOutF <- tcont $ pletFields @'["address", "value"] txOut - - pure $ - psymbolValueOf # ppstSymbol # txOutF.value #== 1 - #&& txOutF.address #== pdata pproposalValidatorAddress - ) - # pfromData txInfoF.inputs - - proposalOutputF <- - tcont $ - pletFields @'["datumHash"] $ - mustBePJust # "Proposal output not found" + pletFieldsC @'["datumHash"] $ + pfield @"resolved" + #$ passertPJust + # "Proposal input not found" #$ pfind - # plam - ( \txOut -> unTermCont $ do - txOutF <- tcont $ pletFields @'["address", "value"] txOut - pure $ - psymbolValueOf # ppstSymbol # txOutF.value #== 1 - #&& txOutF.address #== pdata pproposalValidatorAddress - ) - # pfromData txInfoF.outputs + # plam + ( \((pfield @"resolved" #) -> txOut) -> unTermCont $ do + txOutF <- pletFieldsC @'["address", "value"] txOut + + pure $ + psymbolValueOf # ppstSymbol # txOutF.value #== 1 + #&& txOutF.address #== pdata pproposalValidatorAddress + ) + # pfromData txInfoF.inputs proposalInputDatum <- pletC $ - mustFindDatum' @PProposalDatum + mustFindDatum' @(PAsData PProposalDatum) # proposalInputF.datumHash # txInfoF.datums - proposalOutputDatum <- - pletC $ - mustFindDatum' @PProposalDatum - # proposalOutputF.datumHash - # txInfoF.datums - - pguardC "Proposal datum must be valid" $ - proposalDatumValid' # proposalInputDatum - #&& proposalDatumValid' # proposalOutputDatum proposalInputDatumF <- - tcont $ - pletFields @'["proposalId", "effects", "status", "cosigners", "thresholds", "votes", "timingConfig", "startingTime"] - proposalInputDatum + pletFieldsC @'["effects", "status", "thresholds", "votes"] $ + pto $ pfromData proposalInputDatum -- Check that the proposal state is advanced so that a proposal cannot be executed twice. pguardC "Proposal must be in locked(executable) state in order to execute effects" $ proposalInputDatumF.status #== pconstantData Locked - let expectedOutputProposalDatum = - mkRecordConstr - PProposalDatum - ( #proposalId .= proposalInputDatumF.proposalId - .& #effects .= proposalInputDatumF.effects - .& #status .= pdata (pcon $ PFinished pdnil) - .& #cosigners .= proposalInputDatumF.cosigners - .& #thresholds .= proposalInputDatumF.thresholds - .& #votes .= proposalInputDatumF.votes - .& #timingConfig .= proposalInputDatumF.timingConfig - .& #startingTime .= proposalInputDatumF.startingTime - ) - - pguardC "Unexpected output proposal datum" $ - pdata proposalOutputDatum #== pdata expectedOutputProposalDatum - -- TODO: anything else to check here? -- Find the highest votes and the corresponding tag. @@ -629,22 +511,22 @@ governorValidator gov = pguardC "Output GATs is more than minted GATs" $ plength # outputsWithGAT #== gatCount - let gatOutputValidator' :: Term s (PMap _ PValidatorHash PDatumHash :--> PAsData PTxOut :--> PBool) + let gatOutputValidator' :: Term s (PMap _ PValidatorHash PDatumHash :--> PTxOut :--> PBool) gatOutputValidator' = phoistAcyclic $ plam - ( \effects (pfromData -> output') -> unTermCont $ do - output <- tcont $ pletFields @'["address", "datumHash"] $ output' + ( \effects output' -> unTermCont $ do + output <- pletFieldsC @'["address", "datumHash"] output' let scriptHash = - mustBePJust # "GAT receiver is not a script" - #$ scriptHashFromAddress # output.address + passertPJust # "GAT receiver is not a script" + #$ pscriptHashFromAddress # output.address datumHash = - mustBePDJust # "Output to effect should have datum" + passertPDJust # "Output to effect should have datum" #$ output.datumHash expectedDatumHash = - mustBePJust # "Receiver is not in the effect list" + passertPJust # "Receiver is not in the effect list" #$ plookup # scriptHash # effects pure $ @@ -657,197 +539,51 @@ governorValidator gov = gatOutputValidator = gatOutputValidator' # effectGroup - pure $ - popaque $ - pfoldr - # plam - ( \txOut r -> - let value = pfield @"value" # txOut - atValue = psymbolValueOf # patSymbol # value - in pif (atValue #== 0) r $ - pif (atValue #== 1) (r #&& gatOutputValidator # txOut) $ pconstant False - ) - # pconstant True - # pfromData txInfoF.outputs + pguardC "GATs valid" $ + pfoldr + # plam + ( \txOut r -> + let value = pfield @"value" # txOut + atValue = psymbolValueOf # patSymbol # value + in pif (atValue #== 0) r $ + pif (atValue #== 1) (r #&& gatOutputValidator # txOut) $ pconstant False + ) + # pconstant True + # pfromData txInfoF.outputs + + pure $ popaque $ pconstant () -------------------------------------------------------------------------- - PMutateGovernor _ -> unTermCont $ do + Just MutateGovernor -> unTermCont $ do -- Check that a GAT is burnt. - pure $ popaque $ singleAuthorityTokenBurned patSymbol ctxF.txInfo txInfoF.mint - where - -- Get th amount of governance tokens in a value. - pgtValueOf :: Term s (PValue _ _ :--> PDiscrete GTTag) - pgtValueOf = phoistAcyclic $ pvalueDiscrete' gov.gtClassRef + pguardC "One valid GAT burnt" $ + singleAuthorityTokenBurned patSymbol txInfoF.inputs txInfoF.mint + + pure $ popaque $ pconstant () + -------------------------------------------------------------------------- + Nothing -> ptraceError "Unknown redeemer" + where -- The currency symbol of authority token. patSymbol :: Term s PCurrencySymbol - patSymbol = phoistAcyclic $ pconstant $ authorityTokenSymbolFromGovernor gov + patSymbol = pconstant $ authorityTokenSymbol as -- The currency symbol of the proposal state token. ppstSymbol :: Term s PCurrencySymbol - ppstSymbol = - let AssetClass (sym, _) = proposalSTAssetClassFromGovernor gov - in phoistAcyclic $ pconstant sym - - -- Is a proposal state datum valid? - proposalDatumValid' :: Term s (PProposalDatum :--> PBool) - proposalDatumValid' = - let params = proposalFromGovernor gov - in phoistAcyclic $ proposalDatumValid params + ppstSymbol = pconstant $ proposalSTSymbol as -- The address of the proposal validator. pproposalValidatorAddress :: Term s PAddress pproposalValidatorAddress = - let vh = proposalValidatorHashFromGovernor gov - in phoistAcyclic $ pconstant $ validatorHashToAddress vh - - -- The address of the stake validator. - pstakeValidatorAddress :: Term s PAddress - pstakeValidatorAddress = - let vh = stakeValidatorHashFromGovernor gov - in phoistAcyclic $ pconstant $ validatorHashToAddress vh + pconstant $ + validatorHashToAddress $ + proposalValidatoHash as -- The currency symbol of the stake state token. psstSymbol :: Term s PCurrencySymbol - psstSymbol = - let sym = stakeSTSymbolFromGovernor gov - in phoistAcyclic $ pconstant sym + psstSymbol = pconstant $ stakeSTSymbol as -- The currency symbol of the governor state token. pgstSymbol :: Term s PCurrencySymbol - pgstSymbol = - let sym = governorSTSymbolFromGovernor gov - in phoistAcyclic $ pconstant sym - --------------------------------------------------------------------------------- - -{- | Get the 'CurrencySymbol' of GST. - - @since 0.1.0 --} -governorSTSymbolFromGovernor :: Governor -> CurrencySymbol -governorSTSymbolFromGovernor gov = mintingPolicySymbol policy - where - policy :: MintingPolicy - policy = mkMintingPolicy $ governorPolicy gov - -{- | Get the 'AssetClass' of GST. - - @since 0.1.0 --} -governorSTAssetClassFromGovernor :: Governor -> AssetClass -governorSTAssetClassFromGovernor gov = AssetClass (symbol, "") - where - symbol :: CurrencySymbol - symbol = governorSTSymbolFromGovernor gov - -{- | Get the 'CurrencySymbol' of the proposal state token. - - @since 0.1.0 --} -proposalSTSymbolFromGovernor :: Governor -> CurrencySymbol -proposalSTSymbolFromGovernor gov = symbol - where - gstAC = governorSTAssetClassFromGovernor gov - policy = mkMintingPolicy $ proposalPolicy gstAC - symbol = mintingPolicySymbol policy - -{- | Get the 'AssetClass' of the proposal state token. - - @since 0.1.0 --} -proposalSTAssetClassFromGovernor :: Governor -> AssetClass -proposalSTAssetClassFromGovernor gov = AssetClass (symbol, "") - where - symbol = proposalSTSymbolFromGovernor gov - -{- | Get the 'CurrencySymbol' of the stake token/ - - @since 0.1.0 --} -stakeSTSymbolFromGovernor :: Governor -> CurrencySymbol -stakeSTSymbolFromGovernor gov = mintingPolicySymbol policy - where - policy = mkMintingPolicy $ stakePolicy gov.gtClassRef - -{- | Get the 'AssetClass' of the stake token. - - Note that the token is tagged with the hash of the stake validator. - See 'Agora.Stake.Script.stakePolicy'. - - @since 0.1.0 --} -stakeSTAssetClassFromGovernor :: Governor -> AssetClass -stakeSTAssetClassFromGovernor gov = AssetClass (symbol, tokenName) - where - symbol = stakeSTSymbolFromGovernor gov - - -- Tag with the address where the token is being sent to. - tokenName = validatorHashToTokenName $ stakeValidatorHashFromGovernor gov - -{- | Get the 'Stake' parameter, given the 'Governor' parameter. - - @since 0.1.0 --} -stakeFromGovernor :: Governor -> Stake -stakeFromGovernor gov = - Stake gov.gtClassRef $ - proposalSTAssetClassFromGovernor gov - -{- | Get the hash of 'Agora.Stake.Script.stakePolicy'. - - @since 0.1.0 --} -stakeValidatorHashFromGovernor :: Governor -> ValidatorHash -stakeValidatorHashFromGovernor gov = validatorHash validator - where - params = stakeFromGovernor gov - validator = mkValidator $ stakeValidator params - -{- | Get the 'Proposal' parameter, given the 'Governor' parameter. - - @since 0.1.0 --} -proposalFromGovernor :: Governor -> Proposal -proposalFromGovernor gov = Proposal gstAC sstAC mc - where - gstAC = governorSTAssetClassFromGovernor gov - mc = gov.maximumCosigners - sstAC = stakeSTAssetClassFromGovernor gov - -{- | Get the hash of 'Agora.Proposal.proposalPolicy'. - - @since 0.1.0 --} -proposalValidatorHashFromGovernor :: Governor -> ValidatorHash -proposalValidatorHashFromGovernor gov = validatorHash validator - where - params = proposalFromGovernor gov - validator = mkValidator $ proposalValidator params - -{- | Get the hash of 'Agora.Proposal.proposalValidator'. - - @since 0.1.0 --} -governorValidatorHash :: Governor -> ValidatorHash -governorValidatorHash gov = validatorHash validator - where - validator = mkValidator $ governorValidator gov - -{- | Get the 'AuthorityToken' parameter given the 'Governor' parameter. - - @since 0.1.0 --} -authorityTokenFromGovernor :: Governor -> AuthorityToken -authorityTokenFromGovernor gov = AuthorityToken $ governorSTAssetClassFromGovernor gov - -{- | Get the 'CurrencySymbol' of the authority token. - - @since 0.1.0 --} -authorityTokenSymbolFromGovernor :: Governor -> CurrencySymbol -authorityTokenSymbolFromGovernor gov = mintingPolicySymbol policy - where - policy = mkMintingPolicy $ authorityTokenPolicy params - params = authorityTokenFromGovernor gov + pgstSymbol = pconstant $ governorSTSymbol as diff --git a/agora/Agora/MultiSig.hs b/agora/Agora/MultiSig.hs deleted file mode 100644 index a454ad2d..00000000 --- a/agora/Agora/MultiSig.hs +++ /dev/null @@ -1,136 +0,0 @@ -{-# LANGUAGE TemplateHaskell #-} - -{- | -Module : Agora.MultiSig -Maintainer : riley_kilgore@outlook.com -Description: A basic N of M multisignature validation function. - -A basic N of M multisignature validation function. --} -module Agora.MultiSig ( - validatedByMultisig, - pvalidatedByMultisig, - PMultiSig (..), - MultiSig (..), -) where - -import GHC.Generics qualified as GHC -import Generics.SOP (Generic, I (I)) -import Plutarch.Api.V1 ( - PPubKeyHash, - PTxInfo (..), - ) -import Plutarch.DataRepr ( - DerivePConstantViaData (DerivePConstantViaData), - PDataFields, - PIsDataReprInstances (PIsDataReprInstances), - ) -import Plutarch.Lift ( - PConstantDecl, - PLifted, - PUnsafeLiftDecl, - ) -import PlutusLedgerApi.V1.Crypto (PubKeyHash) -import PlutusTx qualified -import Prelude - --------------------------------------------------------------------------------- - -{- | A MultiSig represents a proof that a particular set of signatures - are present on a transaction. - - @since 0.1.0 --} -data MultiSig = MultiSig - { keys :: [PubKeyHash] - -- ^ List of PubKeyHashes that must be present in the list of signatories. - , minSigs :: Integer - } - deriving stock - ( -- | @since 0.1.0 - GHC.Generic - , -- | @since 0.1.0 - Eq - , -- | @since 0.1.0 - Show - ) - deriving anyclass - ( -- | @since 0.1.0 - Generic - ) - -PlutusTx.makeLift ''MultiSig -PlutusTx.unstableMakeIsData ''MultiSig - -{- | Plutarch-level MultiSig - - @since 0.1.0 --} -newtype PMultiSig (s :: S) = PMultiSig - { getMultiSig :: - Term - s - ( PDataRecord - '[ "keys" ':= PBuiltinList (PAsData PPubKeyHash) - , "minSigs" ':= PInteger - ] - ) - } - deriving stock - ( -- | @since 0.1.0 - GHC.Generic - ) - deriving anyclass - ( -- | @since 0.1.0 - Generic - ) - deriving anyclass - ( -- | @since 0.1.0 - PIsDataRepr - ) - deriving - ( -- | @since 0.1.0 - PlutusType - , -- | @since 0.1.0 - PIsData - , -- | @since 0.1.0 - PDataFields - ) - via (PIsDataReprInstances PMultiSig) - --- | @since 0.1.0 -instance PUnsafeLiftDecl PMultiSig where type PLifted PMultiSig = MultiSig - --- | @since 0.1.0 -deriving via (DerivePConstantViaData MultiSig PMultiSig) instance (PConstantDecl MultiSig) - --------------------------------------------------------------------------------- - -{- | Check if a Haskell-level MultiSig signs this transaction. - - @since 0.1.0 --} -validatedByMultisig :: MultiSig -> Term s (PTxInfo :--> PBool) -validatedByMultisig params = - phoistAcyclic $ - pvalidatedByMultisig # pconstant params - -{- | Check if a Plutarch-level MultiSig signs this transaction. - - @since 0.1.0 --} -pvalidatedByMultisig :: Term s (PMultiSig :--> PTxInfo :--> PBool) -pvalidatedByMultisig = - phoistAcyclic $ - plam $ \multi' txInfo -> unTermCont $ do - multi <- tcont $ pletFields @'["keys", "minSigs"] multi' - let signatories = pfield @"signatories" # txInfo - pure $ - pfromData multi.minSigs - #<= ( plength #$ pfilter - # plam - ( \a -> - pelem # a # pfromData signatories - ) - # multi.keys - ) diff --git a/agora/Agora/Plutarch/Orphans.hs b/agora/Agora/Plutarch/Orphans.hs index 9e92ebd7..57778e67 100644 --- a/agora/Agora/Plutarch/Orphans.hs +++ b/agora/Agora/Plutarch/Orphans.hs @@ -3,132 +3,37 @@ {- FIXME: All of the following instances and types ought to belong in either plutarch or plutarch-extra. - - A number of these have been "stolen" from Mango's - PR: https://github.com/Plutonomicon/plutarch/pull/438/ -} module Agora.Plutarch.Orphans () where -import Control.Arrow (first) -import Plutarch.Api.V1 (PAddress, PCredential, PCurrencySymbol, PDatumHash, PMap, PMaybeData, PPOSIXTime, PPubKeyHash, PStakingCredential, PTokenName, PTxId, PTxOutRef, PValidatorHash, PValue) -import Plutarch.Builtin (PBuiltinMap) -import Plutarch.DataRepr (PIsDataReprInstances (..)) -import Plutarch.Numeric.Additive (AdditiveSemigroup ((+))) -import Plutarch.Reducible (Reduce, Reducible) -import Plutarch.TryFrom (PTryFrom (PTryFromExcess, ptryFrom')) +import Plutarch.Api.V1 (PDatumHash (..)) +import Plutarch.Builtin (PIsData (..)) +import Plutarch.Extra.TermCont (ptryFromC) +import Plutarch.TryFrom (PTryFrom (..)) import Plutarch.Unsafe (punsafeCoerce) -import Prelude hiding ((+)) - -instance Reducible (f x y) => Reducible (Flip f y x) where - type Reduce (Flip f y x) = Reduce (f x y) - -newtype Flip f a b = Flip (f b a) - --- | @since 0.1.0 -instance PTryFrom PData (PAsData b) => PTryFrom PData (PAsData (DerivePNewtype c b)) where - type - PTryFromExcess PData (PAsData (DerivePNewtype c b)) = - PTryFromExcess PData (PAsData b) - ptryFrom' d k = - ptryFrom' @_ @(PAsData b) d $ k . first punsafeCoerce - --- | @since 0.1.0 -instance PTryFrom PData (PAsData PPubKeyHash) where - type PTryFromExcess PData (PAsData PPubKeyHash) = Flip Term PPubKeyHash - ptryFrom' opq = runTermCont $ do - (wrapped :: Term _ (PAsData PByteString), unwrapped :: Term _ PByteString) <- - tcont $ ptryFrom @(PAsData PByteString) opq - tcont $ \f -> pif (plengthBS # unwrapped #== 28) (f ()) (ptraceError "a PubKeyHash should be 28 bytes long") - pure (punsafeCoerce wrapped, punsafeCoerce unwrapped) - --- | @since 0.1.0 -instance AdditiveSemigroup (Term s PPOSIXTime) where - (punsafeCoerce @_ @_ @PInteger -> x) + (punsafeCoerce @_ @_ @PInteger -> y) = punsafeCoerce $ x + y - --- | @since 0.1.0 -deriving via - PAsData (DerivePNewtype PPOSIXTime PInteger) - instance - PTryFrom PData (PAsData PPOSIXTime) - --- | @since 0.1.0 -deriving via - PAsData (PIsDataReprInstances PTxId) - instance - PTryFrom PData (PAsData PTxId) - --- | @since 0.1.0 -deriving via - PAsData (PIsDataReprInstances PTxOutRef) - instance - PTryFrom PData (PAsData PTxOutRef) - --- | @since 0.1.0 -deriving via - PAsData (DerivePNewtype (PMap g k v) (PBuiltinMap k v)) - instance - ( PTryFrom PData (PAsData k) - , PTryFrom PData (PAsData v) - ) => - PTryFrom PData (PAsData (PMap g k v)) --- | @since 0.1.0 -instance PTryFrom PData (PAsData PValidatorHash) where - type PTryFromExcess PData (PAsData PValidatorHash) = Flip Term PValidatorHash - ptryFrom' opq = runTermCont $ do - (wrapped :: Term _ (PAsData PByteString), unwrapped :: Term _ PByteString) <- - tcont $ ptryFrom @(PAsData PByteString) opq - tcont $ \f -> pif (plengthBS # unwrapped #== 28) (f ()) (ptraceError "a ValidatorHash should be 28 bytes long") - pure (punsafeCoerce wrapped, punsafeCoerce unwrapped) +newtype Flip f a b = Flip (f b a) deriving stock (Generic) -- | @since 0.1.0 instance PTryFrom PData (PAsData PDatumHash) where type PTryFromExcess PData (PAsData PDatumHash) = Flip Term PDatumHash ptryFrom' opq = runTermCont $ do - (wrapped :: Term _ (PAsData PByteString), unwrapped :: Term _ PByteString) <- - tcont $ ptryFrom @(PAsData PByteString) opq - tcont $ \f -> pif (plengthBS # unwrapped #== 32) (f ()) (ptraceError "a DatumHash should be 32 bytes long") - pure (punsafeCoerce wrapped, punsafeCoerce unwrapped) + (pfromData -> unwrapped, _) <- ptryFromC @(PAsData PByteString) opq --- | @since 0.1.0 -deriving via - PAsData (DerivePNewtype PCurrencySymbol PByteString) - instance - PTryFrom PData (PAsData PCurrencySymbol) + tcont $ \f -> + pif + -- Blake2b_256 hash: 256 bits/32 bytes. + (plengthBS # unwrapped #== 32) + (f ()) + (ptraceError "ptryFrom(PDatumHash): must be 32 bytes long") --- | @since 0.1.0 -deriving via - PAsData (DerivePNewtype PTokenName PByteString) - instance - PTryFrom PData (PAsData PTokenName) + pure (punsafeCoerce opq, pcon $ PDatumHash unwrapped) --- | @since 0.1.0 -deriving via - PAsData (DerivePNewtype (PValue k v) (PMap k PCurrencySymbol (PMap k PTokenName PInteger))) - instance - PTryFrom PData (PAsData (PValue k v)) +-- | @since 0.2.0 +instance PTryFrom PData (PAsData PUnit) --- | @since 0.1.0 -deriving via - PAsData (PIsDataReprInstances (PMaybeData a)) - instance - PTryFrom PData (PAsData a) => PTryFrom PData (PAsData (PMaybeData a)) - --- | @since 0.1.0 -deriving via - PAsData (PIsDataReprInstances PAddress) - instance - PTryFrom PData (PAsData PAddress) - --- | @since 0.1.0 -deriving via - PAsData (PIsDataReprInstances PCredential) - instance - PTryFrom PData (PAsData PCredential) - --- | @since 0.1.0 -deriving via - PAsData (PIsDataReprInstances PStakingCredential) - instance - PTryFrom PData (PAsData PStakingCredential) +-- | @since 0.2.0 +instance (PIsData a) => PIsData (PAsData a) where + pfromDataImpl = punsafeCoerce + pdataImpl = pdataImpl . pfromData diff --git a/agora/Agora/Proposal.hs b/agora/Agora/Proposal.hs index 5a2b4007..8bc70af9 100644 --- a/agora/Agora/Proposal.hs +++ b/agora/Agora/Proposal.hs @@ -9,7 +9,8 @@ Proposal scripts encoding effects that operate on the system. -} module Agora.Proposal ( -- * Haskell-land - Proposal (..), + + -- Proposal (..), ProposalDatum (..), ProposalRedeemer (..), ProposalStatus (..), @@ -29,20 +30,21 @@ module Agora.Proposal ( PResultTag (..), -- * Plutarch helpers - proposalDatumValid, - pemptyVotesFor, + phasNeutralEffect, + pisEffectsVotesCompatible, + pisVotesEmpty, pwinner, pwinner', pneutralOption, pretractVotes, + pisProposalThresholdsValid, ) where +import Agora.Plutarch.Orphans () import Agora.Proposal.Time (PProposalStartingTime, PProposalTimingConfig, ProposalStartingTime, ProposalTimingConfig) import Agora.SafeMoney (GTTag) -import Agora.Utils (mustBePJust) import Data.Tagged (Tagged) -import GHC.Generics qualified as GHC -import Generics.SOP (Generic, I (I)) +import Generics.SOP qualified as SOP import Plutarch.Api.V1 ( KeyGuarantees (Unsorted), PDatumHash, @@ -50,19 +52,31 @@ import Plutarch.Api.V1 ( PPubKeyHash, PValidatorHash, ) -import Plutarch.DataRepr (DerivePConstantViaData (..), PDataFields, PIsDataReprInstances (..)) -import Plutarch.Extra.List (pnotNull) +import Plutarch.Api.V1.AssocMap qualified as PAssocMap +import Plutarch.DataRepr (DerivePConstantViaData (..), PDataFields) +import Plutarch.Extra.Comonad (pextract) +import Plutarch.Extra.Field (pletAllC) +import Plutarch.Extra.Function (pbuiltinUncurry) +import Plutarch.Extra.IsData ( + DerivePConstantViaDataList (..), + DerivePConstantViaEnum (..), + EnumIsData (..), + PlutusTypeEnumData, + ProductIsData (ProductIsData), + ) +import Plutarch.Extra.List (pfirstJust) import Plutarch.Extra.Map qualified as PM import Plutarch.Extra.Map.Unsorted qualified as PUM -import Plutarch.Extra.TermCont (pguardC, pletC) +import Plutarch.Extra.Maybe (pfromJust) +import Plutarch.Extra.TermCont (pguardC, pletC, pmatchC) import Plutarch.Lift ( DerivePConstantViaNewtype (..), PConstantDecl, PUnsafeLiftDecl (..), ) -import Plutarch.SafeMoney (PDiscrete) +import Plutarch.SafeMoney (PDiscrete (..)) +import Plutarch.Show (PShow (..)) import PlutusLedgerApi.V1 (DatumHash, PubKeyHash, ValidatorHash) -import PlutusLedgerApi.V1.Value (AssetClass) import PlutusTx qualified import PlutusTx.AssocMap qualified as AssocMap @@ -78,21 +92,21 @@ import PlutusTx.AssocMap qualified as AssocMap @since 0.1.0 -} newtype ProposalId = ProposalId {proposalTag :: Integer} - deriving newtype + deriving stock ( -- | @since 0.1.0 - PlutusTx.ToData + Eq , -- | @since 0.1.0 - PlutusTx.FromData + Show , -- | @since 0.1.0 - PlutusTx.UnsafeFromData + Generic ) - deriving stock + deriving newtype ( -- | @since 0.1.0 - Eq + PlutusTx.ToData , -- | @since 0.1.0 - Show + PlutusTx.FromData , -- | @since 0.1.0 - GHC.Generic + PlutusTx.UnsafeFromData ) {- | Encodes a result. Typically, for a Yes/No proposal, we encode it like this: @@ -113,7 +127,7 @@ newtype ResultTag = ResultTag {getResultTag :: Integer} , -- | @since 0.1.0 Ord , -- | @since 0.1.0 - GHC.Generic + Generic ) deriving newtype ( -- | @since 0.1.0 @@ -172,11 +186,25 @@ data ProposalStatus , -- | @since 0.1.0 Show , -- | @since 0.1.0 - GHC.Generic + Generic + , -- | @since 0.2.0 + Enum + , -- | @since 0.2.0 + Bounded ) - --- | @since 0.1.0 -PlutusTx.makeIsDataIndexed ''ProposalStatus [('Draft, 0), ('VotingReady, 1), ('Locked, 2), ('Finished, 3)] + deriving anyclass + ( -- | @since 0.2.0 + SOP.Generic + ) + deriving + ( -- | @since 0.1.0 + PlutusTx.FromData + , -- | @since 0.1.0 + PlutusTx.ToData + , -- | @since 0.1.0 + PlutusTx.UnsafeFromData + ) + via (EnumIsData ProposalStatus) {- | The threshold values for various state transitions to happen. This data is stored centrally (in the 'Agora.Governor.Governor') and copied over @@ -202,11 +230,10 @@ data ProposalThresholds = ProposalThresholds , -- | @since 0.1.0 Show , -- | @since 0.1.0 - GHC.Generic + Generic ) --- | @since 0.1.0 -PlutusTx.makeIsDataIndexed ''ProposalThresholds [('ProposalThresholds, 0)] +PlutusTx.makeIsDataIndexed 'ProposalThresholds [('ProposalThresholds, 0)] {- | Map which encodes the total tally for each result. It's important that the "shape" is consistent with the shape of 'effects'. @@ -224,21 +251,19 @@ PlutusTx.makeIsDataIndexed ''ProposalThresholds [('ProposalThresholds, 0)] newtype ProposalVotes = ProposalVotes { getProposalVotes :: AssocMap.Map ResultTag Integer } - deriving newtype - ( -- | @since 0.1.0 - PlutusTx.ToData - , -- | @since 0.1.0 - PlutusTx.FromData - , -- | @since 0.1.0 - PlutusTx.UnsafeFromData - ) deriving stock ( -- | @since 0.1.0 Eq , -- | @since 0.1.0 Show , -- | @since 0.1.0 - GHC.Generic + Generic + ) + deriving newtype + ( -- | @since 0.1.0 + PlutusTx.ToData + , -- | @since 0.1.0 + PlutusTx.FromData ) {- | Create a 'ProposalVotes' that has the same shape as the 'effects' field. @@ -264,6 +289,8 @@ data ProposalDatum = ProposalDatum -- ^ The status the proposal is in. , cosigners :: [PubKeyHash] -- ^ Who created the proposal initially, and who cosigned it later. + -- + -- This list should be sorted in **ascending** order. , thresholds :: ProposalThresholds -- ^ Thresholds copied over on initialization. , votes :: ProposalVotes @@ -279,10 +306,19 @@ data ProposalDatum = ProposalDatum , -- | @since 0.1.0 Show , -- | @since 0.1.0 - GHC.Generic + Generic ) - -PlutusTx.makeIsDataIndexed ''ProposalDatum [('ProposalDatum, 0)] + deriving anyclass + ( -- | @since 0.2.0 + SOP.Generic + ) + deriving + ( -- | @since 0.1.0 + PlutusTx.ToData + , -- | @since 0.1.0 + PlutusTx.FromData + ) + via (ProductIsData ProposalDatum) {- | Haskell-level redeemer for Proposal scripts. @@ -296,22 +332,24 @@ data ProposalRedeemer -- -- This is particularly used in the 'Draft' 'ProposalStatus', -- where matching 'Agora.Stake.Stake's can be called to advance the proposal, - -- provided enough GT is shared among them. + -- provided enough GT is shared among them. + -- + -- This list should be sorted in ascending order. Cosign [PubKeyHash] | -- | Allow unlocking one or more stakes with votes towards particular 'ResultTag'. - Unlock ResultTag + Unlock | -- | Advance the proposal, performing the required checks for whether that is legal. -- -- These are roughly the checks for each possible transition: -- -- === @'Draft' -> 'VotingReady'@: -- - -- 1. The sum of all of the cosigner's GT is larger than the 'startVoting' field of 'ProposalThresholds'. + -- 1. The sum of all of the cosigner's GT is larger than the 'vote' field of 'ProposalThresholds'. -- 2. The proposal's current time ensures 'isDraftPeriod'. -- -- === @'VotingReady' -> 'Locked'@: -- - -- 1. The sum of all votes is larger than 'countVoting'. + -- 1. The sum of all votes is larger than 'execute'. -- 2. The winning 'ResultTag' has more votes than all other 'ResultTag's. -- 3. The proposal's current time ensures 'isVotingPeriod'. -- @@ -331,7 +369,7 @@ data ProposalRedeemer , -- | @since 0.1.0 Show , -- | @since 0.1.0 - GHC.Generic + Generic ) -- | @since 0.1.0 @@ -343,25 +381,6 @@ PlutusTx.makeIsDataIndexed , ('AdvanceProposal, 3) ] -{- | Parameters that identify the Proposal validator script. - - @since 0.1.0 --} -data Proposal = Proposal - { governorSTAssetClass :: AssetClass - , stakeSTAssetClass :: AssetClass - , maximumCosigners :: Integer - -- ^ Arbitrary limit for maximum amount of cosigners on a proposal. - } - deriving stock - ( -- | @since 0.1.0 - Show - , -- | @since 0.1.0 - Eq - , -- | @since 0.1.0 - GHC.Generic - ) - -------------------------------------------------------------------------------- -- Plutarch-land @@ -370,17 +389,31 @@ data Proposal = Proposal @since 0.1.0 -} newtype PResultTag (s :: S) = PResultTag (Term s PInteger) - deriving - ( -- | @since 0.1.0 + deriving stock + ( -- | @since 0.2.0 + Generic + ) + deriving anyclass + ( -- @since 0.1.0 PlutusType , -- | @since 0.1.0 PIsData , -- | @since 0.1.0 PEq + , -- | @since 0.2.0 + PPartialOrd , -- | @since 0.1.0 POrd + , -- | @since 0.2.0 + PShow ) - via (DerivePNewtype PResultTag PInteger) + +-- | @since 0.2.0 +instance DerivePlutusType PResultTag where + type DPTStrat _ = PlutusTypeNewtype + +-- | @since 0.1.0 +instance PTryFrom PData (PAsData PResultTag) -- | @since 0.1.0 instance PUnsafeLiftDecl PResultTag where type PLifted PResultTag = ResultTag @@ -391,34 +424,36 @@ deriving via instance (PConstantDecl ResultTag) --- | @since 0.1.0 -deriving via - PAsData (DerivePNewtype PResultTag PInteger) - instance - PTryFrom PData (PAsData PResultTag) - {- | Plutarch-level version of 'PProposalId'. @since 0.1.0 -} newtype PProposalId (s :: S) = PProposalId (Term s PInteger) - deriving + deriving stock + ( -- | @since 0.2.0 + Generic + ) + deriving anyclass ( -- | @since 0.1.0 PlutusType , -- | @since 0.1.0 PIsData , -- | @since 0.1.0 PEq + , -- | @since 0.2.0 + PPartialOrd , -- | @since 0.1.0 POrd + , -- | @since 0.2.0 + PShow ) - via (DerivePNewtype PProposalId PInteger) + +-- | @since 0.2.0 +instance DerivePlutusType PProposalId where + type DPTStrat _ = PlutusTypeNewtype -- | @since 0.1.0 -deriving via - PAsData (DerivePNewtype PProposalId PInteger) - instance - PTryFrom PData (PAsData PProposalId) +instance PTryFrom PData (PAsData PProposalId) -- | @since 0.1.0 instance PUnsafeLiftDecl PProposalId where type PLifted PProposalId = ProposalId @@ -434,25 +469,23 @@ deriving via @since 0.1.0 -} data PProposalStatus (s :: S) - = -- TODO: 'PProposalStatus' ought te be encoded as 'PInteger'. - -- e.g. like Tilde used 'pmatchEnum'. - PDraft (Term s (PDataRecord '[])) - | PVotingReady (Term s (PDataRecord '[])) - | PLocked (Term s (PDataRecord '[])) - | PFinished (Term s (PDataRecord '[])) + = -- | @since 0.2.0 + PDraft + | -- | @since 0.2.0 + PVoting + | -- | @since 0.2.0 + PLocked + | -- | @since 0.2.0 + PFinished deriving stock - ( -- | @since 0.1.0 - GHC.Generic - ) - deriving anyclass ( -- | @since 0.1.0 Generic + , -- | @since 0.2.0 + Bounded + , -- | @since 0.2.0 + Enum ) deriving anyclass - ( -- | @since 0.1.0 - PIsDataRepr - ) - deriving ( -- | @since 0.1.0 PlutusType , -- | @since 0.1.0 @@ -460,16 +493,19 @@ data PProposalStatus (s :: S) , -- | @since 0.1.0 PEq ) - via PIsDataReprInstances PProposalStatus + +-- | @since 0.2.0 +instance DerivePlutusType PProposalStatus where + type DPTStrat _ = PlutusTypeEnumData -- | @since 0.1.0 instance PUnsafeLiftDecl PProposalStatus where type PLifted PProposalStatus = ProposalStatus -- | @since 0.1.0 -deriving via PAsData (PIsDataReprInstances PProposalStatus) instance PTryFrom PData (PAsData PProposalStatus) +instance PTryFrom PData (PAsData PProposalStatus) -- | @since 0.1.0 -deriving via (DerivePConstantViaData ProposalStatus PProposalStatus) instance (PConstantDecl ProposalStatus) +deriving via (DerivePConstantViaEnum ProposalStatus PProposalStatus) instance (PConstantDecl ProposalStatus) {- | Plutarch-level version of 'ProposalThresholds'. @@ -487,18 +523,10 @@ newtype PProposalThresholds (s :: S) = PProposalThresholds ) } deriving stock - ( -- | @since 0.1.0 - GHC.Generic - ) - deriving anyclass ( -- | @since 0.1.0 Generic ) deriving anyclass - ( -- | @since 0.1.0 - PIsDataRepr - ) - deriving ( -- | @since 0.1.0 PlutusType , -- | @since 0.1.0 @@ -506,13 +534,13 @@ newtype PProposalThresholds (s :: S) = PProposalThresholds , -- | @since 0.1.0 PDataFields ) - via (PIsDataReprInstances PProposalThresholds) + +-- | @since 0.2.0 +instance DerivePlutusType PProposalThresholds where + type DPTStrat _ = PlutusTypeData -- | @since 0.1.0 -deriving via - PAsData (PIsDataReprInstances PProposalThresholds) - instance - PTryFrom PData (PAsData PProposalThresholds) +instance PTryFrom PData PProposalThresholds -- | @since 0.1.0 instance PUnsafeLiftDecl PProposalThresholds where type PLifted PProposalThresholds = ProposalThresholds @@ -529,40 +557,23 @@ deriving via -} newtype PProposalVotes (s :: S) = PProposalVotes (Term s (PMap 'Unsorted PResultTag PInteger)) - deriving + deriving stock + ( -- | @since 0.2.0 + Generic + ) + deriving anyclass ( -- | @since 0.1.0 PlutusType , -- | @since 0.1.0 PIsData ) - via (DerivePNewtype PProposalVotes (PMap 'Unsorted PResultTag PInteger)) --- | @since 0.1.0 -deriving via - PAsData (DerivePNewtype PProposalVotes (PMap 'Unsorted PResultTag PInteger)) - instance - PTryFrom PData (PAsData PProposalVotes) +-- | @since 0.2.0 +instance DerivePlutusType PProposalVotes where + type DPTStrat _ = PlutusTypeNewtype -{- | Retract votes given the option and the amount of votes. - - @since 0.1.0 --} -pretractVotes :: Term s (PResultTag :--> PInteger :--> PProposalVotes :--> PProposalVotes) -pretractVotes = phoistAcyclic $ - plam $ \rt count votes -> - let voteMap :: Term _ (PMap 'Unsorted PResultTag PInteger) - voteMap = pto votes - in pcon $ - PProposalVotes $ - PM.pupdate - # plam - ( \oldCount -> unTermCont $ do - newCount <- pletC $ oldCount - count - pguardC "Resulting vote count greater or equal to 0" $ 0 #<= newCount - pure $ pcon $ PJust newCount - ) - # rt - # voteMap +-- | @since 0.1.0 +instance PTryFrom PData (PAsData PProposalVotes) -- | @since 0.1.0 instance PUnsafeLiftDecl PProposalVotes where type PLifted PProposalVotes = ProposalVotes @@ -573,19 +584,6 @@ deriving via instance (PConstantDecl ProposalVotes) -{- | Plutarch-level version of 'emptyVotesFor'. - - @since 0.1.0 --} -pemptyVotesFor :: forall s a. (PIsData a) => Term s (PMap 'Unsorted PResultTag a :--> PProposalVotes) -pemptyVotesFor = - phoistAcyclic $ - plam - ( \m -> - pcon $ - PProposalVotes $ PM.pmap # plam (const $ pconstant 0) # m - ) - {- | Plutarch-level version of 'ProposalDatum'. @since 0.1.0 @@ -607,37 +605,29 @@ newtype PProposalDatum (s :: S) = PProposalDatum ) } deriving stock - ( -- | @since 0.1.0 - GHC.Generic - ) - deriving anyclass ( -- | @since 0.1.0 Generic ) deriving anyclass - ( -- | @since 0.1.0 - PIsDataRepr - ) - deriving ( -- | @since 0.1.0 PlutusType , -- | @since 0.1.0 PIsData - , -- | @since 0.1.0 - PDataFields , -- | @since 0.1.0 PEq ) - via (PIsDataReprInstances PProposalDatum) --- | @since 0.1.0 -deriving via PAsData (PIsDataReprInstances PProposalDatum) instance PTryFrom PData (PAsData PProposalDatum) +-- | @since 0.2.0 +instance DerivePlutusType PProposalDatum where + type DPTStrat _ = PlutusTypeNewtype + +instance PTryFrom PData (PAsData PProposalDatum) -- | @since 0.1.0 instance PUnsafeLiftDecl PProposalDatum where type PLifted PProposalDatum = ProposalDatum -- | @since 0.1.0 -deriving via (DerivePConstantViaData ProposalDatum PProposalDatum) instance (PConstantDecl ProposalDatum) +deriving via (DerivePConstantViaDataList ProposalDatum PProposalDatum) instance (PConstantDecl ProposalDatum) {- | Plutarch-level version of 'ProposalRedeemer'. @@ -646,33 +636,25 @@ deriving via (DerivePConstantViaData ProposalDatum PProposalDatum) instance (PCo data PProposalRedeemer (s :: S) = PVote (Term s (PDataRecord '["resultTag" ':= PResultTag])) | PCosign (Term s (PDataRecord '["newCosigners" ':= PBuiltinList (PAsData PPubKeyHash)])) - | PUnlock (Term s (PDataRecord '["resultTag" ':= PResultTag])) + | PUnlock (Term s (PDataRecord '[])) | PAdvanceProposal (Term s (PDataRecord '[])) deriving stock - ( -- | @since 0.1.0 - GHC.Generic - ) - deriving anyclass ( -- | @since 0.1.0 Generic ) deriving anyclass - ( -- | @since 0.1.0 - PIsDataRepr - ) - deriving ( -- | @since 0.1.0 PlutusType , -- | @since 0.1.0 PIsData ) - via PIsDataReprInstances PProposalRedeemer + +-- | @since 0.2.0 +instance DerivePlutusType PProposalRedeemer where + type DPTStrat _ = PlutusTypeData -- | @since 0.1.0 -deriving via - PAsData (PIsDataReprInstances PProposalRedeemer) - instance - PTryFrom PData (PAsData PProposalRedeemer) +instance PTryFrom PData PProposalRedeemer -- | @since 0.1.0 instance PUnsafeLiftDecl PProposalRedeemer where type PLifted PProposalRedeemer = ProposalRedeemer @@ -688,27 +670,50 @@ deriving via (DerivePConstantViaData ProposalRedeemer PProposalRedeemer) instanc @since 0.1.0 -} -proposalDatumValid :: Proposal -> Term s (Agora.Proposal.PProposalDatum :--> PBool) -proposalDatumValid proposal = - phoistAcyclic $ - plam $ \datum' -> unTermCont $ do - datum <- tcont $ pletFields @'["effects", "cosigners", "votes"] $ datum' - - let atLeastOneNegativeResult = - pany - # phoistAcyclic - (plam $ \m -> pnull #$ pto $ pfromData $ psndBuiltin # m) - #$ pto - $ pfromData datum.effects - - pure $ - foldr1 - (#&&) - [ ptraceIfFalse "Proposal has at least one ResultTag has no effects" atLeastOneNegativeResult - , ptraceIfFalse "Proposal has at least one cosigner" $ pnotNull # pfromData datum.cosigners - , ptraceIfFalse "Proposal has fewer cosigners than the limit" $ plength # pfromData datum.cosigners #<= pconstant proposal.maximumCosigners - , ptraceIfFalse "Proposal votes and effects are compatible with each other" $ PUM.pkeysEqual # datum.effects # pto (pfromData datum.votes) - ] + +{- | Return true if the effect list contains at least one neutral outcome. + + @since 0.2.0 +-} +phasNeutralEffect :: + forall (s :: S). + Term + s + ( PMap 'Unsorted PResultTag (PMap 'Unsorted PValidatorHash PDatumHash) + :--> PBool + ) +phasNeutralEffect = phoistAcyclic $ PAssocMap.pany # PAssocMap.pnull + +{- | Return true if votes and effects of the proposal have the same key set. + + @since 0.2.0 +-} +pisEffectsVotesCompatible :: + forall (s :: S). + Term + s + ( PMap 'Unsorted PResultTag (PMap 'Unsorted PValidatorHash PDatumHash) + :--> PProposalVotes + :--> PBool + ) +pisEffectsVotesCompatible = phoistAcyclic $ + plam $ \m (pto -> v :: Term _ (PMap _ _ _)) -> + PUM.pkeysEqual # m # v + +{- | Retutns true if vote counts of /all/ the options are zero. + + @since 0.2.0 +-} +pisVotesEmpty :: + forall (s :: S). + Term + s + ( PProposalVotes + :--> PBool + ) +pisVotesEmpty = phoistAcyclic $ + plam $ \(pto -> m :: Term _ (PMap _ _ _)) -> + PAssocMap.pall # plam (#== 0) # m {- | Wrapper for 'pwinner''. When the winner cannot be found, the 'neutral' option will be returned. @@ -793,13 +798,6 @@ phighestVotes = phoistAcyclic $ let l :: Term _ (PBuiltinList _) l = pto $ pto votes - f :: - Term - _ - ( PBuiltinPair (PAsData PResultTag) (PAsData PInteger) - :--> PBuiltinPair (PAsData PResultTag) (PAsData PInteger) - :--> PBuiltinPair (PAsData PResultTag) (PAsData PInteger) - ) f = phoistAcyclic $ plam $ \this last -> let lastVotes = pfromData $ psndBuiltin # last @@ -822,10 +820,57 @@ pneutralOption = phoistAcyclic $ let l :: Term _ (PBuiltinList (PBuiltinPair (PAsData PResultTag) _)) l = pto effects - f :: Term _ (PBuiltinPair (PAsData PResultTag) (PAsData (PMap 'Unsorted _ _)) :--> PBool) f = phoistAcyclic $ - plam $ \((pfromData . (psndBuiltin #) -> el)) -> - let el' :: Term _ (PBuiltinList _) - el' = pto el - in pnull # el' - in pfromData $ pfstBuiltin #$ mustBePJust # "No neutral option" #$ pfind # f # l + plam $ + pbuiltinUncurry $ \rt el -> + pif + (PAssocMap.pnull # el) + (pcon $ PJust rt) + (pcon PNothing) + in pfromJust #$ pfirstJust # f # l + +{- | Return true if the thresholds are valid. + + @since 0.2.0 +-} +pisProposalThresholdsValid :: forall (s :: S). Term s (PProposalThresholds :--> PBool) +pisProposalThresholdsValid = phoistAcyclic $ + plam $ \thresholds -> unTermCont $ do + thresholdsF <- pletAllC thresholds + + PDiscrete execute' <- pmatchC thresholdsF.execute + PDiscrete draft' <- pmatchC thresholdsF.create + PDiscrete vote' <- pmatchC thresholdsF.vote + + execute <- pletC $ pextract # execute' + draft <- pletC $ pextract # draft' + vote <- pletC $ pextract # vote' + + pure $ + foldr1 + (#&&) + [ ptraceIfFalse "Execute threshold is less than or equal to 0" $ 0 #<= execute + , ptraceIfFalse "Draft threshold is less than or equal to 0" $ 0 #<= draft + , ptraceIfFalse "Vote threshold is less than or equal to 0" $ 0 #<= vote + ] + +{- | Retract votes given the option and the amount of votes. + + @since 0.1.0 +-} +pretractVotes :: Term s (PResultTag :--> PInteger :--> PProposalVotes :--> PProposalVotes) +pretractVotes = phoistAcyclic $ + plam $ \rt count votes -> + let voteMap :: Term _ (PMap 'Unsorted PResultTag PInteger) + voteMap = pto votes + in pcon $ + PProposalVotes $ + PM.pupdate + # plam + ( \oldCount -> unTermCont $ do + newCount <- pletC $ oldCount - count + pguardC "Resulting vote count greater or equal to 0" $ 0 #<= newCount + pure $ pcon $ PJust newCount + ) + # rt + # voteMap diff --git a/agora/Agora/Proposal/Scripts.hs b/agora/Agora/Proposal/Scripts.hs index 6a3df7f3..1da4178a 100644 --- a/agora/Agora/Proposal/Scripts.hs +++ b/agora/Agora/Proposal/Scripts.hs @@ -13,9 +13,7 @@ module Agora.Proposal.Scripts ( import Agora.Proposal ( PProposalDatum (PProposalDatum), PProposalRedeemer (..), - PProposalStatus (..), PProposalVotes (PProposalVotes), - Proposal (governorSTAssetClass, stakeSTAssetClass), ProposalStatus (..), pretractVotes, pwinner', @@ -27,37 +25,45 @@ import Agora.Proposal.Time ( isLockingPeriod, isVotingPeriod, ) +import Agora.Scripts (AgoraScripts, governorSTSymbol, proposalSTSymbol, stakeSTAssetClass) import Agora.Stake ( PProposalLock (..), PStakeDatum (..), - PStakeUsage (..), - findStakeOwnedBy, - pgetStakeUsage, + pextractVoteOption, + pgetStakeRole, + pisCreator, + pisIrrelevant, + pisPureCreator, + pisVoter, ) import Agora.Utils ( - getMintingPolicySymbol, - mustBePJust, mustFindDatum', + pltAsData, ) import Plutarch.Api.V1 ( + PDatumHash, PMintingPolicy, + PPubKeyHash, PScriptContext (PScriptContext), PScriptPurpose (PMinting, PSpending), PTxInfo (PTxInfo), + PTxOut, PValidator, ) import Plutarch.Api.V1.AssetClass (passetClass, passetClassValueOf) import Plutarch.Api.V1.ScriptContext ( pfindTxInByTxOutRef, pisTokenSpent, + ptryFindDatum, ptxSignedBy, - pvalueSpent, ) import "liqwid-plutarch-extra" Plutarch.Api.V1.Value (psymbolValueOf) import Plutarch.Extra.Comonad (pextract) -import Plutarch.Extra.List (pisUniqBy) +import Plutarch.Extra.Field (pletAllC) +import Plutarch.Extra.IsData (pmatchEnum) +import Plutarch.Extra.List (pisUniq', pmapMaybe, pmergeBy, pmsortBy) import Plutarch.Extra.Map (plookup, pupdate) -import Plutarch.Extra.Maybe (pisJust) +import Plutarch.Extra.Maybe (passertPJust, pfromDJust, pfromJust, pisJust) import Plutarch.Extra.Record (mkRecordConstr, (.&), (.=)) import Plutarch.Extra.TermCont ( pguardC, @@ -97,24 +103,20 @@ proposalPolicy :: proposalPolicy (AssetClass (govCs, govTn)) = plam $ \_redeemer ctx' -> unTermCont $ do PScriptContext ctx' <- pmatchC ctx' - ctx <- tcont $ pletFields @'["txInfo", "purpose"] ctx' + ctx <- pletAllC ctx' PTxInfo txInfo' <- pmatchC $ pfromData ctx.txInfo - txInfo <- tcont $ pletFields @'["inputs", "mint"] txInfo' - PMinting _ownSymbol <- pmatchC $ pfromData ctx.purpose - - let inputs = txInfo.inputs - mintedValue = pfromData txInfo.mint + txInfo <- pletFieldsC @'["inputs", "mint"] txInfo' PMinting ownSymbol' <- pmatchC $ pfromData ctx.purpose let mintedProposalST = passetClassValueOf - # mintedValue + # pfromData txInfo.mint # (passetClass # (pfield @"_0" # ownSymbol') # pconstant "") pguardC "Governance state-thread token must move" $ pisTokenSpent # (passetClass # pconstant govCs # pconstant govTn) - # inputs + # txInfo.inputs pguardC "Minted exactly one proposal ST" $ mintedProposalST #== 1 @@ -149,53 +151,45 @@ proposalPolicy (AssetClass (govCs, govTn)) = @since 0.1.0 -} -proposalValidator :: Proposal -> ClosedTerm PValidator -proposalValidator proposal = +proposalValidator :: + -- | Lazy precompiled scripts. + AgoraScripts -> + -- | See 'Agora.Governor.Governor.maximumCosigners'. + Integer -> + ClosedTerm PValidator +proposalValidator as maximumCosigners = plam $ \datum redeemer ctx' -> unTermCont $ do PScriptContext ctx' <- pmatchC ctx' - ctx <- tcont $ pletFields @'["txInfo", "purpose"] ctx' + ctx <- pletFieldsC @'["txInfo", "purpose"] ctx' txInfo <- pletC $ pfromData ctx.txInfo PTxInfo txInfo' <- pmatchC txInfo txInfoF <- - tcont $ - pletFields - @'[ "inputs" - , "outputs" - , "mint" - , "datums" - , "signatories" - , "validRange" - ] - txInfo' + pletFieldsC + @'[ "inputs" + , "outputs" + , "mint" + , "datums" + , "signatories" + , "validRange" + ] + txInfo' PSpending ((pfield @"_0" #) -> txOutRef) <- pmatchC $ pfromData ctx.purpose PJust ((pfield @"resolved" #) -> txOut) <- pmatchC $ pfindTxInByTxOutRef # txOutRef # txInfoF.inputs - txOutF <- tcont $ pletFields @'["address", "value"] $ txOut - - (pfromData -> proposalDatum, _) <- - ptryFromC @(PAsData PProposalDatum) datum - (pfromData -> proposalRedeemer, _) <- - ptryFromC @(PAsData PProposalRedeemer) redeemer - - proposalF <- - tcont $ - pletFields - @'[ "proposalId" - , "effects" - , "status" - , "cosigners" - , "thresholds" - , "votes" - , "timingConfig" - , "startingTime" - ] - proposalDatum + txOutF <- pletFieldsC @'["address", "value"] $ txOut + + proposalDatum <- pfromData . fst <$> ptryFromC @(PAsData PProposalDatum) datum + proposalRedeemer <- fst <$> ptryFromC @PProposalRedeemer redeemer + + proposalF <- pletAllC $ pto proposalDatum ownAddress <- pletC $ txOutF.address - let stCurrencySymbol = - pconstant $ getMintingPolicySymbol (proposalPolicy proposal.governorSTAssetClass) - valueSpent <- pletC $ pvalueSpent # txInfoF.inputs + thresholdsF <- pletAllC proposalF.thresholds + + currentStatus <- pletC $ pfromData $ proposalF.status + + let stCurrencySymbol = pconstant $ proposalSTSymbol as signedBy <- pletC $ ptxSignedBy # txInfoF.signatories @@ -210,19 +204,20 @@ proposalValidator proposal = -- proposal inputs in one thansaction. ownOutput <- pletC $ - mustBePJust # "Own output should be present" #$ pfind + passertPJust # "Own output should be present" #$ pfind # plam ( \input -> unTermCont $ do - inputF <- tcont $ pletFields @'["address", "value", "datumHash"] input + inputF <- pletAllC input -- TODO: this is highly inefficient: O(n) for every output, -- Maybe we can cache the sorted datum map? let datum = - mustFindDatum' @PProposalDatum - # inputF.datumHash - # txInfoF.datums + pfromData $ + mustFindDatum' @(PAsData PProposalDatum) + # inputF.datumHash + # txInfoF.datums - proposalId = pfield @"proposalId" # datum + proposalId = pfield @"proposalId" # pto datum pure $ inputF.address #== ownAddress @@ -233,342 +228,478 @@ proposalValidator proposal = proposalOut <- pletC $ - mustFindDatum' @PProposalDatum - # (pfield @"datumHash" # ownOutput) - # txInfoF.datums + pfromData $ + mustFindDatum' @(PAsData PProposalDatum) + # (pfield @"datumHash" # ownOutput) + # txInfoF.datums proposalUnchanged <- pletC $ proposalOut #== proposalDatum + + proposalOutStatus <- + pletC $ + pfromData $ + pfield @"status" # pto proposalOut + + onlyStatusChanged <- + pletC $ + -- Only the status of proposals is updated. + proposalOut + #== mkRecordConstr + PProposalDatum + ( #proposalId .= proposalF.proposalId + .& #effects .= proposalF.effects + .& #status .= pdata proposalOutStatus + .& #cosigners .= proposalF.cosigners + .& #thresholds .= proposalF.thresholds + .& #votes .= proposalF.votes + .& #timingConfig .= proposalF.timingConfig + .& #startingTime .= proposalF.startingTime + ) + -------------------------------------------------------------------------- - -- Find the stake input and stake output by SST. - let AssetClass (stakeSym, stakeTn) = proposal.stakeSTAssetClass + -- Find the stake inputs/outputs by SST. + + let AssetClass (stakeSym, stakeTn) = stakeSTAssetClass as stakeSTAssetClass <- pletC $ passetClass # pconstant stakeSym # pconstant stakeTn - spentStakeST <- - pletC $ passetClassValueOf # valueSpent # stakeSTAssetClass - - let stakeInput = - pfield @"resolved" - #$ mustBePJust - # "Stake input should be present" - #$ pfind - # plam - ( \(pfromData . (pfield @"value" #) . (pfield @"resolved" #) -> value) -> - passetClassValueOf # value # stakeSTAssetClass #== 1 - ) - # pfromData txInfoF.inputs - stakeIn <- pletC $ mustFindDatum' @PStakeDatum # (pfield @"datumHash" # stakeInput) # txInfoF.datums - stakeInF <- pletFieldsC @'["stakedAmount", "lockedBy", "owner"] stakeIn - - let stakeOutput = - mustBePJust # "Stake output should be present" - #$ pfind - # plam - ( \(pfromData . (pfield @"value" #) -> value) -> - passetClassValueOf # value # stakeSTAssetClass #== 1 + filterStakeDatumHash :: Term _ (PTxOut :--> PMaybe (PAsData PDatumHash)) <- + pletC $ + plam $ \txOut -> unTermCont $ do + txOutF <- pletFieldsC @'["value", "datumHash"] txOut + pure $ + pif + (passetClassValueOf # txOutF.value # stakeSTAssetClass #== 1) + ( let datumHash = pfromDJust # txOutF.datumHash + in pcon $ PJust $ pdata datumHash ) - # pfromData txInfoF.outputs - - stakeOut <- pletC $ mustFindDatum' @PStakeDatum # (pfield @"datumHash" # stakeOutput) # txInfoF.datums + (pcon PNothing) - stakeUnchanged <- pletC $ stakeIn #== stakeOut - - -------------------------------------------------------------------------- + stakeInputDatumHashes <- + pletC $ + pmapMaybe @PBuiltinList + # plam ((filterStakeDatumHash #) . (pfield @"resolved" #)) + # txInfoF.inputs - pure $ - pmatch proposalRedeemer $ \case - PVote r -> unTermCont $ do - pguardC "Input proposal must be in VotingReady state" $ - proposalF.status #== pconstant VotingReady - - pguardC "Proposal time should be wthin the voting period" $ - isVotingPeriod # proposalF.timingConfig # proposalF.startingTime # currentTime - - -- Ensure the transaction is voting to a valid 'ResultTag'(outcome). - PProposalVotes voteMap <- pmatchC proposalF.votes - voteFor <- pletC $ pfromData $ pfield @"resultTag" # r - - pguardC "Vote option should be valid" $ - pisJust #$ plookup # voteFor # voteMap - - -- Ensure that no lock with the current proposal id has been put on the stake. - pguardC "Same stake shouldn't vote on the same proposal twice" $ - pnot #$ pany - # plam - ( \((pfield @"proposalTag" #) . pfromData -> pid) -> - pid #== proposalF.proposalId - ) - # pfromData stakeInF.lockedBy - - let -- The amount of new votes should be the 'stakedAmount'. - -- Update the vote counter of the proposal, and leave other stuff as is. - expectedNewVotes = pmatch (pfromData proposalF.votes) $ \(PProposalVotes m) -> - pcon $ - PProposalVotes $ - pupdate - # plam - ( \votes -> unTermCont $ do - PDiscrete v <- pmatchC stakeInF.stakedAmount - pure $ pcon $ PJust $ votes + (pextract # v) - ) - # voteFor - # m - expectedProposalOut = - mkRecordConstr - PProposalDatum - ( #proposalId .= proposalF.proposalId - .& #effects .= proposalF.effects - .& #status .= proposalF.status - .& #cosigners .= proposalF.cosigners - .& #thresholds .= proposalF.thresholds - .& #votes .= pdata expectedNewVotes - .& #timingConfig .= proposalF.timingConfig - .& #startingTime .= proposalF.startingTime + stakeOutputDatumHashes <- + pletC $ + pmapMaybe @PBuiltinList + # filterStakeDatumHash + # txInfoF.outputs + + stakeInputNum <- pletC $ plength # stakeInputDatumHashes + + pguardC "Every stake input should have a correspoding output" $ + stakeInputNum #== plength # stakeOutputDatumHashes + + ---------------------------------------------------------------------------- + + withMultipleStakes' :: + Term + _ + ( ( PInteger + :--> PBuiltinList (PAsData PPubKeyHash) + :--> PUnit + ) + :--> PUnit + ) <- + pletC $ + plam $ \validationLogic -> unTermCont $ do + -- The following code ensures that all the stake datums are not + -- changed. + -- + -- TODO: This is quite inefficient (O(nlogn)) but for now we don't + -- have a nice way to check this. In plutus v2 we'll have map of + -- (Script -> Redeemer) in ScriptContext, which should be the + -- straight up solution. + let sortDatumHashes = phoistAcyclic $ pmsortBy # pltAsData + + sortedStakeInputDatumHashes = + sortDatumHashes # stakeInputDatumHashes + + sortedStakeOutputDatumHashes = + sortDatumHashes # stakeOutputDatumHashes + + pguardC "All stake datum are unchanged" $ + plistEquals + # sortedStakeInputDatumHashes + # sortedStakeOutputDatumHashes + + PPair totalStakedAmount stakeOwners <- + pmatchC $ + pfoldl + # plam + ( \l dh -> unTermCont $ do + let stake = + pfromData $ + pfromJust + #$ ptryFindDatum @(PAsData PStakeDatum) + # pfromData dh + # txInfoF.datums + + stakeF <- pletFieldsC @'["stakedAmount", "owner"] $ pto stake + + PPair amount owners <- pmatchC l + + let newAmount = amount + punsafeCoerce (pfromData stakeF.stakedAmount) + updatedOwners = pcons # stakeF.owner # owners + + pure $ pcon $ PPair newAmount updatedOwners ) + # pcon (PPair (0 :: Term _ PInteger) (pnil @PBuiltinList)) + # stakeInputDatumHashes - pguardC "Output proposal should be valid" $ proposalOut #== expectedProposalOut + sortedStakeOwners <- pletC $ pmsortBy # pltAsData # stakeOwners - -- We validate the output stake datum here as well: We need the vote option - -- to create a valid 'ProposalLock', however the vote option is encoded - -- in the proposal redeemer, which is invisible for the stake validator. + pure $ validationLogic # totalStakedAmount # sortedStakeOwners - let newProposalLock = - mkRecordConstr - PProposalLock - ( #vote .= pdata voteFor - .& #proposalTag .= proposalF.proposalId - ) - -- Prepend the new lock to existing locks - expectedProposalLocks = - pcons - # pdata newProposalLock - # pfromData stakeInF.lockedBy - expectedStakeOut = - mkRecordConstr - PStakeDatum - ( #stakedAmount .= stakeInF.stakedAmount - .& #owner .= stakeInF.owner - .& #lockedBy .= pdata expectedProposalLocks - ) + withSingleStake' :: + Term + _ + ( ( PStakeDatum :--> PStakeDatum :--> PBool :--> PUnit + ) + :--> PUnit + ) <- pletC $ + plam $ \validationLogic -> unTermCont $ do + pguardC "Can only deal with one stake" $ + stakeInputNum #== 1 - pguardC "Output stake should be locked by the proposal" $ expectedStakeOut #== stakeOut + stakeInputHash <- pletC $ pfromData $ phead # stakeInputDatumHashes + stakeOutputHash <- pletC $ pfromData $ phead # stakeOutputDatumHashes - pure $ popaque (pconstant ()) - -------------------------------------------------------------------------- - PCosign r -> unTermCont $ do - pguardC "Stake should not change" stakeUnchanged + stakeIn :: Term _ PStakeDatum <- + pletC $ pfromData $ pfromJust #$ ptryFindDatum # stakeInputHash # txInfoF.datums - newSigs <- pletC $ pfield @"newCosigners" # r + stakeOut :: Term _ PStakeDatum <- + pletC $ pfromData $ pfromJust #$ ptryFindDatum # stakeOutputHash # txInfoF.datums - pguardC "Cosigners are unique" $ - pisUniqBy - # phoistAcyclic (plam (#==)) - # phoistAcyclic (plam $ \(pfromData -> x) (pfromData -> y) -> x #< y) - # newSigs + stakeUnchanged <- pletC $ stakeInputHash #== stakeOutputHash - pguardC "Signed by all new cosigners" $ - pall # signedBy # newSigs + pure $ validationLogic # stakeIn # stakeOut # stakeUnchanged - pguardC "As many new cosigners as Stake datums" $ - spentStakeST #== plength # newSigs + let withMultipleStakes val = + withMultipleStakes' #$ plam $ + \totalStakedAmount + sortedStakeOwner -> + unTermCont $ + val totalStakedAmount sortedStakeOwner - pguardC "All new cosigners are witnessed by their Stake datums" $ - pall - # plam - ( \sig -> - pmatch - ( findStakeOwnedBy # stakeSTAssetClass - # pfromData sig - # txInfoF.datums - # txInfoF.inputs - ) - $ \case - PNothing -> pcon PFalse - PJust _ -> pcon PTrue - ) - # newSigs - - let updatedSigs = pconcat # newSigs # proposalF.cosigners - expectedDatum = - mkRecordConstr - PProposalDatum - ( #proposalId .= proposalF.proposalId - .& #effects .= proposalF.effects - .& #status .= proposalF.status - .& #cosigners .= pdata updatedSigs - .& #thresholds .= proposalF.thresholds - .& #votes .= proposalF.votes - .& #timingConfig .= proposalF.timingConfig - .& #startingTime .= proposalF.startingTime - ) + withSingleStake val = + withSingleStake' #$ plam $ \stakeIn stakeOut stakeUnchange -> unTermCont $ do + stakeInF <- pletAllC $ pto stakeIn - pguardC "Signatures are correctly added to cosignature list" $ - proposalOut #== expectedDatum - - pure $ popaque (pconstant ()) - -------------------------------------------------------------------------- - PUnlock r -> unTermCont $ do - -- At draft stage, the votes should be empty. - pguardC "Shouldn't retract votes from a draft proposal" $ - pnot #$ proposalF.status #== pconstantData Draft - - -- This is the vote option we're retracting from. - retractFrom <- pletC $ pfield @"resultTag" # r - - -- Determine if the input stake is actually locked by this proposal. - stakeUsage <- pletC $ pgetStakeUsage # stakeInF.lockedBy # proposalF.proposalId - - pguardC "Stake input relevant" $ - pmatch stakeUsage $ \case - PDidNothing -> - ptraceIfFalse "Stake should be relevant" $ - pconstant False - PCreated -> - ptraceIfFalse "Removing creator's locks means status is Finished" $ - proposalF.status #== pconstantData Finished - PVotedFor rt -> - ptraceIfFalse "Result tag should match the one given in the redeemer" $ - rt #== retractFrom - - -- The count of removing votes is equal to the 'stakeAmount' of input stake. - retractCount <- - pletC $ - pmatch stakeInF.stakedAmount $ \(PDiscrete v) -> pextract # v - - -- The votes can only change when the proposal still allows voting. - let shouldUpdateVotes = - proposalF.status #== pconstantData VotingReady - #&& pnot # (pcon PCreated #== stakeUsage) - - pguardC "Proposal output correct" $ - pif - shouldUpdateVotes - ( let -- Remove votes and leave other parts of the proposal as it. - expectedVotes = pretractVotes # retractFrom # retractCount # proposalF.votes - - expectedProposalOut = - mkRecordConstr - PProposalDatum - ( #proposalId .= proposalF.proposalId - .& #effects .= proposalF.effects - .& #status .= proposalF.status - .& #cosigners .= proposalF.cosigners - .& #thresholds .= proposalF.thresholds - .& #votes .= pdata expectedVotes - .& #timingConfig .= proposalF.timingConfig - .& #startingTime .= proposalF.startingTime - ) - in ptraceIfFalse "Update votes" $ - expectedProposalOut #== proposalOut - ) - -- No change to the proposal is allowed. - $ ptraceIfFalse "Proposal unchanged" proposalUnchanged - - -- At last, we ensure that all locks belong to this proposal will be removed. - stakeOutputLocks <- pletC $ pfield @"lockedBy" # stakeOut - - let templateStakeOut = - mkRecordConstr - PStakeDatum - ( #stakedAmount .= stakeInF.stakedAmount - .& #owner .= stakeInF.owner - .& #lockedBy .= stakeOutputLocks - ) + val stakeInF stakeOut stakeUnchange - pguardC "Only locks updated in the output stake" $ - templateStakeOut #== stakeOut - - pguardC "All relevant locks removed from the stake" $ - pgetStakeUsage # pfromData stakeOutputLocks - # proposalF.proposalId #== pcon PDidNothing - - pure $ popaque (pconstant ()) - -------------------------------------------------------------------------- - PAdvanceProposal _r -> unTermCont $ do - pguardC "Stake should not change" stakeUnchanged - - proposalOutStatus <- pletC $ pfield @"status" # proposalOut - - let -- Only the status of proposals should be updated in this case. - templateProposalOut = - mkRecordConstr - PProposalDatum - ( #proposalId .= proposalF.proposalId - .& #effects .= proposalF.effects - .& #status .= proposalOutStatus - .& #cosigners .= proposalF.cosigners - .& #thresholds .= proposalF.thresholds - .& #votes .= proposalF.votes - .& #timingConfig .= proposalF.timingConfig - .& #startingTime .= proposalF.startingTime - ) - - pguardC "Only status changes in the output proposal" $ - templateProposalOut #== proposalOut + pure $ + popaque $ + pmatch proposalRedeemer $ \case + PCosign r -> withMultipleStakes $ \_ sortedStakeOwners -> do + pguardC "Should be in draft state" $ + currentStatus #== pconstant Draft + + newSigs <- pletC $ pfield @"newCosigners" # r + + pguardC "Signed by all new cosigners" $ + pall # signedBy # newSigs + + updatedSigs <- + pletC $ + pmergeBy # pltAsData + # newSigs + # proposalF.cosigners + + pguardC "Less cosigners than maximum limit" $ + plength # updatedSigs #< pconstant maximumCosigners + + pguardC "Cosigners are unique" $ + pisUniq' # updatedSigs + + pguardC "All new cosigners are witnessed by their Stake datums" $ + plistEquals # sortedStakeOwners # newSigs + + let expectedDatum = + mkRecordConstr + PProposalDatum + ( #proposalId .= proposalF.proposalId + .& #effects .= proposalF.effects + .& #status .= proposalF.status + .& #cosigners .= pdata updatedSigs + .& #thresholds .= proposalF.thresholds + .& #votes .= proposalF.votes + .& #timingConfig .= proposalF.timingConfig + .& #startingTime .= proposalF.startingTime + ) + + pguardC "Signatures are correctly added to cosignature list" $ + proposalOut #== expectedDatum + + pure $ pconstant () + + ---------------------------------------------------------------------- + + PVote r -> withSingleStake $ \stakeInF stakeOut _ -> do + pguardC "Input proposal must be in VotingReady state" $ + currentStatus #== pconstant VotingReady + + pguardC "Proposal time should be wthin the voting period" $ + isVotingPeriod # proposalF.timingConfig + # proposalF.startingTime + #$ pfromJust + # currentTime + + -- Ensure the transaction is voting to a valid 'ResultTag'(outcome). + PProposalVotes voteMap <- pmatchC proposalF.votes + voteFor <- pletC $ pfromData $ pfield @"resultTag" # r + + pguardC "Vote option should be valid" $ + pisJust #$ plookup # voteFor # voteMap + + -- Ensure that no lock with the current proposal id has been put on the stake. + pguardC "Same stake shouldn't vote on the same proposal twice" $ + pnot #$ pisVoter #$ pgetStakeRole # proposalF.proposalId # pfromData stakeInF.lockedBy + + let -- The amount of new votes should be the 'stakedAmount'. + -- Update the vote counter of the proposal, and leave other stuff as is. + expectedNewVotes = pmatch (pfromData proposalF.votes) $ \(PProposalVotes m) -> + pcon $ + PProposalVotes $ + pupdate + # plam + ( \votes -> unTermCont $ do + PDiscrete v <- pmatchC stakeInF.stakedAmount + pure $ pcon $ PJust $ votes + (pextract # v) + ) + # voteFor + # m + expectedProposalOut = + mkRecordConstr + PProposalDatum + ( #proposalId .= proposalF.proposalId + .& #effects .= proposalF.effects + .& #status .= proposalF.status + .& #cosigners .= proposalF.cosigners + .& #thresholds .= proposalF.thresholds + .& #votes .= pdata expectedNewVotes + .& #timingConfig .= proposalF.timingConfig + .& #startingTime .= proposalF.startingTime + ) + + pguardC "Output proposal should be valid" $ proposalOut #== expectedProposalOut + + -- We validate the output stake datum here as well: We need the vote option + -- to create a valid 'ProposalLock', however the vote option is encoded + -- in the proposal redeemer, which is invisible for the stake validator. + + let newProposalLock = + mkRecordConstr + PVoted + ( #votedOn .= proposalF.proposalId + .& #votedFor .= pdata voteFor + ) + -- Prepend the new lock to existing locks + expectedProposalLocks = + pcons + # pdata newProposalLock + # pfromData stakeInF.lockedBy + expectedStakeOut = + mkRecordConstr + PStakeDatum + ( #stakedAmount .= stakeInF.stakedAmount + .& #owner .= stakeInF.owner + .& #delegatedTo .= stakeInF.delegatedTo + .& #lockedBy .= pdata expectedProposalLocks + ) + + pguardC "Output stake should be locked by the proposal" $ expectedStakeOut #== stakeOut + + pure $ pconstant () + + ---------------------------------------------------------------------- + + PUnlock _ -> withSingleStake $ \stakeInF stakeOut _ -> do + stakeRole <- pletC $ pgetStakeRole # proposalF.proposalId # stakeInF.lockedBy + + pguardC "Stake input should be relevant" $ + pnot #$ pisIrrelevant # stakeRole + + retractCount <- + pletC $ + pmatch stakeInF.stakedAmount $ \(PDiscrete v) -> pextract # v + + -- The votes can only change when the proposal still allows voting. + let shouldUpdateVotes = + currentStatus #== pconstant VotingReady + #&& pnot # (pisPureCreator # stakeRole) + + allowRemovingCreatorLock = + currentStatus #== pconstant Finished + + isCreator = pisCreator # stakeRole + + -- If the stake has been used for creating the proposal, + -- the creator lock can only be removed when the proposal + -- is finished. + -- + -- In other cases, all the locks related to this + -- proposal should be removed. + validateOutputLocks = plam $ \locks -> + plet + ( pgetStakeRole # proposalF.proposalId # locks + ) + $ \newStakeRole -> + pif + (isCreator #&& pnot # allowRemovingCreatorLock) + (pisPureCreator # newStakeRole) + (pisIrrelevant # newStakeRole) + + pguardC "Proposal output correct" $ + pif + shouldUpdateVotes + ( let -- Remove votes and leave other parts of the proposal as it. + expectedVotes = pretractVotes # (pextractVoteOption # stakeRole) # retractCount # proposalF.votes + + expectedProposalOut = + mkRecordConstr + PProposalDatum + ( #proposalId .= proposalF.proposalId + .& #effects .= proposalF.effects + .& #status .= proposalF.status + .& #cosigners .= proposalF.cosigners + .& #thresholds .= proposalF.thresholds + .& #votes .= pdata expectedVotes + .& #timingConfig .= proposalF.timingConfig + .& #startingTime .= proposalF.startingTime + ) + in ptraceIfFalse "Update votes" $ + expectedProposalOut #== proposalOut + ) + -- No change to the proposal is allowed. + $ ptraceIfFalse "Proposal unchanged" proposalUnchanged - inDraftPeriod <- pletC $ isDraftPeriod # proposalF.timingConfig # proposalF.startingTime # currentTime - inVotingPeriod <- pletC $ isVotingPeriod # proposalF.timingConfig # proposalF.startingTime # currentTime - inLockedPeriod <- pletC $ isLockingPeriod # proposalF.timingConfig # proposalF.startingTime # currentTime - inExecutionPeriod <- pletC $ isExecutionPeriod # proposalF.timingConfig # proposalF.startingTime # currentTime + -- At last, we ensure that all locks belong to this proposal will be removed. + stakeOutputLocks <- pletC $ pfield @"lockedBy" # pto stakeOut - -- Check the timings. - let isFinished = proposalF.status #== pconstantData Finished + let templateStakeOut = + mkRecordConstr + PStakeDatum + ( #stakedAmount .= stakeInF.stakedAmount + .& #owner .= stakeInF.owner + .& #delegatedTo .= stakeInF.delegatedTo + .& #lockedBy .= pdata stakeOutputLocks + ) - notTooLate = pmatch (pfromData proposalF.status) $ \case - PDraft _ -> inDraftPeriod - -- Can only advance after the voting period is over. - PVotingReady _ -> inLockedPeriod - PLocked _ -> inExecutionPeriod - _ -> pconstant False + pguardC "Only locks updated in the output stake" $ + templateStakeOut #== stakeOut - notTooEarly = pmatch (pfromData proposalF.status) $ \case - PVotingReady _ -> pnot # inVotingPeriod - PLocked _ -> pnot # inLockedPeriod - _ -> pconstant True + pguardC "All relevant locks removed from the stake" $ + validateOutputLocks # stakeOutputLocks - pguardC "Cannot advance ahead of time" notTooEarly - pguardC "Finished proposals cannot be advanced" $ pnot # isFinished + pure $ pconstant () - thresholdsF <- pletFieldsC @'["execute"] proposalF.thresholds + ---------------------------------------------------------------------- + + PAdvanceProposal _ -> + let currentTime' = pfromJust # currentTime + fromDraft = withMultipleStakes $ \totalStakedAmount sortedStakeOwners -> + pmatchC (isDraftPeriod # proposalF.timingConfig # proposalF.startingTime # currentTime') >>= \case + PTrue -> do + pguardC "More cosigns than minimum amount" $ + punsafeCoerce (pfromData thresholdsF.vote) #< totalStakedAmount + + pguardC "All new cosigners are witnessed by their Stake datums" $ + plistEquals # sortedStakeOwners # proposalF.cosigners + + -- 'Draft' -> 'VotingReady' + pguardC "Proposal status set to VotingReady" $ + proposalOutStatus #== pconstant VotingReady + + pure $ pconstant () + PFalse -> do + pguardC "Advance to failed state" $ proposalOutStatus #== pconstant Finished + + pure $ pconstant () + + fromOther = withSingleStake $ \_ _ stakeUnchanged -> do + pguardC "Stake should not change" stakeUnchanged + + pguardC + "Only status changes in the output proposal" + onlyStatusChanged + + inVotingPeriod <- pletC $ isVotingPeriod # proposalF.timingConfig # proposalF.startingTime # currentTime' + inLockedPeriod <- pletC $ isLockingPeriod # proposalF.timingConfig # proposalF.startingTime # currentTime' + inExecutionPeriod <- pletC $ isExecutionPeriod # proposalF.timingConfig # proposalF.startingTime # currentTime' + + proposalStatus <- pletC $ pto $ pfromData proposalF.status + + -- Check the timings. + let isFinished = currentStatus #== pconstant Finished + + notTooLate = pmatchEnum proposalStatus $ \case + -- Can only advance after the voting period is over. + VotingReady -> inLockedPeriod + Locked -> inExecutionPeriod + _ -> pconstant False + + notTooEarly = pmatchEnum (pto $ pfromData proposalF.status) $ \case + VotingReady -> pnot # inVotingPeriod + Locked -> pnot # inLockedPeriod + _ -> pconstant True + + pguardC "Cannot advance ahead of time" notTooEarly + pguardC "Finished proposals cannot be advanced" $ pnot # isFinished + + let gstSymbol = pconstant $ governorSTSymbol as + + gstMoved <- + pletC $ + pany + # plam + ( \( (pfield @"value" #) + . (pfield @"resolved" #) -> + value + ) -> + psymbolValueOf # gstSymbol # value #== 1 + ) + # pfromData txInfoF.inputs + + let toFailedState = unTermCont $ do + pguardC "Proposal should fail: not on time" $ + proposalOutStatus #== pconstant Finished + + pguardC "GST not moved" $ pnot # gstMoved + + pure $ pconstant () + + toNextState = pmatchEnum proposalStatus $ \case + VotingReady -> unTermCont $ do + -- 'VotingReady' -> 'Locked' + pguardC "Proposal status set to Locked" $ + proposalOutStatus #== pconstant Locked + + pguardC "Winner outcome not found" $ + pisJust #$ pwinner' # proposalF.votes + #$ punsafeCoerce + $ pfromData thresholdsF.execute + + pure $ pconstant () + Locked -> unTermCont $ do + -- 'Locked' -> 'Finished' + pguardC "Proposal status set to Finished" $ + proposalOutStatus #== pconstant Finished - pure $ - pif - notTooLate - -- On time: advance to next status. - ( pmatch (pfromData proposalF.status) $ \case - PDraft _ -> unTermCont $ do - -- TODO: Perform other necessary checks. - - -- 'Draft' -> 'VotingReady' - pguardC "Proposal status set to VotingReady" $ - proposalOutStatus #== pconstantData VotingReady - - pure $ popaque (pconstant ()) - PVotingReady _ -> unTermCont $ do - -- 'VotingReady' -> 'Locked' - pguardC "Proposal status set to Locked" $ - proposalOutStatus #== pconstantData Locked - - pguardC "Winner outcome not found" $ - pisJust #$ pwinner' # proposalF.votes - #$ punsafeCoerce - $ pfromData thresholdsF.execute - - pure $ popaque (pconstant ()) - PLocked _ -> unTermCont $ do - -- 'Locked' -> 'Finished' - pguardC "Proposal status set to Finished" $ - proposalOutStatus #== pconstantData Finished - - -- TODO: Perform other necessary checks. - pure $ popaque (pconstant ()) - _ -> popaque (pconstant ()) - ) - -- Too late: failed proposal, status set to 'Finished'. - ( popaque $ - ptraceIfFalse "Proposal should fail: not on time" $ - proposalOutStatus #== pconstantData Finished - -- TODO: Should check that the GST is not moved - -- if the proposal is in 'Locked' state. - ) + pguardC "GST moved" gstMoved + + -- TODO: Perform other necessary checks. + pure $ pconstant () + _ -> pconstant () + + pure $ + pif + notTooLate + -- On time: advance to next status. + toNextState + -- Too late: failed proposal, status set to 'Finished'. + toFailedState + in pif (currentStatus #== pconstant Draft) fromDraft fromOther diff --git a/agora/Agora/Proposal/Time.hs b/agora/Agora/Proposal/Time.hs index 1a821299..97d61964 100644 --- a/agora/Agora/Proposal/Time.hs +++ b/agora/Agora/Proposal/Time.hs @@ -26,11 +26,11 @@ module Agora.Proposal.Time ( isVotingPeriod, isLockingPeriod, isExecutionPeriod, + pisProposalTimingConfigValid, + pisMaxTimeRangeWidthValid, ) where -import Agora.Plutarch.Orphans () -import GHC.Generics qualified as GHC -import Generics.SOP (Generic, HasDatatypeInfo, I (I)) +import Control.Composition ((.*)) import Plutarch.Api.V1 ( PExtended (PFinite), PInterval (PInterval), @@ -42,18 +42,19 @@ import Plutarch.Api.V1 ( import Plutarch.DataRepr ( DerivePConstantViaData (..), PDataFields, - PIsDataReprInstances (..), ) -import Plutarch.Extra.TermCont (pguardC, pmatchC) +import Plutarch.Extra.Applicative (PApply (pliftA2)) +import Plutarch.Extra.Field (pletAll, pletAllC) +import Plutarch.Extra.Maybe (pjust, pmaybe, pnothing) +import Plutarch.Extra.TermCont (pmatchC) import Plutarch.Lift ( DerivePConstantViaNewtype (..), PConstantDecl, PUnsafeLiftDecl (..), ) -import Plutarch.Numeric.Additive (AdditiveSemigroup ((+))) -import PlutusLedgerApi.V1.Time (POSIXTime) +import PlutusLedgerApi.V1 (POSIXTime) import PlutusTx qualified -import Prelude hiding ((+)) +import Prelude -------------------------------------------------------------------------------- @@ -64,8 +65,22 @@ import Prelude hiding ((+)) newtype ProposalStartingTime = ProposalStartingTime { getProposalStartingTime :: POSIXTime } - deriving newtype (PlutusTx.ToData, PlutusTx.FromData, PlutusTx.UnsafeFromData) - deriving stock (Eq, Show, GHC.Generic) + deriving stock + ( -- | @since 0.1.0 + Eq + , -- | @since 0.1.0 + Show + , -- | @since 0.1.0 + Generic + ) + deriving newtype + ( -- | @since 0.1.0 + PlutusTx.ToData + , -- | @since 0.1.0 + PlutusTx.FromData + , -- | @since 0.1.0 + PlutusTx.UnsafeFromData + ) {- | Configuration of proposal timings. @@ -89,11 +104,10 @@ data ProposalTimingConfig = ProposalTimingConfig , -- | @since 0.1.0 Show , -- | @since 0.1.0 - GHC.Generic + Generic ) --- | @since 0.1.0 -PlutusTx.makeIsDataIndexed ''ProposalTimingConfig [('ProposalTimingConfig, 0)] +PlutusTx.makeIsDataIndexed 'ProposalTimingConfig [('ProposalTimingConfig, 0)] -- | Represents the maximum width of a 'PlutusLedgerApi.V1.Time.POSIXTimeRange'. newtype MaxTimeRangeWidth = MaxTimeRangeWidth {getMaxWidth :: POSIXTime} @@ -105,7 +119,7 @@ newtype MaxTimeRangeWidth = MaxTimeRangeWidth {getMaxWidth :: POSIXTime} , -- | @since 0.1.0 Ord , -- | @since 0.1.0 - GHC.Generic + Generic ) deriving newtype ( -- | @since 0.1.0 @@ -151,41 +165,41 @@ data PProposalTime (s :: S) = PProposalTime } deriving stock ( -- | @since 0.1.0 - GHC.Generic + Generic ) deriving anyclass ( -- | @since 0.1.0 - Generic - , -- | @since 0.1.0 PlutusType - , -- | @since 0.1.0 - HasDatatypeInfo , -- | @since 0.1.0 PEq ) +instance DerivePlutusType PProposalTime where + type DPTStrat _ = PlutusTypeScott + -- | Plutarch-level version of 'ProposalStartingTime'. newtype PProposalStartingTime (s :: S) = PProposalStartingTime (Term s PPOSIXTime) - deriving + deriving stock + ( -- | @since 0.1.0 + Generic + ) + deriving anyclass ( -- | @since 0.1.0 PlutusType , -- | @since 0.1.0 PIsData , -- | @since 0.1.0 PEq - , -- | @since 0.1.0 - POrd ) - via (DerivePNewtype PProposalStartingTime PPOSIXTime) + +instance DerivePlutusType PProposalStartingTime where + type DPTStrat _ = PlutusTypeNewtype -- | @since 0.1.0 instance PUnsafeLiftDecl PProposalStartingTime where type PLifted PProposalStartingTime = ProposalStartingTime -deriving via - PAsData (DerivePNewtype PProposalStartingTime PPOSIXTime) - instance - PTryFrom PData (PAsData PProposalStartingTime) +instance PTryFrom PData (PAsData PProposalStartingTime) -- | @since 0.1.0 deriving via @@ -210,18 +224,10 @@ newtype PProposalTimingConfig (s :: S) = PProposalTimingConfig ) } deriving stock - ( -- | @since 0.1.0 - GHC.Generic - ) - deriving anyclass ( -- | @since 0.1.0 Generic ) deriving anyclass - ( -- | @since 0.1.0 - PIsDataRepr - ) - deriving ( -- | @since 0.1.0 PlutusType , -- | @since 0.1.0 @@ -229,10 +235,12 @@ newtype PProposalTimingConfig (s :: S) = PProposalTimingConfig , -- | @since 0.1.0 PDataFields ) - via (PIsDataReprInstances PProposalTimingConfig) + +instance DerivePlutusType PProposalTimingConfig where + type DPTStrat _ = PlutusTypeData -- | @since 0.1.0 -deriving via PAsData (PIsDataReprInstances PProposalTimingConfig) instance PTryFrom PData (PAsData PProposalTimingConfig) +instance PTryFrom PData PProposalTimingConfig -- | @since 0.1.0 instance PUnsafeLiftDecl PProposalTimingConfig where @@ -247,20 +255,28 @@ deriving via -- | Plutarch-level version of 'MaxTimeRangeWidth'. newtype PMaxTimeRangeWidth (s :: S) = PMaxTimeRangeWidth (Term s PPOSIXTime) - deriving + deriving stock + ( -- | @since 0.2.0 + Generic + ) + deriving anyclass ( -- | @since 0.1.0 PlutusType , -- | @since 0.1.0 PIsData , -- | @since 0.1.0 PEq + , -- | @since 0.2.0 + PPartialOrd , -- | @since 0.1.0 POrd ) - via (DerivePNewtype PMaxTimeRangeWidth PPOSIXTime) + +instance DerivePlutusType PMaxTimeRangeWidth where + type DPTStrat _ = PlutusTypeNewtype -- | @since 0.1.0 -deriving via PAsData (DerivePNewtype PMaxTimeRangeWidth PPOSIXTime) instance PTryFrom PData (PAsData PMaxTimeRangeWidth) +instance PTryFrom PData (PAsData PMaxTimeRangeWidth) -- | @since 0.1.0 instance PUnsafeLiftDecl PMaxTimeRangeWidth where type PLifted PMaxTimeRangeWidth = MaxTimeRangeWidth @@ -273,29 +289,76 @@ deriving via -------------------------------------------------------------------------------- +{- | Return true if the timing configuration is valid. + + @since 0.2.0 +-} +pisProposalTimingConfigValid :: Term s (PProposalTimingConfig :--> PBool) +pisProposalTimingConfigValid = phoistAcyclic $ + plam $ \conf -> unTermCont $ do + confF <- pletAllC conf + + -- everything is greater or equal 0 + pure $ + ptraceIfFalse "ge 0" $ + foldr + ( \t -> + (#&&) + ( pconstant 0 + #<= pfromData t + ) + ) + (pconstant True) + [ confF.draftTime + , confF.votingTime + , confF.lockingTime + , confF.executingTime + ] + +{- | Return true if the maximum time width is greater than 0. + + @since 0.2.0 +-} +pisMaxTimeRangeWidthValid :: Term s (PMaxTimeRangeWidth :--> PBool) +pisMaxTimeRangeWidthValid = + phoistAcyclic $ + plam $ + ptraceIfFalse "greater than 0" + . (pconstant (MaxTimeRangeWidth 0) #<) + {- | Get the starting time of a proposal, from the 'PlutusLedgerApi.V1.txInfoValidPeriod' field. For every proposal, this is only meant to run once upon creation. Given time range should be tight enough, meaning that the width of the time range should be less than the maximum value. @since 0.1.0 -} -createProposalStartingTime :: forall (s :: S). Term s (PMaxTimeRangeWidth :--> PPOSIXTimeRange :--> PProposalStartingTime) +createProposalStartingTime :: + forall (s :: S). + Term + s + ( PMaxTimeRangeWidth + :--> PPOSIXTimeRange + :--> PMaybe PProposalStartingTime + ) createProposalStartingTime = phoistAcyclic $ - plam $ \(pto -> maxDuration) iv -> unTermCont $ do - currentTimeF <- pmatchC $ currentProposalTime # iv - - -- Use the middle of the current time range as the starting time. - let duration = currentTimeF.upperBound - currentTimeF.lowerBound - - startingTime = - pdiv - # (currentTimeF.lowerBound + currentTimeF.upperBound) - # 2 - - pguardC "createProposalStartingTime: given time range should be tight enough" $ - duration #<= maxDuration - - pure $ pcon $ PProposalStartingTime startingTime + plam $ \(pto -> maxDuration) iv -> + let ct = currentProposalTime # iv + + f :: Term _ (PProposalTime :--> PMaybe PProposalStartingTime) + f = plam $ + flip pmatch $ \(PProposalTime lb ub) -> + let duration = ub - lb + + startingTime = pdiv # (lb + ub) # 2 + in pif + (duration #<= maxDuration) + (pjust #$ pcon $ PProposalStartingTime startingTime) + ( ptrace + "createProposalStartingTime: given time range should be tight enough" + pnothing + ) + in -- TODO: PMonad when? + pmaybe # pnothing # f # ct {- | Get the current proposal time, from the 'PlutusLedgerApi.V1.txInfoValidPeriod' field. @@ -304,33 +367,30 @@ createProposalStartingTime = phoistAcyclic $ @since 0.1.0 -} -currentProposalTime :: forall (s :: S). Term s (PPOSIXTimeRange :--> PProposalTime) +currentProposalTime :: forall (s :: S). Term s (PPOSIXTimeRange :--> PMaybe PProposalTime) currentProposalTime = phoistAcyclic $ plam $ \iv -> unTermCont $ do PInterval iv' <- pmatchC iv - ivf <- tcont $ pletFields @'["from", "to"] iv' + ivf <- pletAllC iv' PLowerBound lb <- pmatchC ivf.from PUpperBound ub <- pmatchC ivf.to - lbf <- tcont $ pletFields @'["_0", "_1"] lb - ubf <- tcont $ pletFields @'["_0", "_1"] ub - pure $ - pcon $ - PProposalTime - { lowerBound = - pmatch - lbf._0 - ( \case - PFinite ((pfield @"_0" #) -> d) -> d - _ -> ptraceError "currentProposalTime: Can't get fully-bounded proposal time." - ) - , upperBound = - pmatch - ubf._0 - ( \case - PFinite ((pfield @"_0" #) -> d) -> d - _ -> ptraceError "currentProposalTime: Can't get fully-bounded proposal time." + + let getBound = phoistAcyclic $ + plam $ + flip pletAll $ \f -> + pif + f._1 + ( pmatch f._0 $ \case + PFinite (pfromData . (pfield @"_0" #) -> d) -> pjust # d + _ -> ptrace "currentProposalTime: time range should be bounded" pnothing ) - } + (ptrace "currentProposalTime: time range should be inclusive" pnothing) + + lowerBound = getBound # lb + upperBound = getBound # ub + + mkTime = phoistAcyclic $ plam $ pcon .* PProposalTime + pure $ pliftA2 # mkTime # lowerBound # upperBound {- | Check if 'PProposalTime' is within two 'PPOSIXTime'. Inclusive. diff --git a/agora/Agora/ScriptInfo.hs b/agora/Agora/ScriptInfo.hs deleted file mode 100644 index 09c7ac6a..00000000 --- a/agora/Agora/ScriptInfo.hs +++ /dev/null @@ -1,99 +0,0 @@ -{- | -Module : Agora.ScriptInfo -Maintainer : emi@haskell.fyi -Description: Exportable script bundles for off-chain consumption. - -Exportable script bundles for off-chain consumption. --} -module Agora.ScriptInfo ( - -- * Types - PolicyInfo (..), - ValidatorInfo (..), - - -- * Introduction functions - mkValidatorInfo, - mkPolicyInfo, -) where - -import Agora.Aeson.Orphans () -import Data.Aeson qualified as Aeson -import GHC.Generics qualified as GHC -import Plutarch.Api.V1 (PMintingPolicy, PValidator, mintingPolicySymbol, mkMintingPolicy, mkValidator, validatorHash) -import PlutusLedgerApi.V1 (MintingPolicy, Validator, ValidatorHash) -import PlutusLedgerApi.V1.Value (CurrencySymbol) - -{- | Bundle containing a 'Validator' and its hash. - - @since 0.1.0 --} -data ValidatorInfo = ValidatorInfo - { script :: Validator - -- ^ The validator script. - , hash :: ValidatorHash - -- ^ Hash of the validator. - } - deriving stock - ( -- | @since 0.1.0 - Show - , -- | @since 0.1.0 - Eq - , -- | @since 0.1.0 - GHC.Generic - ) - deriving anyclass - ( -- | @since 0.1.0 - Aeson.ToJSON - , -- | @since 0.1.0 - Aeson.FromJSON - ) - -{- | Create a 'ValidatorInfo' given a Plutarch term. - - @since 0.1.0 --} -mkValidatorInfo :: ClosedTerm PValidator -> ValidatorInfo -mkValidatorInfo term = - ValidatorInfo - { script = validator - , hash = validatorHash validator - } - where - validator = mkValidator term - -{- | Bundle containing a 'MintingPolicy' and its symbol. - - @since 0.1.0 --} -data PolicyInfo = PolicyInfo - { policy :: MintingPolicy - -- ^ The minting policy. - , currencySymbol :: CurrencySymbol - -- ^ The symbol given by the minting policy. - } - deriving stock - ( -- | @since 0.1.0 - Show - , -- | @since 0.1.0 - Eq - , -- | @since 0.1.0 - GHC.Generic - ) - deriving anyclass - ( -- | @since 0.1.0 - Aeson.ToJSON - , -- | @since 0.1.0 - Aeson.FromJSON - ) - -{- | Create a 'PolicyInfo' given a Plutarch term. - - @since 0.1.0 --} -mkPolicyInfo :: ClosedTerm PMintingPolicy -> PolicyInfo -mkPolicyInfo term = - PolicyInfo - { policy = policy - , currencySymbol = mintingPolicySymbol policy - } - where - policy = mkMintingPolicy term diff --git a/agora/Agora/Scripts.hs b/agora/Agora/Scripts.hs new file mode 100644 index 00000000..9a76167e --- /dev/null +++ b/agora/Agora/Scripts.hs @@ -0,0 +1,138 @@ +{- | Module : Agora.Scripts + Maintainer : connor@mlabs.city + Description: Precompiled core scripts and utilities + + Precompiled core scripts and utilities +-} +module Agora.Scripts ( + AgoraScripts (..), + governorSTSymbol, + governorSTAssetClass, + governorValidatorHash, + proposalSTSymbol, + proposalSTAssetClass, + proposalValidatoHash, + stakeSTSymbol, + stakeSTAssetClass, + stakeValidatorHash, + authorityTokenSymbol, + treasuryValidatorHash, +) where + +import Agora.Governor (GovernorDatum, GovernorRedeemer) +import Agora.Proposal (ProposalDatum, ProposalRedeemer) +import Agora.Stake (StakeDatum, StakeRedeemer) +import Agora.Treasury (TreasuryRedeemer) +import Agora.Utils (CompiledMintingPolicy (..), CompiledValidator (..), validatorHashToTokenName) +import Plutarch.Api.V1 (mintingPolicySymbol, validatorHash) +import PlutusLedgerApi.V1 (CurrencySymbol) +import PlutusLedgerApi.V1.Scripts (ValidatorHash) +import PlutusLedgerApi.V1.Value (AssetClass (..)) + +{- | Precompiled core scripts. + + Including: + + - Governor policy + - Governor validator + - Proposal policy + - Proposal validator + - Stake policy + - Stake validator + - Treasury validator + - Authority token policy + + @since 0.2.0 +-} +data AgoraScripts = AgoraScripts + { compiledGovernorPolicy :: CompiledMintingPolicy () + , compiledGovernorValidator :: CompiledValidator GovernorDatum GovernorRedeemer + , compiledStakePolicy :: CompiledMintingPolicy () + , compiledStakeValidator :: CompiledValidator StakeDatum StakeRedeemer + , compiledProposalPolicy :: CompiledMintingPolicy () + , compiledProposalValidator :: CompiledValidator ProposalDatum ProposalRedeemer + , compiledTreasuryValidator :: CompiledValidator () TreasuryRedeemer + , compiledAuthorityTokenPolicy :: CompiledMintingPolicy () + } + +{- | Get the currency symbol of the governor state token. + + @since 0.2.0 +-} +governorSTSymbol :: AgoraScripts -> CurrencySymbol +governorSTSymbol = mintingPolicySymbol . getCompiledMintingPolicy . compiledGovernorPolicy + +{- | Get the asset class of the governor state token. + + @since 0.2.0 +-} +governorSTAssetClass :: AgoraScripts -> AssetClass +governorSTAssetClass as = AssetClass (governorSTSymbol as, "") + +{- | Get the script hash of the governor validator. + + @since 0.2.0 +-} +governorValidatorHash :: AgoraScripts -> ValidatorHash +governorValidatorHash = validatorHash . getCompiledValidator . compiledGovernorValidator + +{- | Get the currency symbol of the propsoal state token. + + @since 0.2.0 +-} +proposalSTSymbol :: AgoraScripts -> CurrencySymbol +proposalSTSymbol as = mintingPolicySymbol $ getCompiledMintingPolicy as.compiledProposalPolicy + +{- | Get the asset class of the governor state token. + + @since 0.2.0 +-} +proposalSTAssetClass :: AgoraScripts -> AssetClass +proposalSTAssetClass as = AssetClass (proposalSTSymbol as, "") + +{- | Get the script hash of the proposal validator. + + @since 0.2.0 +-} +proposalValidatoHash :: AgoraScripts -> ValidatorHash +proposalValidatoHash = validatorHash . getCompiledValidator . compiledProposalValidator + +{- | Get the script hash of the governor validator. + + @since 0.2.0 +-} +stakeSTSymbol :: AgoraScripts -> CurrencySymbol +stakeSTSymbol = mintingPolicySymbol . getCompiledMintingPolicy . compiledStakePolicy + +{- | Get the asset class of the stake state token. + + Note that this token is tagged with the hash of the stake validator. + See 'Agora.Stake.Script.stakePolicy'. + + @since 0.2.0 +-} +stakeSTAssetClass :: AgoraScripts -> AssetClass +stakeSTAssetClass as = + let tn = validatorHashToTokenName $ stakeValidatorHash as + in AssetClass (stakeSTSymbol as, tn) + +{- | Get the script hash of the stake validator. + + @since 0.2.0 +-} +stakeValidatorHash :: AgoraScripts -> ValidatorHash +stakeValidatorHash = validatorHash . getCompiledValidator . compiledStakeValidator + +{- | Get the currency symbol of the authority token. + + @since 0.2.0 +-} +authorityTokenSymbol :: AgoraScripts -> CurrencySymbol +authorityTokenSymbol = mintingPolicySymbol . getCompiledMintingPolicy . compiledAuthorityTokenPolicy + +{- | Get the script hash of the treasury validator. + + @since 0.2.0 +-} +treasuryValidatorHash :: AgoraScripts -> ValidatorHash +treasuryValidatorHash = validatorHash . getCompiledValidator . compiledTreasuryValidator diff --git a/agora/Agora/Stake.hs b/agora/Agora/Stake.hs index ab41ab4a..423f3479 100644 --- a/agora/Agora/Stake.hs +++ b/agora/Agora/Stake.hs @@ -11,71 +11,54 @@ module Agora.Stake ( -- * Haskell-land StakeDatum (..), StakeRedeemer (..), - Stake (..), ProposalLock (..), -- * Plutarch-land PStakeDatum (..), PStakeRedeemer (..), PProposalLock (..), - PStakeUsage (..), + PStakeRole (..), -- * Utility functions - stakeLocked, - findStakeOwnedBy, - pgetStakeUsage, + pstakeLocked, + pnumCreatedProposals, + pextractVoteOption, + pgetStakeRole, + pisVoter, + pisCreator, + pisPureCreator, + pisIrrelevant, ) where -import Agora.Plutarch.Orphans () import Agora.Proposal (PProposalId, PResultTag, ProposalId (..), ResultTag (..)) import Agora.SafeMoney (GTTag) import Data.Tagged (Tagged (..)) -import GHC.Generics qualified as GHC -import Generics.SOP (Generic, HasDatatypeInfo, I (I)) +import Generics.SOP qualified as SOP import Plutarch.Api.V1 ( - PDatum, - PDatumHash, - PMaybeData (PDJust, PDNothing), + PMaybeData, PPubKeyHash, - PTuple, - PTxInInfo (PTxInInfo), - PTxOut (PTxOut), ) -import Plutarch.Api.V1.AssetClass (PAssetClass, passetClassValueOf) -import Plutarch.Api.V1.ScriptContext (ptryFindDatum) import Plutarch.DataRepr ( DerivePConstantViaData (..), - PDataFields, - PIsDataReprInstances (PIsDataReprInstances), ) -import Plutarch.Extra.List (pmapMaybe, pnotNull) -import Plutarch.Extra.TermCont (pletC, pletFieldsC, pmatchC) -import Plutarch.Internal (punsafeCoerce) +import Plutarch.Extra.Field (pletAll) +import Plutarch.Extra.IsData ( + DerivePConstantViaDataList (..), + ProductIsData (ProductIsData), + ) +import Plutarch.Extra.List (pnotNull) +import Plutarch.Extra.Sum (PSum (..)) +import Plutarch.Extra.Traversable (pfoldMap) import Plutarch.Lift (PConstantDecl, PUnsafeLiftDecl (..)) import Plutarch.SafeMoney (PDiscrete) +import Plutarch.Show (PShow (..)) import PlutusLedgerApi.V1 (PubKeyHash) -import PlutusLedgerApi.V1.Value (AssetClass) import PlutusTx qualified import Prelude hiding (Num (..)) -------------------------------------------------------------------------------- -{- | Parameters for creating Stake scripts. - - @since 0.1.0 --} -data Stake = Stake - { gtClassRef :: Tagged GTTag AssetClass - -- ^ Used when inlining the AssetClass of a 'PDiscrete' in the script code. - , proposalSTClass :: AssetClass - } - deriving stock - ( -- | @since 0.1.0 - GHC.Generic - ) - -{- | A lock placed on a Stake datum in order to prevent - depositing and withdrawing when votes are in place. +{- | Locks that are stored in the stake datums for various purposes. NOTE: Due to retracting votes always being possible, this lock will only lock with contention on the proposal. @@ -102,22 +85,41 @@ data Stake = Stake @since 0.1.0 -} -data ProposalLock = ProposalLock - { vote :: ResultTag - -- ^ What was voted on. This allows retracting votes to - -- undo their vote. - , proposalId :: ProposalId - -- ^ Identifies the proposal. See 'ProposalId' for further - -- comments on its significance. - } +data ProposalLock + = -- | The stake was used to create a proposal. + -- + -- This kind of lock is placed upon the creation of a proposal, in order + -- to limit creation of proposals per stake. + -- + -- See also: https://github.com/Liqwid-Labs/agora/issues/68 + -- + -- @since 0.2.0 + Created + ProposalId + -- ^ The identifier of the proposal. + | -- | The stake was used to vote on a proposal. + -- + -- This kind of lock is placed while voting on a proposal, in order to + -- prevent depositing and withdrawing when votes are in place. + -- + -- @since 0.2.0 + Voted + ProposalId + -- ^ The identifier of the proposal. + ResultTag + -- ^ The option which was voted on. This allows votes to be retracted. deriving stock ( -- | @since 0.1.0 Show , -- | @since 0.1.0 - GHC.Generic + Generic ) -PlutusTx.makeIsDataIndexed ''ProposalLock [('ProposalLock, 0)] +PlutusTx.makeIsDataIndexed + ''ProposalLock + [ ('Created, 0) + , ('Voted, 1) + ] {- | Haskell-level redeemer for Stake scripts. @@ -135,16 +137,26 @@ data StakeRedeemer -- This needs to be done in sync with casting a vote, otherwise -- it's possible for a lock to be permanently placed on the stake, -- and then the funds are lost. - PermitVote ProposalLock + PermitVote | -- | Retract a vote, removing it from the 'lockedBy' field. See 'ProposalLock'. -- This action checks for permission of the 'Agora.Proposal.Proposal'. Finished proposals are -- always allowed to have votes retracted and won't affect the Proposal datum, -- allowing 'Stake's to be unlocked. - RetractVotes [ProposalLock] + RetractVotes | -- | The owner can consume stake if nothing is changed about it. -- If the proposal token moves, this is equivalent to the owner consuming it. WitnessStake - deriving stock (Show, GHC.Generic) + | -- | The owner can delegate the stake to another user, allowing the + -- delegate to vote on prooposals with the stake. + DelegateTo PubKeyHash + | -- | Revoke the existing delegation. + ClearDelegate + deriving stock + ( -- | @since 0.1.0 + Show + , -- | @since 0.1.0 + Generic + ) PlutusTx.makeIsDataIndexed ''StakeRedeemer @@ -153,6 +165,8 @@ PlutusTx.makeIsDataIndexed , ('PermitVote, 2) , ('RetractVotes, 3) , ('WitnessStake, 4) + , ('DelegateTo, 5) + , ('ClearDelegate, 6) ] {- | Haskell-level datum for Stake scripts. @@ -162,19 +176,35 @@ PlutusTx.makeIsDataIndexed data StakeDatum = StakeDatum { stakedAmount :: Tagged GTTag Integer -- ^ Tracks the amount of governance token staked in the datum. - -- This also acts as the voting weight for 'Agora.Proposal.Proposal's. + -- This also acts as the voting weight for 'Agora.Proposal.Proposal's. , owner :: PubKeyHash -- ^ The hash of the public key this stake belongs to. -- -- TODO Support for MultiSig/Scripts is tracked here: -- https://github.com/Liqwid-Labs/agora/issues/45 + , delegatedTo :: Maybe PubKeyHash + -- ^ To whom this stake has been delegated. , lockedBy :: [ProposalLock] -- ^ The current proposals locking this stake. This field must be empty - -- for the stake to be usable for deposits and withdrawals. + -- for the stake to be usable for deposits and withdrawals. } - deriving stock (Show, GHC.Generic) - -PlutusTx.makeIsDataIndexed ''StakeDatum [('StakeDatum, 0)] + deriving stock + ( -- | @since 0.1.0 + Show + , -- | @since 0.1.0 + Generic + ) + deriving anyclass + ( -- | @since 0.1.0 + SOP.Generic + ) + deriving + ( -- | @since 0.1.0 + PlutusTx.ToData + , -- | @since 0.1.0 + PlutusTx.FromData + ) + via (ProductIsData StakeDatum) -------------------------------------------------------------------------------- @@ -189,42 +219,39 @@ newtype PStakeDatum (s :: S) = PStakeDatum ( PDataRecord '[ "stakedAmount" ':= PDiscrete GTTag , "owner" ':= PPubKeyHash + , "delegatedTo" ':= PMaybeData (PAsData PPubKeyHash) , "lockedBy" ':= PBuiltinList (PAsData PProposalLock) ] ) } deriving stock - ( -- | @since 0.1.0 - GHC.Generic - ) - deriving anyclass ( -- | @since 0.1.0 Generic ) deriving anyclass - ( -- | @since 0.1.0 - PIsDataRepr - ) - deriving ( -- | @since 0.1.0 PlutusType , -- | @since 0.1.0 PIsData - , -- | @since 0.1.0 - PDataFields , -- | @since 0.1.0 PEq ) - via (PIsDataReprInstances PStakeDatum) + +instance DerivePlutusType PStakeDatum where + type DPTStrat _ = PlutusTypeNewtype -- | @since 0.1.0 -instance Plutarch.Lift.PUnsafeLiftDecl PStakeDatum where type PLifted PStakeDatum = StakeDatum +instance Plutarch.Lift.PUnsafeLiftDecl PStakeDatum where + type PLifted PStakeDatum = StakeDatum -- | @since 0.1.0 -deriving via (DerivePConstantViaData StakeDatum PStakeDatum) instance (Plutarch.Lift.PConstantDecl StakeDatum) +deriving via + (DerivePConstantViaDataList StakeDatum PStakeDatum) + instance + (Plutarch.Lift.PConstantDecl StakeDatum) -- | @since 0.1.0 -deriving via PAsData (PIsDataReprInstances PStakeDatum) instance PTryFrom PData (PAsData PStakeDatum) +instance PTryFrom PData (PAsData PStakeDatum) {- | Plutarch-level redeemer for Stake scripts. @@ -235,208 +262,257 @@ data PStakeRedeemer (s :: S) PDepositWithdraw (Term s (PDataRecord '["delta" ':= PDiscrete GTTag])) | -- | Destroy a stake, retrieving its LQ, the minimum ADA and any other assets. PDestroy (Term s (PDataRecord '[])) - | PPermitVote (Term s (PDataRecord '["lock" ':= PProposalLock])) - | PRetractVotes (Term s (PDataRecord '["locks" ':= PBuiltinList (PAsData PProposalLock)])) + | PPermitVote (Term s (PDataRecord '[])) + | PRetractVotes (Term s (PDataRecord '[])) | PWitnessStake (Term s (PDataRecord '[])) + | PDelegateTo (Term s (PDataRecord '["pkh" ':= PPubKeyHash])) + | PClearDelegate (Term s (PDataRecord '[])) deriving stock - ( -- | @since 0.1.0 - GHC.Generic - ) - deriving anyclass ( -- | @since 0.1.0 Generic ) deriving anyclass ( -- | @since 0.1.0 - PIsDataRepr - ) - deriving - ( -- | @since 0.1.0 + SOP.Generic + , -- | @since 0.1.0 PlutusType , -- | @since 0.1.0 PIsData ) - via PIsDataReprInstances PStakeRedeemer +instance DerivePlutusType PStakeRedeemer where + type DPTStrat _ = PlutusTypeData + +-- | @since 0.1.0 +instance PTryFrom PData PStakeRedeemer + +-- | @since 0.1.0 +instance Plutarch.Lift.PUnsafeLiftDecl PStakeRedeemer where + type PLifted PStakeRedeemer = StakeRedeemer + +-- | @since 0.1.0 deriving via - PAsData (PIsDataReprInstances PStakeRedeemer) + (DerivePConstantViaData StakeRedeemer PStakeRedeemer) instance - PTryFrom PData (PAsData PStakeRedeemer) - -instance Plutarch.Lift.PUnsafeLiftDecl PStakeRedeemer where type PLifted PStakeRedeemer = StakeRedeemer -deriving via (DerivePConstantViaData StakeRedeemer PStakeRedeemer) instance (Plutarch.Lift.PConstantDecl StakeRedeemer) + (Plutarch.Lift.PConstantDecl StakeRedeemer) {- | Plutarch-level version of 'ProposalLock'. - @since 0.1.0 + @since 0.2.0 -} -newtype PProposalLock (s :: S) = PProposalLock - { getProposalLock :: - Term - s - ( PDataRecord - '[ "vote" ':= PResultTag - , "proposalTag" ':= PProposalId - ] - ) - } - deriving stock (GHC.Generic) - deriving anyclass (Generic) - deriving anyclass (PIsDataRepr) - deriving - (PlutusType, PIsData, PDataFields, PEq) - via (PIsDataReprInstances PProposalLock) +data PProposalLock (s :: S) + = PCreated + ( Term + s + ( PDataRecord + '["created" ':= PProposalId] + ) + ) + | PVoted + ( Term + s + ( PDataRecord + '[ "votedOn" ':= PProposalId + , "votedFor" ':= PResultTag + ] + ) + ) + deriving stock + ( -- | @since 0.1.0 + Generic + ) + deriving anyclass + ( -- | @since 0.1.0 + PlutusType + , -- | @since 0.1.0 + PIsData + , -- | @since 0.1.0 + PEq + ) + +instance DerivePlutusType PProposalLock where + type DPTStrat _ = PlutusTypeData + +-- | @since 0.1.0 +instance PTryFrom PData PProposalLock + +-- | @since 0.2.0 +instance PTryFrom PData (PAsData PProposalLock) + +-- | @since 0.1.0 +instance Plutarch.Lift.PUnsafeLiftDecl PProposalLock where + type PLifted PProposalLock = ProposalLock +-- | @since 0.1.0 deriving via - PAsData (PIsDataReprInstances PProposalLock) + (DerivePConstantViaData ProposalLock PProposalLock) instance - PTryFrom PData (PAsData PProposalLock) + (Plutarch.Lift.PConstantDecl ProposalLock) -instance Plutarch.Lift.PUnsafeLiftDecl PProposalLock where type PLifted PProposalLock = ProposalLock -deriving via (DerivePConstantViaData ProposalLock PProposalLock) instance (Plutarch.Lift.PConstantDecl ProposalLock) +-- | @since 0.2.0 +instance PShow PProposalLock where + pshow' :: Bool -> Term s PProposalLock -> Term s PString + pshow' True x = "(" <> pshow' False x <> ")" + pshow' False lock = pmatch lock $ \case + PCreated ((pfield @"created" #) -> pid) -> "PCreated " <> pshow' True pid + PVoted x -> pletFields @'["votedOn", "votedFor"] x $ \xF -> + "PVoted " <> pshow' True xF.votedOn <> " " <> pshow' True xF.votedFor -------------------------------------------------------------------------------- {- | Check whether a Stake is locked. If it is locked, various actions are unavailable. - @since 0.1.0 + @since 0.2.0 -} -stakeLocked :: forall (s :: S). Term s (PStakeDatum :--> PBool) -stakeLocked = phoistAcyclic $ +pstakeLocked :: forall (s :: S). Term s (PStakeDatum :--> PBool) +pstakeLocked = phoistAcyclic $ plam $ \stakeDatum -> - let locks :: Term _ (PBuiltinList (PAsData PProposalLock)) - locks = pfield @"lockedBy" # stakeDatum - in pnotNull # locks + pnotNull #$ pfield @"lockedBy" @(PBuiltinList _) # pto stakeDatum -{- | Find a stake owned by a particular PK. +{- | Get the number of *alive* proposals that were created by the given stake. - @since 0.1.0 + @since 0.2.0 -} -findStakeOwnedBy :: - Term - s - ( PAssetClass - :--> PPubKeyHash - :--> PBuiltinList (PAsData (PTuple PDatumHash PDatum)) - :--> PBuiltinList (PAsData PTxInInfo) - :--> PMaybe (PAsData PStakeDatum) - ) -findStakeOwnedBy = phoistAcyclic $ - plam $ \ac pk datums inputs -> - pmatch (pfind # (isInputStakeOwnedBy # ac # pk # datums) # inputs) $ \case - PNothing -> pcon PNothing - PJust (pfromData -> v) -> unTermCont $ do - let txOut = pfield @"resolved" # pto v - txOutF <- tcont $ pletFields @'["datumHash"] $ txOut - pure $ - pmatch txOutF.datumHash $ \case - PDNothing _ -> pcon PNothing - PDJust ((pfield @"_0" #) -> dh) -> - ptryFindDatum @(PAsData PStakeDatum) # dh # datums - -{- | Check if a StakeDatum is owned by a particular public key. - - @since 0.1.0 --} -stakeDatumOwnedBy :: Term _ (PPubKeyHash :--> PStakeDatum :--> PBool) -stakeDatumOwnedBy = +pnumCreatedProposals :: Term s (PBuiltinList (PAsData PProposalLock) :--> PInteger) +pnumCreatedProposals = phoistAcyclic $ - plam $ \pk stakeDatum -> - pletFields @'["owner"] (pto stakeDatum) $ \stakeDatumF -> - stakeDatumF.owner #== pdata pk - -{- | Does the input have a `Stake` owned by a particular PK? - - @since 0.1.0 --} -isInputStakeOwnedBy :: - Term - _ - ( PAssetClass :--> PPubKeyHash - :--> PBuiltinList (PAsData (PTuple PDatumHash PDatum)) - :--> PAsData PTxInInfo - :--> PBool - ) -isInputStakeOwnedBy = - plam $ \ac ss datums txInInfo' -> unTermCont $ do - PTxInInfo ((pfield @"resolved" #) -> txOut) <- pmatchC $ pfromData txInInfo' - PTxOut txOut' <- pmatchC txOut - txOutF <- pletFieldsC @'["value", "datumHash"] txOut' - outStakeST <- pletC $ passetClassValueOf # txOutF.value # ac - pure $ - pmatch txOutF.datumHash $ \case - PDNothing _ -> pcon PFalse - PDJust ((pfield @"_0" #) -> datumHash) -> - pif - (outStakeST #== 1) - ( pmatch (ptryFindDatum @(PAsData PStakeDatum) # datumHash # datums) $ \case - PNothing -> pcon PFalse - PJust v -> stakeDatumOwnedBy # ss # pfromData (punsafeCoerce v) + plam $ \l -> + pto $ + pfoldMap + # plam + ( \(pfromData -> lock) -> pmatch lock $ \case + PCreated _ -> pcon $ PSum 1 + _ -> mempty ) - (pcon PFalse) + # l -{- | Represent the usage of a stake on a particular proposal. - A stake can be used to either create or vote on a proposal. +{- | The role of a stake for a particular proposal. Scott-encoded. - @since 0.1.0 + @since 0.2.0 -} -data PStakeUsage (s :: S) - = PVotedFor (Term s PResultTag) - | PCreated - | PDidNothing +data PStakeRole (s :: S) + = -- | The stake was used to vote on the proposal. + PVoter + (Term s PResultTag) + -- ^ The option which was voted for. + | -- | The stake was used to create the proposal. + PCreator + | -- | The stake was used to both create and vote on the proposal. + PBoth + (Term s PResultTag) + -- ^ The option which was voted for. + | -- | The stake has nothing to do with the given proposal. + PIrrelevant deriving stock - ( -- | @since 0.1.0 - GHC.Generic + ( -- | @since 0.2.0 + Generic ) deriving anyclass - ( -- | @since 0.1.0 - Generic - , -- | @since 0.1.0 + ( -- | @since 0.2.0 PlutusType - , -- | @since 0.1.0 - HasDatatypeInfo - , -- | @since 0.1.0 + , -- | @since 0.2.0 PEq ) -{- | / O(n) /.Return the usage of a stake on a particular proposal, - given the 'lockedBy' field of a stake and the target proposal. +instance DerivePlutusType PStakeRole where + type DPTStrat _ = PlutusTypeScott - @since 0.1.0 +{- | Retutn true if the stake was used to voted on the proposal. + + @since 0.2.0 -} -pgetStakeUsage :: - Term - _ - ( PBuiltinList (PAsData PProposalLock) - :--> PProposalId - :--> PStakeUsage - ) -pgetStakeUsage = phoistAcyclic $ - plam $ \locks pid -> - let -- All locks from the given proposal. - filteredLocks = - pmapMaybe - # plam - ( \lock'@(pfromData -> lock) -> unTermCont $ do - lockF <- pletFieldsC @'["proposalTag"] lock - - pure $ +pisVoter :: Term s (PStakeRole :--> PBool) +pisVoter = phoistAcyclic $ + plam $ \sr -> pmatch sr $ \case + PVoter _ -> pconstant True + PBoth _ -> pconstant True + _ -> pconstant False + +{- | Retutn true if the stake was used to create the proposal. + + @since 0.2.0 +-} +pisCreator :: Term s (PStakeRole :--> PBool) +pisCreator = phoistAcyclic $ + plam $ \sr -> pmatch sr $ \case + PCreator -> pconstant True + PBoth _ -> pconstant True + _ -> pconstant False + +{- | Retutn true if the stake was used to create the proposal, but not vote on + the proposal. + + @since 0.2.0 +-} +pisPureCreator :: Term s (PStakeRole :--> PBool) +pisPureCreator = phoistAcyclic $ + plam $ \sr -> pmatch sr $ \case + PCreator -> pconstant True + _ -> pconstant False + +{- | Return true if the stake isn't related to the proposal. + + @since 0.2.0 +-} +pisIrrelevant :: Term s (PStakeRole :--> PBool) +pisIrrelevant = phoistAcyclic $ + plam $ \sr -> pmatch sr $ \case + PIrrelevant -> pconstant True + _ -> pconstant False + +{- | Get the role of a stake for the proposal specified by the poroposal id, + given the 'StakeDatum.lockedBy' field of the stake. + + Note that the list of locks is cosidered valid only if it contains at most + two locks from the given proposal: one voter lock and one creator lock. + + @since 0.2.0 +-} +pgetStakeRole :: Term s (PProposalId :--> PBuiltinList (PAsData PProposalLock) :--> PStakeRole) +pgetStakeRole = phoistAcyclic $ + plam $ \pid locks -> + pfoldl + # plam + ( \role (pfromData -> lock) -> + let thisRole = pmatch lock $ \case + PCreated ((pfield @"created" #) -> pid') -> pif - (lockF.proposalTag #== pid) - (pcon $ PJust lock') - (pcon PNothing) - ) - # locks - - lockCount' = plength # filteredLocks - in plet lockCount' $ \lockCount -> - pif (lockCount #== 0) (pcon PDidNothing) $ - pif - (lockCount #== 1) - ( pcon $ - PVotedFor $ - pfromData $ - pfield @"vote" #$ phead # filteredLocks - ) - -- Note: see the implementation of the governor. - (pcon PCreated) + (pid' #== pid) + (pcon PCreator) + (pcon PIrrelevant) + PVoted lock' -> pletAll lock' $ \lockF -> + pif + (lockF.votedOn #== pid) + (pcon $ PVoter lockF.votedFor) + (pcon PIrrelevant) + in pcombineStakeRole # thisRole # role + ) + # pcon PIrrelevant + # locks + where + pcombineStakeRole :: Term s (PStakeRole :--> PStakeRole :--> PStakeRole) + pcombineStakeRole = phoistAcyclic $ + plam $ \x y -> + let cannotCombine = ptraceError "duplicate roles" + in pmatch x $ \case + PVoter r -> pmatch y $ \case + PCreator -> pcon $ PBoth r + PIrrelevant -> x + _ -> cannotCombine + PCreator -> pmatch y $ \case + PVoter r -> pcon $ PBoth r + PIrrelevant -> x + _ -> cannotCombine + PBoth _ -> cannotCombine + PIrrelevant -> y + +{- | Get the outcome that was voted for. + + @since 0.2.0 +-} +pextractVoteOption :: Term s (PStakeRole :--> PResultTag) +pextractVoteOption = phoistAcyclic $ + plam $ \sr -> pmatch sr $ \case + PVoter r -> r + PBoth r -> r + _ -> ptraceError "not voter" diff --git a/agora/Agora/Stake/Scripts.hs b/agora/Agora/Stake/Scripts.hs index be546f85..f76deb44 100644 --- a/agora/Agora/Stake/Scripts.hs +++ b/agora/Agora/Stake/Scripts.hs @@ -8,36 +8,44 @@ Plutus Scripts for Stakes. module Agora.Stake.Scripts (stakePolicy, stakeValidator) where import Agora.SafeMoney (GTTag) -import Agora.Stake +import Agora.Scripts (AgoraScripts, proposalSTAssetClass, stakeSTSymbol) +import Agora.Stake ( + PStakeDatum (PStakeDatum), + PStakeRedeemer (..), + StakeRedeemer (WitnessStake), + pstakeLocked, + ) import Agora.Utils ( - mustBePJust, mustFindDatum', - pvalidatorHashToTokenName, ) +import Data.Function (on) import Data.Tagged (Tagged (..), untag) import Plutarch.Api.V1 ( AmountGuarantees (Positive), PCredential (PPubKeyCredential, PScriptCredential), + PDatumHash, PMintingPolicy, PScriptPurpose (PMinting, PSpending), PTokenName, PTxInfo, + PTxOut, PValidator, PValue, - mintingPolicySymbol, - mkMintingPolicy, ) import Plutarch.Api.V1.AssetClass (passetClass, passetClassValueOf, pvalueOf) -import Plutarch.Api.V1.ScriptContext (pfindTxInByTxOutRef, pisTokenSpent, ptxSignedBy, pvalueSpent) +import Plutarch.Api.V1.ScriptContext (pfindTxInByTxOutRef, ptxSignedBy, pvalueSpent) import "liqwid-plutarch-extra" Plutarch.Api.V1.Value (pgeqByClass', pgeqBySymbol, psymbolValueOf) +import Plutarch.Extra.Field (pletAllC) +import Plutarch.Extra.List (pmapMaybe, pmsortBy) +import Plutarch.Extra.Maybe (passertPJust, pdjust, pdnothing, pfromDJust, pmaybeData) import Plutarch.Extra.Record (mkRecordConstr, (.&), (.=)) -import Plutarch.Extra.TermCont (pguardC, pletC, pmatchC, ptryFromC) -import Plutarch.Internal (punsafeCoerce) +import Plutarch.Extra.TermCont (pguardC, pletC, pletFieldsC, pmatchC, ptryFromC) import Plutarch.Numeric.Additive (AdditiveMonoid (zero), AdditiveSemigroup ((+))) import Plutarch.SafeMoney ( pdiscreteValue', pvalueDiscrete', ) +import Plutarch.Unsafe (punsafeCoerce) import PlutusLedgerApi.V1.Value (AssetClass (AssetClass)) import Prelude hiding (Num (..)) @@ -66,11 +74,11 @@ stakePolicy :: ClosedTerm PMintingPolicy stakePolicy gtClassRef = plam $ \_redeemer ctx' -> unTermCont $ do - ctx <- tcont $ pletFields @'["txInfo", "purpose"] ctx' + ctx <- pletFieldsC @'["txInfo", "purpose"] ctx' txInfo <- pletC $ ctx.txInfo let _a :: Term _ PTxInfo _a = txInfo - txInfoF <- tcont $ pletFields @'["mint", "inputs", "outputs", "signatories", "datums"] txInfo + txInfoF <- pletFieldsC @'["mint", "inputs", "outputs", "signatories", "datums"] txInfo PMinting ownSymbol' <- pmatchC $ pfromData ctx.purpose ownSymbol <- pletC $ pfield @"_0" # ownSymbol' @@ -88,12 +96,16 @@ stakePolicy gtClassRef = pany # plam ( \((pfield @"resolved" #) -> txOut) -> unTermCont $ do - txOutF <- tcont $ pletFields @'["value", "datumHash"] txOut + txOutF <- pletFieldsC @'["value", "datumHash"] txOut pure $ pif (psymbolValueOf # ownSymbol # txOutF.value #== 1) - ( let datum = mustFindDatum' @PStakeDatum # txOutF.datumHash # txInfoF.datums - in pnot # (stakeLocked # datum) + ( let datum = + pfromData $ + mustFindDatum' @(PAsData PStakeDatum) + # txOutF.datumHash + # txInfoF.datums + in pnot # (pstakeLocked # datum) ) (pconstant False) ) @@ -111,30 +123,30 @@ stakePolicy gtClassRef = pguardC "A UTXO must exist with the correct output" $ unTermCont $ do let scriptOutputWithStakeST = - mustBePJust + passertPJust # "Output to script not found" #$ pfind # plam ( \output -> unTermCont $ do - outputF <- tcont $ pletFields @'["value", "address"] output + outputF <- pletFieldsC @'["value", "address"] output pure $ pmatch (pfromData $ pfield @"credential" # outputF.address) $ \case -- Should pay to a script address PPubKeyCredential _ -> pcon PFalse PScriptCredential ((pfield @"_0" #) -> validatorHash) -> let tn :: Term _ PTokenName - tn = pvalidatorHashToTokenName validatorHash + tn = punsafeCoerce $ pfromData validatorHash in pvalueOf # outputF.value # ownSymbol # tn #== 1 ) # pfromData txInfoF.outputs outputF <- - tcont $ - pletFields @'["value", "address", "datumHash"] scriptOutputWithStakeST + pletFieldsC @'["value", "address", "datumHash"] scriptOutputWithStakeST datumF <- - tcont $ - pletFields @'["owner", "stakedAmount"] $ - mustFindDatum' @PStakeDatum # outputF.datumHash # txInfoF.datums + pletFieldsC @'["owner", "stakedAmount"] $ + pto $ + pfromData $ + mustFindDatum' @(PAsData PStakeDatum) # outputF.datumHash # txInfoF.datums let hasExpectedStake = ptraceIfFalse "Stake ouput has expected amount of stake token" $ @@ -205,41 +217,58 @@ stakePolicy gtClassRef = @since 0.1.0 -} -stakeValidator :: Stake -> ClosedTerm PValidator -stakeValidator stake = +stakeValidator :: + -- | Lazy precompiled scripts. + AgoraScripts -> + -- | See 'Agora.Governor.Governor.gtClassRef'. + Tagged GTTag AssetClass -> + ClosedTerm PValidator +stakeValidator as gtClassRef = plam $ \datum redeemer ctx' -> unTermCont $ do - ctx <- tcont $ pletFields @'["txInfo", "purpose"] ctx' + ctx <- pletFieldsC @'["txInfo", "purpose"] ctx' txInfo <- pletC $ pfromData ctx.txInfo - txInfoF <- tcont $ pletFields @'["mint", "inputs", "outputs", "signatories", "datums"] txInfo + txInfoF <- + pletFieldsC + @'[ "mint" + , "inputs" + , "outputs" + , "signatories" + , "datums" + ] + txInfo - (pfromData -> stakeRedeemer, _) <- ptryFromC redeemer + stakeRedeemer <- fst <$> ptryFromC redeemer - -- TODO: Use PTryFrom - let stakeDatum' :: Term _ PStakeDatum - stakeDatum' = pfromData $ punsafeCoerce datum - stakeDatum <- tcont $ pletFields @'["owner", "stakedAmount", "lockedBy"] stakeDatum' + stakeDatum' <- pfromData . fst <$> ptryFromC datum + stakeDatum <- pletAllC $ pto stakeDatum' PSpending txOutRef <- pmatchC $ pfromData ctx.purpose - PJust txInInfo <- pmatchC $ pfindTxInByTxOutRef # (pfield @"_0" # txOutRef) # txInfoF.inputs - ownAddress <- pletC $ pfield @"address" #$ pfield @"resolved" # txInInfo - let continuingValue :: Term _ (PValue _ _) - continuingValue = pfield @"value" #$ pfield @"resolved" # txInInfo + PJust ((pfield @"resolved" #) -> resolved) <- + pmatchC $ + pfindTxInByTxOutRef + # (pfield @"_0" # txOutRef) + # txInfoF.inputs + resolvedF <- pletFieldsC @'["address", "value", "datumHash"] resolved -- Whether the owner signs this transaction or not. - ownerSignsTransaction <- pletC $ ptxSignedBy # txInfoF.signatories # stakeDatum.owner + signedBy <- pletC $ ptxSignedBy # txInfoF.signatories + + ownerSignsTransaction <- pletC $ signedBy # stakeDatum.owner - stCurrencySymbol <- pletC $ pconstant $ mintingPolicySymbol $ mkMintingPolicy (stakePolicy stake.gtClassRef) + delegateSignsTransaction <- + pletC $ + pmaybeData # pconstant False + # signedBy + # stakeDatum.delegatedTo + + stCurrencySymbol <- pletC $ pconstant $ stakeSTSymbol as mintedST <- pletC $ psymbolValueOf # stCurrencySymbol # txInfoF.mint valueSpent <- pletC $ pvalueSpent # txInfoF.inputs spentST <- pletC $ psymbolValueOf # stCurrencySymbol #$ valueSpent - let AssetClass (propCs, propTn) = stake.proposalSTClass - proposalSTClass = passetClass # pconstant propCs # pconstant propTn - spentProposalST <- pletC $ passetClassValueOf # valueSpent # proposalSTClass - -- Is the stake currently locked? - stakeIsLocked <- pletC $ stakeLocked # stakeDatum' + stakeIsLocked <- pletC $ pstakeLocked # stakeDatum' pure $ pmatch stakeRedeemer $ \case @@ -255,196 +284,258 @@ stakeValidator stake = pguardC "Owner signs this transaction" ownerSignsTransaction pure $ popaque (pconstant ()) - -------------------------------------------------------------------------- + ------------------------------------------------------------------------ -- Handle redeemers that require own stake output. + _ -> unTermCont $ do - -- Filter out own output with own address and PST. - ownOutput <- + let AssetClass (propCs, propTn) = proposalSTAssetClass as + proposalSTClass = passetClass # pconstant propCs # pconstant propTn + spentProposalST = passetClassValueOf # valueSpent # proposalSTClass + + proposalTokenMoved <- pletC $ 1 #<= spentProposalST + + -- Filter out own outputs using own address and ST. + ownOutputs <- pletC $ - mustBePJust # "Own output should be present" #$ pfind + pfilter # plam - ( \input -> unTermCont $ do - inputF <- tcont $ pletFields @'["address", "value"] input + ( \output -> unTermCont $ do + outputF <- pletFieldsC @'["address", "value"] output + pure $ - inputF.address #== ownAddress - #&& psymbolValueOf # stCurrencySymbol # inputF.value #== 1 + outputF.address #== resolvedF.address + #&& psymbolValueOf # stCurrencySymbol # outputF.value #== 1 ) # pfromData txInfoF.outputs - stakeOut <- - pletC $ - mustFindDatum' @PStakeDatum - # (pfield @"datumHash" # ownOutput) - # txInfoF.datums + let witnessStake = unTermCont $ do + pguardC "Either owner signs the transaction or proposal token moved" $ + ownerSignsTransaction #|| proposalTokenMoved - ownOutputValue <- - pletC $ - pfield @"value" # ownOutput + -- FIXME: remove this once we have reference input. + -- + -- Our goal here is to allow multiple input stakes, and also ensure that every the input stakes has a + -- corresponding output stake, which carries the same value and the same datum as the input stake. + -- + -- Validation strategy I have tried/considered so far: + -- 1. Check that the number of input stakes equals to the number of output stakes, and verify + -- that there's an output stake with the exact same value and datum hash as the stake being + -- validated , However this approach has a fatal vulnerability: let's say we have two totally + -- identical stakes, a malicious user can comsume these two stakes and remove GTs from one of them. + -- 2. Perform the same checks as the last approch does, while also checking that every output stake is + -- valid(stakedAmount == actual value). However this requires that all the output stake datum are + -- included in the transaction, and we have to find and go through them one by one to access the + -- 'stakedAmount' fields, meaning that computationally this approach is *very* expensive. + -- 3. The one implemented below. Find all the continuous input/output, sort them by 'datumHash', and + -- ensure that the two sorted lists are equal. + let ownInputs = + pmapMaybe + # plam + ( \input -> plet (pfield @"resolved" # input) $ \resolvedInput -> + let value = pfield @"value" # resolvedInput + in pif + (psymbolValueOf # stCurrencySymbol # value #== 1) + (pcon $ PJust resolvedInput) + (pcon PNothing) + ) + # pfromData txInfoF.inputs - ownOutputValueUnchanged <- - pletC $ - pdata continuingValue #== pdata ownOutputValue + sortTxOuts :: Term _ (PBuiltinList PTxOut :--> PBuiltinList PTxOut) + sortTxOuts = phoistAcyclic $ plam (pmsortBy # plam ((#<) `on` (getDatumHash #)) #) + where + getDatumHash :: Term _ (PTxOut :--> PDatumHash) + getDatumHash = phoistAcyclic $ plam ((pfromDJust #) . pfromData . (pfield @"datumHash" #)) - stakeOutUnchanged <- - pletC $ - pdata stakeOut #== pdata stakeDatum' + sortedOwnInputs = sortTxOuts # ownInputs + sortedOwnOutputs = sortTxOuts # ownOutputs - pure $ - pmatch stakeRedeemer $ \case - PRetractVotes l -> unTermCont $ do - pguardC - "Owner signs this transaction" - ownerSignsTransaction + pguardC "Every stake inputs has a corresponding unchanged output" $ + plistEquals # sortedOwnInputs # sortedOwnOutputs + + pure $ popaque $ pconstant () + ---------------------------------------------------------------------- + + let onlyAcceptOneStake = unTermCont $ do pguardC "ST at inputs must be 1" $ spentST #== 1 - -- This puts trust into the Proposal. The Proposal must necessarily check - -- that this is not abused. - pguardC "Proposal ST spent" $ - spentProposalST #== 1 + ownOutput <- pletC $ phead # ownOutputs - pguardC "A UTXO must exist with the correct output" $ - let expectedLocks = pfield @"locks" # l + stakeOut <- + pletC $ + pfromData $ + mustFindDatum' @(PAsData PStakeDatum) + # (pfield @"datumHash" # ownOutput) + # txInfoF.datums - expectedDatum = - mkRecordConstr - PStakeDatum - ( #stakedAmount .= stakeDatum.stakedAmount - .& #owner .= stakeDatum.owner - .& #lockedBy .= expectedLocks - ) + ownOutputValue <- + pletC $ + pfield @"value" # ownOutput - valueCorrect = ownOutputValueUnchanged - outputDatumCorrect = stakeOut #== expectedDatum - in foldl1 - (#&&) - [ ptraceIfFalse "valueCorrect" valueCorrect - , ptraceIfFalse "datumCorrect" outputDatumCorrect - ] - - pure $ popaque (pconstant ()) - -------------------------------------------------------------------------- - PPermitVote l -> unTermCont $ do - pguardC - "Owner signs this transaction" - ownerSignsTransaction - - -- This puts trust into the Proposal. The Proposal must necessarily check - -- that this is not abused. - pguardC "Proposal ST spent" $ - spentProposalST #== 1 - - -- Update the stake datum, but only the 'lockedBy' field. - - let -- We actually don't know whether the given lock is valid or not. - -- This is checked in the proposal validator. - newLock = pfield @"lock" # l - -- Prepend the new lock to the existing locks. - expectedLocks = pcons # newLock # stakeDatum.lockedBy - - expectedDatum <- + ownOutputValueUnchanged <- pletC $ - mkRecordConstr - PStakeDatum - ( #stakedAmount .= stakeDatum.stakedAmount - .& #owner .= stakeDatum.owner - .& #lockedBy .= pdata expectedLocks - ) - - pguardC "A UTXO must exist with the correct output" $ - let correctOutputDatum = stakeOut #== expectedDatum - valueCorrect = ownOutputValueUnchanged - in foldl1 - (#&&) - [ ptraceIfFalse "valueCorrect" valueCorrect - , ptraceIfFalse "datumCorrect" correctOutputDatum - ] - - pure $ popaque (pconstant ()) - -------------------------------------------------------------------------- - PWitnessStake _ -> unTermCont $ do - pguardC "ST at inputs must be 1" $ - spentST #== 1 + pdata resolvedF.value #== pdata ownOutputValue - let AssetClass (propCs, propTn) = stake.proposalSTClass - propAssetClass = passetClass # pconstant propCs # pconstant propTn - proposalTokenMoved = - pisTokenSpent - # propAssetClass - # txInfoF.inputs - - -- In order for cosignature to be witnessed, it must be possible for a - -- proposal to allow this transaction to happen. This puts trust into the Proposal. - -- The Proposal must necessarily check that this is not abused. - pguardC - "Owner signs this transaction OR proposal token is spent" - (ownerSignsTransaction #|| proposalTokenMoved) - - pguardC "A UTXO must exist with the correct output" $ - let correctOutputDatum = stakeOutUnchanged - valueCorrect = ownOutputValueUnchanged - in foldl1 - (#&&) - [ ptraceIfFalse "valueCorrect" valueCorrect - , ptraceIfFalse "correctOutputDatum" correctOutputDatum - ] - pure $ popaque (pconstant ()) - -------------------------------------------------------------------------- - PDepositWithdraw r -> unTermCont $ do - pguardC "ST at inputs must be 1" $ - spentST #== 1 - pguardC "Stake unlocked" $ - pnot #$ stakeIsLocked - pguardC - "Owner signs this transaction" - ownerSignsTransaction - pguardC "A UTXO must exist with the correct output" $ - unTermCont $ do - let oldStakedAmount = pfromData $ stakeDatum.stakedAmount - delta = pfromData $ pfield @"delta" # r - - newStakedAmount <- pletC $ oldStakedAmount + delta - - pguardC "New staked amount shoudl be greater than or equal to 0" $ - zero #<= newStakedAmount - - let expectedDatum = + onlyLocksUpdated <- + pletC $ + let templateStakeDatum = mkRecordConstr PStakeDatum - ( #stakedAmount .= pdata newStakedAmount + ( #stakedAmount .= stakeDatum.stakedAmount .& #owner .= stakeDatum.owner - .& #lockedBy .= stakeDatum.lockedBy + .& #delegatedTo .= stakeDatum.delegatedTo + .& #lockedBy .= pfield @"lockedBy" # pto stakeOut ) - datumCorrect = stakeOut #== expectedDatum - - let valueDelta :: Term _ (PValue _ 'Positive) - valueDelta = pdiscreteValue' stake.gtClassRef # delta - - expectedValue = - continuingValue <> valueDelta - - valueCorrect = - foldr1 + in stakeOut #== templateStakeDatum + + setDelegate <- pletC $ + plam $ \maybePkh -> unTermCont $ do + pguardC + "Owner signs this transaction" + ownerSignsTransaction + + pguardC "A UTXO must exist with the correct output" $ + let correctOutputDatum = + stakeOut + #== mkRecordConstr + PStakeDatum + ( #stakedAmount .= stakeDatum.stakedAmount + .& #owner .= stakeDatum.owner + .& #delegatedTo .= pdata maybePkh + .& #lockedBy .= stakeDatum.lockedBy + ) + valueCorrect = ownOutputValueUnchanged + in foldl1 (#&&) - [ pgeqByClass' (AssetClass ("", "")) - # ownOutputValue - # expectedValue - , pgeqByClass' (untag stake.gtClassRef) - # ownOutputValue - # expectedValue - , pgeqBySymbol - # stCurrencySymbol - # ownOutputValue - # expectedValue + [ ptraceIfFalse "valueCorrect" valueCorrect + , ptraceIfFalse "datumCorrect" correctOutputDatum ] - -- - pure $ - foldl1 - (#&&) - [ ptraceIfFalse "valueCorrect" valueCorrect - , ptraceIfFalse "datumCorrect" datumCorrect - ] - -- - pure $ popaque (pconstant ()) - _ -> popaque (pconstant ()) + + pure $ popaque (pconstant ()) + + pure $ + pmatch stakeRedeemer $ \case + PRetractVotes _ -> unTermCont $ do + pguardC + "Owner or delegate signs this transaction" + $ ownerSignsTransaction #|| delegateSignsTransaction + + -- This puts trust into the Proposal. The Proposal must necessarily check + -- that this is not abused. + pguardC "Proposal ST spent" proposalTokenMoved + + pguardC "A UTXO must exist with the correct output" $ + let valueCorrect = ownOutputValueUnchanged + outputDatumCorrect = onlyLocksUpdated + in foldl1 + (#&&) + [ ptraceIfFalse "valueCorrect" valueCorrect + , ptraceIfFalse "datumCorrect" outputDatumCorrect + ] + + pure $ popaque (pconstant ()) + + ------------------------------------------------------------ + + PPermitVote _ -> unTermCont $ do + pguardC + "Owner or delegate signs this transaction" + $ ownerSignsTransaction #|| delegateSignsTransaction + + let proposalTokenMinted = + passetClassValueOf # txInfoF.mint # proposalSTClass #== 1 + + -- This puts trust into the Proposal. The Proposal must necessarily check + -- that this is not abused. + pguardC "Proposal ST spent or minted" $ + proposalTokenMoved #|| proposalTokenMinted + pguardC "A UTXO must exist with the correct output" $ + let correctOutputDatum = onlyLocksUpdated + valueCorrect = ownOutputValueUnchanged + in foldl1 + (#&&) + [ ptraceIfFalse "valueCorrect" valueCorrect + , ptraceIfFalse "datumCorrect" correctOutputDatum + ] + + pure $ popaque (pconstant ()) + + ------------------------------------------------------------ + + PDepositWithdraw r -> unTermCont $ do + pguardC "Stake unlocked" $ + pnot #$ stakeIsLocked + pguardC + "Owner signs this transaction" + ownerSignsTransaction + pguardC "A UTXO must exist with the correct output" $ + unTermCont $ do + let oldStakedAmount = pfromData $ stakeDatum.stakedAmount + delta = pfromData $ pfield @"delta" # r + + newStakedAmount <- pletC $ oldStakedAmount + delta + + pguardC "New staked amount should be greater than or equal to 0" $ + zero #<= newStakedAmount + + let expectedDatum = + mkRecordConstr + PStakeDatum + ( #stakedAmount .= pdata newStakedAmount + .& #owner .= stakeDatum.owner + .& #delegatedTo .= stakeDatum.delegatedTo + .& #lockedBy .= stakeDatum.lockedBy + ) + datumCorrect = stakeOut #== expectedDatum + + let valueDelta :: Term _ (PValue _ 'Positive) + valueDelta = pdiscreteValue' gtClassRef # delta + + expectedValue = + resolvedF.value <> valueDelta + + valueCorrect = + foldr1 + (#&&) + [ pgeqByClass' (AssetClass ("", "")) + # ownOutputValue + # expectedValue + , pgeqByClass' (untag gtClassRef) + # ownOutputValue + # expectedValue + , pgeqBySymbol + # stCurrencySymbol + # ownOutputValue + # expectedValue + ] + -- + pure $ + foldl1 + (#&&) + [ ptraceIfFalse "valueCorrect" valueCorrect + , ptraceIfFalse "datumCorrect" datumCorrect + ] + -- + pure $ popaque (pconstant ()) + + ------------------------------------------------------------ + + PDelegateTo ((pfromData . (pfield @"pkh" #)) -> pkh) -> unTermCont $ do + pguardC "Cannot delegate to the owner" $ + pnot #$ stakeDatum.owner #== pkh + + pure $ setDelegate #$ pdjust # pdata pkh + ------------------------------------------------------------ + + PClearDelegate _ -> + setDelegate # pdnothing + ------------------------------------------------------------ + + _ -> popaque (pconstant ()) + + pure $ + pif + (pdata stakeRedeemer #== pconstantData WitnessStake) + witnessStake + onlyAcceptOneStake diff --git a/agora/Agora/Treasury.hs b/agora/Agora/Treasury.hs index 85f4869b..e5b37336 100644 --- a/agora/Agora/Treasury.hs +++ b/agora/Agora/Treasury.hs @@ -11,16 +11,17 @@ treasury. module Agora.Treasury (module Agora.Treasury) where import Agora.AuthorityToken (singleAuthorityTokenBurned) -import GHC.Generics qualified as GHC -import Generics.SOP (Generic, I (I)) +import Generics.SOP qualified as SOP import Plutarch.Api.V1 (PValidator) import Plutarch.Api.V1.Contexts (PScriptPurpose (PMinting)) import "plutarch" Plutarch.Api.V1.Value (PValue) -import Plutarch.DataRepr ( - DerivePConstantViaData (..), - PIsDataReprInstances (PIsDataReprInstances), +import Plutarch.Builtin (pforgetData) +import Plutarch.Extra.IsData ( + DerivePConstantViaEnum (..), + EnumIsData (..), + PlutusTypeEnumData, ) -import Plutarch.Extra.TermCont (pguardC, pletC, pmatchC, ptryFromC) +import Plutarch.Extra.TermCont (pguardC, pletC, pletFieldsC, pmatchC) import Plutarch.Lift (PConstantDecl (..), PLifted (..), PUnsafeLiftDecl) import Plutarch.TryFrom () import PlutusLedgerApi.V1.Value (CurrencySymbol) @@ -39,14 +40,23 @@ data TreasuryRedeemer , -- | @since 0.1.0 Show , -- | @since 0.1.0 - GHC.Generic + Generic + , -- | @since 0.2.0 + Enum + , -- | @since 0.2.0 + Bounded ) - --- | @since 0.1.0 -PlutusTx.makeIsDataIndexed - ''TreasuryRedeemer - [ ('SpendTreasuryGAT, 0) - ] + deriving anyclass + ( -- | @since 0.2.0 + SOP.Generic + ) + deriving + ( -- | @since 0.1.0 + PlutusTx.ToData + , -- | @since 0.1.0 + PlutusTx.FromData + ) + via (EnumIsData TreasuryRedeemer) -------------------------------------------------------------------------------- @@ -55,33 +65,25 @@ PlutusTx.makeIsDataIndexed @since 0.1.0 -} -newtype PTreasuryRedeemer (s :: S) - = -- | Alters treasury parameters, subject to the burning of a - -- governance authority token. - PSpendTreasuryGAT (Term s (PDataRecord '[])) +data PTreasuryRedeemer (s :: S) + = PSpendTreasuryGAT deriving stock - ( -- | @since 0.1.0 - GHC.Generic - ) - deriving anyclass ( -- | @since 0.1.0 Generic - , -- | @since 0.1.0 - PIsDataRepr + , -- | @since 0.2.0 + Bounded + , -- | @since 0.2.0 + Enum ) - deriving + deriving anyclass ( -- | @since 0.1.0 PlutusType , -- | @since 0.1.0 PIsData ) - via PIsDataReprInstances PTreasuryRedeemer --- | @since 0.1.0 -deriving via - PAsData (PIsDataReprInstances PTreasuryRedeemer) - instance - PTryFrom PData (PAsData PTreasuryRedeemer) +instance DerivePlutusType PTreasuryRedeemer where + type DPTStrat _ = PlutusTypeEnumData -- | @since 0.1.0 instance PUnsafeLiftDecl PTreasuryRedeemer where @@ -89,7 +91,7 @@ instance PUnsafeLiftDecl PTreasuryRedeemer where -- | @since 0.1.0 deriving via - (DerivePConstantViaData TreasuryRedeemer PTreasuryRedeemer) + (DerivePConstantViaEnum TreasuryRedeemer PTreasuryRedeemer) instance (PConstantDecl TreasuryRedeemer) @@ -105,26 +107,24 @@ treasuryValidator :: CurrencySymbol -> ClosedTerm PValidator treasuryValidator gatCs' = plam $ \_datum redeemer ctx' -> unTermCont $ do - (treasuryRedeemer, _) <- ptryFromC redeemer - -- plet required fields from script context. - ctx <- tcont $ pletFields @["txInfo", "purpose"] ctx' + ctx <- pletFieldsC @["txInfo", "purpose"] ctx' -- Ensure that script is for burning i.e. minting a negative amount. PMinting _ <- pmatchC ctx.purpose -- Ensure redeemer type is valid. - PSpendTreasuryGAT _ <- pmatchC $ pfromData treasuryRedeemer + pguardC "Redeemer should be SpendTreasuryGAT" $ + redeemer #== pforgetData (pconstantData SpendTreasuryGAT) -- Get the minted value from txInfo. - txInfo' <- pletC ctx.txInfo - txInfo <- tcont $ pletFields @'["mint"] txInfo' + txInfo <- pletFieldsC @'["mint", "inputs"] ctx.txInfo let mint :: Term _ (PValue _ _) mint = txInfo.mint gatCs <- pletC $ pconstant gatCs' pguardC "A single authority token has been burned" $ - singleAuthorityTokenBurned gatCs txInfo' mint + singleAuthorityTokenBurned gatCs txInfo.inputs mint pure . popaque $ pconstant () diff --git a/agora/Agora/Utils.hs b/agora/Agora/Utils.hs index 02ef1eb6..97a7cd0f 100644 --- a/agora/Agora/Utils.hs +++ b/agora/Agora/Utils.hs @@ -1,3 +1,6 @@ +{-# LANGUAGE QuantifiedConstraints #-} +{-# OPTIONS_GHC -Wno-unrecognised-pragmas #-} + {- | Module : Agora.Utils Maintainer : emi@haskell.fyi @@ -6,49 +9,32 @@ Description: Plutarch utility functions that should be upstreamed or don't belon Plutarch utility functions that should be upstreamed or don't belong anywhere else. -} module Agora.Utils ( - scriptHashFromAddress, - findOutputsToAddress, - findTxOutDatum, validatorHashToTokenName, - pvalidatorHashToTokenName, - getMintingPolicySymbol, - hasOnlyOneTokenOfCurrencySymbol, mustFindDatum', - mustBePJust, - mustBePDJust, validatorHashToAddress, - isScriptAddress, - isPubKey, + pltAsData, + withBuiltinPairAsData, + CompiledValidator (..), + CompiledMintingPolicy (..), + CompiledEffect (..), ) where import Plutarch.Api.V1 ( - AmountGuarantees, - KeyGuarantees, - PAddress, - PCredential (PScriptCredential), - PCurrencySymbol, PDatum, PDatumHash, - PMaybeData (PDJust), - PMintingPolicy, - PTokenName (PTokenName), + PMaybeData, PTuple, - PTxOut, - PValidatorHash, - PValue, - mintingPolicySymbol, - mkMintingPolicy, ) -import Plutarch.Api.V1.ScriptContext (pfindDatum) -import "liqwid-plutarch-extra" Plutarch.Api.V1.Value (psymbolValueOf) import Plutarch.Builtin (pforgetData) import Plutarch.Extra.List (plookupTuple) -import Plutarch.Extra.TermCont (pletC, pmatchC) +import Plutarch.Extra.Maybe (passertPDJust, passertPJust) +import Plutarch.Extra.TermCont (ptryFromC) import PlutusLedgerApi.V1 ( Address (..), Credential (..), - CurrencySymbol, + MintingPolicy, TokenName (..), + Validator, ValidatorHash (..), ) @@ -56,60 +42,6 @@ import PlutusLedgerApi.V1 ( All of these functions are quite inefficient. -} -{- | Get script hash from an Address. - - @since 0.1.0 --} -scriptHashFromAddress :: Term s (PAddress :--> PMaybe PValidatorHash) -scriptHashFromAddress = phoistAcyclic $ - plam $ \addr -> - pmatch (pfromData $ pfield @"credential" # addr) $ \case - PScriptCredential ((pfield @"_0" #) -> h) -> pcon $ PJust h - _ -> pcon PNothing - -{- | Return true if the given address is a script address. - - @since 0.1.0 --} -isScriptAddress :: Term s (PAddress :--> PBool) -isScriptAddress = phoistAcyclic $ - plam $ \addr -> pnot #$ isPubKey #$ pfromData $ pfield @"credential" # addr - -{- | Return true if the given credential is a pub-key-hash. - - @since 0.1.0 --} -isPubKey :: Term s (PCredential :--> PBool) -isPubKey = phoistAcyclic $ - plam $ \cred -> - pmatch cred $ \case - PScriptCredential _ -> pconstant False - _ -> pconstant True - -{- | Find all TxOuts sent to an Address - - @since 0.1.0 --} -findOutputsToAddress :: Term s (PBuiltinList (PAsData PTxOut) :--> PAddress :--> PBuiltinList (PAsData PTxOut)) -findOutputsToAddress = phoistAcyclic $ - plam $ \outputs address' -> unTermCont $ do - address <- pletC $ pdata address' - pure $ - pfilter # plam (\(pfromData -> txOut) -> pfield @"address" # txOut #== address) - # outputs - -{- | Find the data corresponding to a TxOut, if there is one - - @since 0.1.0 --} -findTxOutDatum :: Term s (PBuiltinList (PAsData (PTuple PDatumHash PDatum)) :--> PTxOut :--> PMaybe PDatum) -findTxOutDatum = phoistAcyclic $ - plam $ \datums out -> unTermCont $ do - datumHash' <- pmatchC $ pfromData $ pfield @"datumHash" # out - pure $ case datumHash' of - PDJust ((pfield @"_0" #) -> datumHash) -> pfindDatum # datumHash # datums - _ -> pcon PNothing - {- | Safely convert a 'PValidatorHash' into a 'PTokenName'. This can be useful for tagging tokens for extra safety. @@ -118,39 +50,13 @@ findTxOutDatum = phoistAcyclic $ validatorHashToTokenName :: ValidatorHash -> TokenName validatorHashToTokenName (ValidatorHash hash) = TokenName hash -{- | Plutarch level 'validatorHashToTokenName'. - - @since 0.1.0 --} -pvalidatorHashToTokenName :: forall (s :: S). Term s PValidatorHash -> Term s PTokenName -pvalidatorHashToTokenName vh = pcon (PTokenName (pto vh)) - -{- | Get the CurrencySymbol of a PMintingPolicy. - - @since 0.1.0 --} -getMintingPolicySymbol :: ClosedTerm PMintingPolicy -> CurrencySymbol -getMintingPolicySymbol v = mintingPolicySymbol $ mkMintingPolicy v - -{- | The entire value only contains one token of the given currency symbol. - - @since 0.1.0 --} -hasOnlyOneTokenOfCurrencySymbol :: - forall (keys :: KeyGuarantees) (amounts :: AmountGuarantees) (s :: S). - Term s (PCurrencySymbol :--> PValue keys amounts :--> PBool) -hasOnlyOneTokenOfCurrencySymbol = phoistAcyclic $ - plam $ \cs vs -> P.do - psymbolValueOf # cs # vs #== 1 - #&& (plength #$ pto $ pto $ pto vs) #== 1 - {- | Find datum given a maybe datum hash @since 0.1.0 -} mustFindDatum' :: forall (datum :: PType). - (PIsData datum, PTryFrom PData (PAsData datum)) => + (PIsData datum, PTryFrom PData datum) => forall s. Term s @@ -160,36 +66,67 @@ mustFindDatum' :: ) mustFindDatum' = phoistAcyclic $ plam $ \mdh datums -> unTermCont $ do - let dh = mustBePDJust # "Given TxOut dones't have a datum" # mdh - dt = mustBePJust # "Datum not found in the transaction" #$ plookupTuple # dh # datums - (d, _) <- tcont $ ptryFrom $ pforgetData $ pdata dt - pure $ pfromData d + let dh = passertPDJust # "Given TxOut dones't have a datum" # mdh + dt = passertPJust # "Datum not found in the transaction" #$ plookupTuple # dh # datums + (d, _) <- ptryFromC $ pforgetData $ pdata dt + pure d -{- | Extract the value stored in a PMaybe container. - If there's no value, throw an error with the given message. +{- | Create an 'Address' from a given 'ValidatorHash' with no 'PlutusLedgerApi.V1.Credential.StakingCredential'. @since 0.1.0 -} -mustBePJust :: forall a s. Term s (PString :--> PMaybe a :--> a) -mustBePJust = phoistAcyclic $ - plam $ \emsg mv' -> pmatch mv' $ \case - PJust v -> v - _ -> ptraceError emsg +validatorHashToAddress :: ValidatorHash -> Address +validatorHashToAddress vh = Address (ScriptCredential vh) Nothing -{- | Extract the value stored in a PMaybeData container. - If there's no value, throw an error with the given message. +{- | Compare two 'PAsData' value, return true if the first one is less than the second one. - @since 0.1.0 + @since 0.2.0 -} -mustBePDJust :: forall a s. (PIsData a) => Term s (PString :--> PMaybeData a :--> a) -mustBePDJust = phoistAcyclic $ - plam $ \emsg mv' -> pmatch mv' $ \case - PDJust ((pfield @"_0" #) -> v) -> v - _ -> ptraceError emsg +pltAsData :: + forall (a :: PType) (s :: S). + (POrd a, PIsData a) => + Term s (PAsData a :--> PAsData a :--> PBool) +pltAsData = phoistAcyclic $ + plam $ + \(pfromData -> l) (pfromData -> r) -> l #< r -{- | Create an 'Address' from a given 'ValidatorHash' with no 'PlutusLedgerApi.V1.Credential.StakingCredential'. +{- | Extract data stored in a 'PBuiltinPair' and call a function to process it. - @since 0.1.0 + @since 0.2.0 -} -validatorHashToAddress :: ValidatorHash -> Address -validatorHashToAddress vh = Address (ScriptCredential vh) Nothing +withBuiltinPairAsData :: + forall (a :: PType) (b :: PType) (c :: PType) (s :: S). + (PIsData a, PIsData b) => + (Term s a -> Term s b -> Term s c) -> + Term + s + (PBuiltinPair (PAsData a) (PAsData b)) -> + Term s c +withBuiltinPairAsData f p = + let a = pfromData $ pfstBuiltin # p + b = pfromData $ psndBuiltin # p + in f a b + +{- | Type-safe wrapper for compiled plutus validator. + + @since 0.2.0 +-} +newtype CompiledValidator (datum :: Type) (redeemer :: Type) = CompiledValidator + { getCompiledValidator :: Validator + } + +{- | Type-safe wrapper for compiled plutus miting policy. + + @since 0.2.0 +-} +newtype CompiledMintingPolicy (redeemer :: Type) = CompiledMintingPolicy + { getCompiledMintingPolicy :: MintingPolicy + } + +{- | Type-safe wrapper for compiled plutus effect. + + @since 0.2.0 +-} +newtype CompiledEffect (datum :: Type) = CompiledEffect + { getCompiledEffect :: Validator + } diff --git a/bench.csv b/bench.csv index 723eb3ae..bc75af40 100644 --- a/bench.csv +++ b/bench.csv @@ -1,37 +1,582 @@ name,cpu,mem,size -Agora/Effects/Treasury Withdrawal Effect/effect/Simple,333327612,830203,3674 -Agora/Effects/Treasury Withdrawal Effect/effect/Simple with multiple treasuries ,492387542,1197315,3986 -Agora/Effects/Treasury Withdrawal Effect/effect/Mixed Assets,456007605,1104500,3859 -Agora/Effects/Governor Mutation Effect/validator/valid new governor datum/governor validator should pass,90397270,249528,8807 -Agora/Effects/Governor Mutation Effect/validator/valid new governor datum/effect validator should pass,106082031,292993,3609 -Agora/Stake/policy/stakeCreation,52241265,152127,2514 -Agora/Stake/validator/stakeDepositWithdraw deposit,180880812,492023,4431 -Agora/Stake/validator/stakeDepositWithdraw withdraw,180880812,492023,4419 -Agora/Proposal/policy/proposalCreation,23140177,69194,1519 -Agora/Proposal/validator/cosignature/proposal,338483402,961112,8620 -Agora/Proposal/validator/cosignature/stake,126327509,315061,4968 -Agora/Proposal/validator/voting/proposal,296656410,830692,8549 -Agora/Proposal/validator/voting/stake,121170376,320853,4942 -Agora/Proposal/validator/advancing/successfully advance to next state/Draft -> VotringReady,294340341,825452,8447 -Agora/Proposal/validator/advancing/successfully advance to next state/VotingReady -> Locked,306801371,861382,8456 -Agora/Proposal/validator/advancing/successfully advance to next state/Locked -> Finished,295193386,827555,8456 -Agora/Proposal/validator/advancing/successfully advance to failed state: timeout/Draft -> Finished,293210540,822722,8449 -Agora/Proposal/validator/advancing/successfully advance to failed state: timeout/VotingReady -> Finished,291801629,820017,8450 -Agora/Proposal/validator/advancing/successfully advance to failed state: timeout/Locked -> Finished,292932607,822421,8450 -"Agora/Proposal/validator/unlocking/legal/1 proposals, voter, unlock stake + retract votes, VotingReady",302502183,848154,8500 -"Agora/Proposal/validator/unlocking/legal/1 proposals, creator, unlock stake, Finished",273224492,773388,8504 -"Agora/Proposal/validator/unlocking/legal/voter unlocks stake after voting/1 proposals, voter, unlock stake, Finished",268700821,763033,8504 -"Agora/Proposal/validator/unlocking/legal/voter unlocks stake after voting/1 proposals, voter, unlock stake, Locked",268700821,763033,8504 -"Agora/Proposal/validator/unlocking/legal/42 proposals, voter, unlock stake + retract votes, VotingReady",2908014422,8180225,30018 -"Agora/Proposal/validator/unlocking/legal/42 proposals, creator, unlock stake, Finished",2616129517,7383326,30287 -"Agora/Proposal/validator/unlocking/legal/voter unlocks stake after voting/42 proposals, voter, unlock stake, Finished",2464384686,6936321,30187 -"Agora/Proposal/validator/unlocking/legal/voter unlocks stake after voting/42 proposals, voter, unlock stake, Locked",2464384686,6936321,30187 -Agora/AuthorityToken/singleAuthorityTokenBurned/Correct simple,21017788,55883,806 -Agora/AuthorityToken/singleAuthorityTokenBurned/Correct many inputs,33204186,88241,900 -Agora/Treasury/Validator/Positive/Allows for effect changes,29938856,79744,1391 -Agora/AuthorityToken/singleAuthorityTokenBurned/Correct simple,21017788,55883,806 -Agora/AuthorityToken/singleAuthorityTokenBurned/Correct many inputs,33204186,88241,900 -Agora/Governor/policy/GST minting,51007235,144191,2034 -Agora/Governor/validator/proposal creation,317651809,854963,9323 -Agora/Governor/validator/GATs minting,423756405,1151000,9444 -Agora/Governor/validator/mutate governor state,91544121,254987,8908 +Agora/Effects/Treasury Withdrawal Effect/effect/Simple,380214695,980182,4275 +Agora/Effects/Treasury Withdrawal Effect/effect/Simple with multiple treasuries ,544143721,1366494,4691 +Agora/Effects/Treasury Withdrawal Effect/effect/Mixed Assets,545045362,1387355,4636 +Agora/Effects/Governor Mutation Effect/validator/valid new governor datum/governor validator should pass,112721874,312363,9413 +Agora/Effects/Governor Mutation Effect/validator/valid new governor datum/effect validator should pass,152563857,422397,4692 +Agora/Stake/policy/stakeCreation,54323406,159125,2646 +Agora/Stake/validator/stakeDepositWithdraw deposit,194804304,538628,5315 +Agora/Stake/validator/stakeDepositWithdraw withdraw,194804304,538628,5303 +Agora/Stake/validator/set delegate/override existing delegate,117949415,309090,5367 +Agora/Stake/validator/set delegate/remove existing delegate,115539973,301757,5304 +Agora/Stake/validator/set delegate/set delegate to something,114218077,301022,5304 +Agora/Proposal/policy (proposal creation)/legal/proposal,33965644,101486,1971 +Agora/Proposal/policy (proposal creation)/legal/governor,369498544,984529,9918 +Agora/Proposal/policy (proposal creation)/legal/stake,168978875,446628,5969 +Agora/Proposal/policy (proposal creation)/illegal/invalid next proposal id/proposal,33965644,101486,1971 +Agora/Proposal/policy (proposal creation)/illegal/invalid next proposal id/stake,168978875,446628,5969 +Agora/Proposal/policy (proposal creation)/illegal/use other's stake/proposal,33965644,101486,1940 +Agora/Proposal/policy (proposal creation)/illegal/use other's stake/governor,369498544,984529,9887 +Agora/Proposal/policy (proposal creation)/illegal/altered stake/proposal,33965644,101486,1971 +Agora/Proposal/policy (proposal creation)/illegal/invalid stake locks/proposal,33965644,101486,1979 +Agora/Proposal/policy (proposal creation)/illegal/invalid stake locks/stake,174412535,461278,5977 +Agora/Proposal/policy (proposal creation)/illegal/has reached maximum proposals limit/proposal,33965644,101486,1991 +Agora/Proposal/policy (proposal creation)/illegal/has reached maximum proposals limit/stake,181677311,482844,5999 +Agora/Proposal/policy (proposal creation)/illegal/loose time range/proposal,33965644,101486,1971 +Agora/Proposal/policy (proposal creation)/illegal/loose time range/stake,168978875,446628,5969 +Agora/Proposal/policy (proposal creation)/illegal/open time range/proposal,33965644,101486,1967 +Agora/Proposal/policy (proposal creation)/illegal/open time range/stake,168978875,446628,5965 +Agora/Proposal/policy (proposal creation)/illegal/invalid proposal status/VotingReady/proposal,33965644,101486,1971 +Agora/Proposal/policy (proposal creation)/illegal/invalid proposal status/VotingReady/stake,168978875,446628,5969 +Agora/Proposal/policy (proposal creation)/illegal/invalid proposal status/Locked/proposal,33965644,101486,1971 +Agora/Proposal/policy (proposal creation)/illegal/invalid proposal status/Locked/stake,168978875,446628,5969 +Agora/Proposal/policy (proposal creation)/illegal/invalid proposal status/Finished/proposal,33965644,101486,1971 +Agora/Proposal/policy (proposal creation)/illegal/invalid proposal status/Finished/stake,168978875,446628,5969 +Agora/Proposal/validator/cosignature/legal/with 1 cosigners/proposal,278329834,780402,9534 +Agora/Proposal/validator/cosignature/legal/with 1 cosigners/stake,132939473,344002,5780 +Agora/Proposal/validator/cosignature/legal/with 5 cosigners/proposal,733369909,2047977,12188 +Agora/Proposal/validator/cosignature/legal/with 5 cosigners/stake,584246489,1537942,8314 +Agora/Proposal/validator/cosignature/legal/with 10 cosigners/proposal,1453961927,4008580,15507 +Agora/Proposal/validator/cosignature/legal/with 10 cosigners/stake,1244034344,3305773,11482 +Agora/Proposal/validator/cosignature/illegal/duplicate cosigners/stake,132939473,344002,5780 +Agora/Proposal/validator/cosignature/illegal/proposal status not Draft/with 1 cosigners/status: VotingReady/stake,132939473,344002,5780 +Agora/Proposal/validator/cosignature/illegal/proposal status not Draft/with 1 cosigners/status: Locked/stake,132939473,344002,5780 +Agora/Proposal/validator/cosignature/illegal/proposal status not Draft/with 1 cosigners/status: Finished/stake,132939473,344002,5780 +Agora/Proposal/validator/cosignature/illegal/proposal status not Draft/with 5 cosigners/status: VotingReady/stake,584246489,1537942,8314 +Agora/Proposal/validator/cosignature/illegal/proposal status not Draft/with 5 cosigners/status: Locked/stake,584246489,1537942,8314 +Agora/Proposal/validator/cosignature/illegal/proposal status not Draft/with 5 cosigners/status: Finished/stake,584246489,1537942,8314 +Agora/Proposal/validator/cosignature/illegal/proposal status not Draft/with 10 cosigners/status: VotingReady/stake,1244034344,3305773,11482 +Agora/Proposal/validator/cosignature/illegal/proposal status not Draft/with 10 cosigners/status: Locked/stake,1244034344,3305773,11482 +Agora/Proposal/validator/cosignature/illegal/proposal status not Draft/with 10 cosigners/status: Finished/stake,1244034344,3305773,11482 +Agora/Proposal/validator/voting/legal/ordinary/proposal,300100170,843476,9516 +Agora/Proposal/validator/voting/legal/ordinary/stake,157219895,416300,5803 +Agora/Proposal/validator/voting/legal/delegate/proposal,301216160,847088,9579 +Agora/Proposal/validator/voting/legal/delegate/stake,161458884,426174,5897 +Agora/Proposal/validator/advancing/with 1 cosigners and 1 effects/legal/to next state/from Draft to VotingReady/proposal,293553258,818566,10029 +Agora/Proposal/validator/advancing/with 1 cosigners and 1 effects/legal/to next state/from Draft to VotingReady/stake,144038574,373470,6116 +Agora/Proposal/validator/advancing/with 1 cosigners and 1 effects/legal/to next state/from VotingReady to Locked/proposal,339788223,934150,10038 +Agora/Proposal/validator/advancing/with 1 cosigners and 1 effects/legal/to next state/from VotingReady to Locked/stake,144761110,375734,6123 +Agora/Proposal/validator/advancing/with 1 cosigners and 1 effects/legal/to next state/from Locked to Finished/proposal,389689216,1074147,11190 +Agora/Proposal/validator/advancing/with 1 cosigners and 1 effects/legal/to next state/from Locked to Finished/stake,201040711,510637,7275 +Agora/Proposal/validator/advancing/with 1 cosigners and 1 effects/legal/to next state/from Locked to Finished/governor,494243991,1258194,11233 +Agora/Proposal/validator/advancing/with 1 cosigners and 1 effects/legal/to next state/from Locked to Finished/authority,15875303,48540,3625 +Agora/Proposal/validator/advancing/with 1 cosigners and 1 effects/legal/to failed state/from Draft to Finished/proposal,290760522,812653,10031 +Agora/Proposal/validator/advancing/with 1 cosigners and 1 effects/legal/to failed state/from Draft to Finished/stake,144761110,375734,6118 +Agora/Proposal/validator/advancing/with 1 cosigners and 1 effects/legal/to failed state/from VotingReady to Finished/proposal,327404759,899415,10032 +Agora/Proposal/validator/advancing/with 1 cosigners and 1 effects/legal/to failed state/from VotingReady to Finished/stake,144761110,375734,6119 +Agora/Proposal/validator/advancing/with 1 cosigners and 1 effects/legal/to failed state/from Locked to Finished/proposal,329666715,904223,10032 +Agora/Proposal/validator/advancing/with 1 cosigners and 1 effects/legal/to failed state/from Locked to Finished/stake,144761110,375734,6119 +Agora/Proposal/validator/advancing/with 1 cosigners and 1 effects/illegal/advance finished proposals/(negative test)/stake,144038574,373470,6116 +Agora/Proposal/validator/advancing/with 1 cosigners and 1 effects/illegal/advance finished proposals/(negative test)/stake,144761110,375734,6123 +Agora/Proposal/validator/advancing/with 1 cosigners and 1 effects/illegal/advance finished proposals/(negative test)/stake,201040711,510637,7275 +Agora/Proposal/validator/advancing/with 1 cosigners and 1 effects/illegal/advance finished proposals/(negative test)/authority,15875303,48540,3625 +Agora/Proposal/validator/advancing/with 1 cosigners and 1 effects/illegal/insufficient cosigns/stake,144038574,373470,6116 +Agora/Proposal/validator/advancing/with 1 cosigners and 1 effects/illegal/insufficient votes/stake,144761110,375734,6119 +Agora/Proposal/validator/advancing/with 1 cosigners and 1 effects/illegal/ambiguous winning effect/stake,144761110,375734,6127 +Agora/Proposal/validator/advancing/with 1 cosigners and 1 effects/illegal/to next state too late/from Draft/stake,144038574,373470,6118 +Agora/Proposal/validator/advancing/with 1 cosigners and 1 effects/illegal/to next state too late/from VotingReady/stake,144761110,375734,6123 +Agora/Proposal/validator/advancing/with 1 cosigners and 1 effects/illegal/to next state too late/from Locked/stake,201040711,510637,7275 +Agora/Proposal/validator/advancing/with 1 cosigners and 1 effects/illegal/to next state too late/from Locked/governor,494243991,1258194,11233 +Agora/Proposal/validator/advancing/with 1 cosigners and 1 effects/illegal/to next state too late/from Locked/authority,15875303,48540,3625 +Agora/Proposal/validator/advancing/with 1 cosigners and 1 effects/illegal/altered output stake datum/from Locked/governor,494243991,1258194,11234 +Agora/Proposal/validator/advancing/with 1 cosigners and 1 effects/illegal/altered output stake datum/from Locked/authority,15875303,48540,3626 +Agora/Proposal/validator/advancing/with 1 cosigners and 1 effects/illegal/forget to mint GATs/proposal,365438170,1001538,10479 +Agora/Proposal/validator/advancing/with 1 cosigners and 1 effects/illegal/forget to mint GATs/stake,187940552,485026,6564 +Agora/Proposal/validator/advancing/with 1 cosigners and 1 effects/illegal/mint GATs for wrong validators/proposal,397772898,1098350,11417 +Agora/Proposal/validator/advancing/with 1 cosigners and 1 effects/illegal/mint GATs for wrong validators/stake,204588820,517864,7502 +Agora/Proposal/validator/advancing/with 1 cosigners and 1 effects/illegal/mint GATs for wrong validators/authority,17699300,53602,3852 +Agora/Proposal/validator/advancing/with 1 cosigners and 1 effects/illegal/mint GATs with bad token name/proposal,389689216,1074147,11012 +Agora/Proposal/validator/advancing/with 1 cosigners and 1 effects/illegal/mint GATs with bad token name/stake,201040711,510637,7097 +Agora/Proposal/validator/advancing/with 1 cosigners and 1 effects/illegal/wrong GAT datum/proposal,389689216,1074147,11184 +Agora/Proposal/validator/advancing/with 1 cosigners and 1 effects/illegal/wrong GAT datum/stake,201040711,510637,7269 +Agora/Proposal/validator/advancing/with 1 cosigners and 1 effects/illegal/wrong GAT datum/authority,15875303,48540,3619 +Agora/Proposal/validator/advancing/with 1 cosigners and 1 effects/illegal/invalid governor output datum/proposal,389689216,1074147,11190 +Agora/Proposal/validator/advancing/with 1 cosigners and 1 effects/illegal/invalid governor output datum/stake,201040711,510637,7275 +Agora/Proposal/validator/advancing/with 1 cosigners and 1 effects/illegal/invalid governor output datum/authority,15875303,48540,3625 +Agora/Proposal/validator/advancing/with 1 cosigners and 2 effects/legal/to next state/from Draft to VotingReady/proposal,340836965,940834,10618 +Agora/Proposal/validator/advancing/with 1 cosigners and 2 effects/legal/to next state/from Draft to VotingReady/stake,144038574,373470,6509 +Agora/Proposal/validator/advancing/with 1 cosigners and 2 effects/legal/to next state/from VotingReady to Locked/proposal,390766816,1066406,10627 +Agora/Proposal/validator/advancing/with 1 cosigners and 2 effects/legal/to next state/from VotingReady to Locked/stake,144761110,375734,6516 +Agora/Proposal/validator/advancing/with 1 cosigners and 2 effects/legal/to next state/from Locked to Finished/proposal,436972923,1196415,11780 +Agora/Proposal/validator/advancing/with 1 cosigners and 2 effects/legal/to next state/from Locked to Finished/stake,201040711,510637,7669 +Agora/Proposal/validator/advancing/with 1 cosigners and 2 effects/legal/to next state/from Locked to Finished/governor,514789615,1314031,11627 +Agora/Proposal/validator/advancing/with 1 cosigners and 2 effects/legal/to next state/from Locked to Finished/authority,15875303,48540,4019 +Agora/Proposal/validator/advancing/with 1 cosigners and 2 effects/legal/to failed state/from Draft to Finished/proposal,338044229,934921,10620 +Agora/Proposal/validator/advancing/with 1 cosigners and 2 effects/legal/to failed state/from Draft to Finished/stake,144761110,375734,6511 +Agora/Proposal/validator/advancing/with 1 cosigners and 2 effects/legal/to failed state/from VotingReady to Finished/proposal,374688466,1021683,10621 +Agora/Proposal/validator/advancing/with 1 cosigners and 2 effects/legal/to failed state/from VotingReady to Finished/stake,144761110,375734,6512 +Agora/Proposal/validator/advancing/with 1 cosigners and 2 effects/legal/to failed state/from Locked to Finished/proposal,376950422,1026491,10621 +Agora/Proposal/validator/advancing/with 1 cosigners and 2 effects/legal/to failed state/from Locked to Finished/stake,144761110,375734,6512 +Agora/Proposal/validator/advancing/with 1 cosigners and 2 effects/illegal/advance finished proposals/(negative test)/stake,144038574,373470,6509 +Agora/Proposal/validator/advancing/with 1 cosigners and 2 effects/illegal/advance finished proposals/(negative test)/stake,144761110,375734,6516 +Agora/Proposal/validator/advancing/with 1 cosigners and 2 effects/illegal/advance finished proposals/(negative test)/stake,201040711,510637,7669 +Agora/Proposal/validator/advancing/with 1 cosigners and 2 effects/illegal/advance finished proposals/(negative test)/authority,15875303,48540,4019 +Agora/Proposal/validator/advancing/with 1 cosigners and 2 effects/illegal/insufficient cosigns/stake,144038574,373470,6509 +Agora/Proposal/validator/advancing/with 1 cosigners and 2 effects/illegal/insufficient votes/stake,144761110,375734,6512 +Agora/Proposal/validator/advancing/with 1 cosigners and 2 effects/illegal/ambiguous winning effect/stake,144761110,375734,6524 +Agora/Proposal/validator/advancing/with 1 cosigners and 2 effects/illegal/to next state too late/from Draft/stake,144038574,373470,6511 +Agora/Proposal/validator/advancing/with 1 cosigners and 2 effects/illegal/to next state too late/from VotingReady/stake,144761110,375734,6516 +Agora/Proposal/validator/advancing/with 1 cosigners and 2 effects/illegal/to next state too late/from Locked/stake,201040711,510637,7669 +Agora/Proposal/validator/advancing/with 1 cosigners and 2 effects/illegal/to next state too late/from Locked/governor,514789615,1314031,11627 +Agora/Proposal/validator/advancing/with 1 cosigners and 2 effects/illegal/to next state too late/from Locked/authority,15875303,48540,4019 +Agora/Proposal/validator/advancing/with 1 cosigners and 2 effects/illegal/altered output stake datum/from Locked/governor,514789615,1314031,11628 +Agora/Proposal/validator/advancing/with 1 cosigners and 2 effects/illegal/altered output stake datum/from Locked/authority,15875303,48540,4020 +Agora/Proposal/validator/advancing/with 1 cosigners and 2 effects/illegal/forget to mint GATs/proposal,412721877,1123806,11068 +Agora/Proposal/validator/advancing/with 1 cosigners and 2 effects/illegal/forget to mint GATs/stake,187940552,485026,6957 +Agora/Proposal/validator/advancing/with 1 cosigners and 2 effects/illegal/mint GATs for wrong validators/proposal,445056605,1220618,12007 +Agora/Proposal/validator/advancing/with 1 cosigners and 2 effects/illegal/mint GATs for wrong validators/stake,204588820,517864,7896 +Agora/Proposal/validator/advancing/with 1 cosigners and 2 effects/illegal/mint GATs for wrong validators/authority,17699300,53602,4246 +Agora/Proposal/validator/advancing/with 1 cosigners and 2 effects/illegal/mint GATs with bad token name/proposal,436972923,1196415,11601 +Agora/Proposal/validator/advancing/with 1 cosigners and 2 effects/illegal/mint GATs with bad token name/stake,201040711,510637,7490 +Agora/Proposal/validator/advancing/with 1 cosigners and 2 effects/illegal/wrong GAT datum/proposal,436972923,1196415,11774 +Agora/Proposal/validator/advancing/with 1 cosigners and 2 effects/illegal/wrong GAT datum/stake,201040711,510637,7663 +Agora/Proposal/validator/advancing/with 1 cosigners and 2 effects/illegal/wrong GAT datum/authority,15875303,48540,4013 +Agora/Proposal/validator/advancing/with 1 cosigners and 2 effects/illegal/invalid governor output datum/proposal,436972923,1196415,11780 +Agora/Proposal/validator/advancing/with 1 cosigners and 2 effects/illegal/invalid governor output datum/stake,201040711,510637,7669 +Agora/Proposal/validator/advancing/with 1 cosigners and 2 effects/illegal/invalid governor output datum/authority,15875303,48540,4019 +Agora/Proposal/validator/advancing/with 1 cosigners and 5 effects/legal/to next state/from Draft to VotingReady/proposal,482688086,1307638,12390 +Agora/Proposal/validator/advancing/with 1 cosigners and 5 effects/legal/to next state/from Draft to VotingReady/stake,144038574,373470,7690 +Agora/Proposal/validator/advancing/with 1 cosigners and 5 effects/legal/to next state/from VotingReady to Locked/proposal,543702595,1463174,12399 +Agora/Proposal/validator/advancing/with 1 cosigners and 5 effects/legal/to next state/from VotingReady to Locked/stake,144761110,375734,7697 +Agora/Proposal/validator/advancing/with 1 cosigners and 5 effects/legal/to next state/from Locked to Finished/proposal,578824044,1563219,13551 +Agora/Proposal/validator/advancing/with 1 cosigners and 5 effects/legal/to next state/from Locked to Finished/stake,201040711,510637,8849 +Agora/Proposal/validator/advancing/with 1 cosigners and 5 effects/legal/to next state/from Locked to Finished/governor,576426487,1481542,12807 +Agora/Proposal/validator/advancing/with 1 cosigners and 5 effects/legal/to next state/from Locked to Finished/authority,15875303,48540,5199 +Agora/Proposal/validator/advancing/with 1 cosigners and 5 effects/legal/to failed state/from Draft to Finished/proposal,479895350,1301725,12392 +Agora/Proposal/validator/advancing/with 1 cosigners and 5 effects/legal/to failed state/from Draft to Finished/stake,144761110,375734,7692 +Agora/Proposal/validator/advancing/with 1 cosigners and 5 effects/legal/to failed state/from VotingReady to Finished/proposal,516539587,1388487,12393 +Agora/Proposal/validator/advancing/with 1 cosigners and 5 effects/legal/to failed state/from VotingReady to Finished/stake,144761110,375734,7693 +Agora/Proposal/validator/advancing/with 1 cosigners and 5 effects/legal/to failed state/from Locked to Finished/proposal,518801543,1393295,12393 +Agora/Proposal/validator/advancing/with 1 cosigners and 5 effects/legal/to failed state/from Locked to Finished/stake,144761110,375734,7693 +Agora/Proposal/validator/advancing/with 1 cosigners and 5 effects/illegal/advance finished proposals/(negative test)/stake,144038574,373470,7690 +Agora/Proposal/validator/advancing/with 1 cosigners and 5 effects/illegal/advance finished proposals/(negative test)/stake,144761110,375734,7697 +Agora/Proposal/validator/advancing/with 1 cosigners and 5 effects/illegal/advance finished proposals/(negative test)/stake,201040711,510637,8849 +Agora/Proposal/validator/advancing/with 1 cosigners and 5 effects/illegal/advance finished proposals/(negative test)/authority,15875303,48540,5199 +Agora/Proposal/validator/advancing/with 1 cosigners and 5 effects/illegal/insufficient cosigns/stake,144038574,373470,7690 +Agora/Proposal/validator/advancing/with 1 cosigners and 5 effects/illegal/insufficient votes/stake,144761110,375734,7693 +Agora/Proposal/validator/advancing/with 1 cosigners and 5 effects/illegal/ambiguous winning effect/stake,144761110,375734,7717 +Agora/Proposal/validator/advancing/with 1 cosigners and 5 effects/illegal/to next state too late/from Draft/stake,144038574,373470,7692 +Agora/Proposal/validator/advancing/with 1 cosigners and 5 effects/illegal/to next state too late/from VotingReady/stake,144761110,375734,7697 +Agora/Proposal/validator/advancing/with 1 cosigners and 5 effects/illegal/to next state too late/from Locked/stake,201040711,510637,8849 +Agora/Proposal/validator/advancing/with 1 cosigners and 5 effects/illegal/to next state too late/from Locked/governor,576426487,1481542,12807 +Agora/Proposal/validator/advancing/with 1 cosigners and 5 effects/illegal/to next state too late/from Locked/authority,15875303,48540,5199 +Agora/Proposal/validator/advancing/with 1 cosigners and 5 effects/illegal/altered output stake datum/from Locked/governor,576426487,1481542,12808 +Agora/Proposal/validator/advancing/with 1 cosigners and 5 effects/illegal/altered output stake datum/from Locked/authority,15875303,48540,5200 +Agora/Proposal/validator/advancing/with 1 cosigners and 5 effects/illegal/forget to mint GATs/proposal,554572998,1490610,12840 +Agora/Proposal/validator/advancing/with 1 cosigners and 5 effects/illegal/forget to mint GATs/stake,187940552,485026,8138 +Agora/Proposal/validator/advancing/with 1 cosigners and 5 effects/illegal/mint GATs for wrong validators/proposal,586907726,1587422,13778 +Agora/Proposal/validator/advancing/with 1 cosigners and 5 effects/illegal/mint GATs for wrong validators/stake,204588820,517864,9076 +Agora/Proposal/validator/advancing/with 1 cosigners and 5 effects/illegal/mint GATs for wrong validators/authority,17699300,53602,5426 +Agora/Proposal/validator/advancing/with 1 cosigners and 5 effects/illegal/mint GATs with bad token name/proposal,578824044,1563219,13373 +Agora/Proposal/validator/advancing/with 1 cosigners and 5 effects/illegal/mint GATs with bad token name/stake,201040711,510637,8671 +Agora/Proposal/validator/advancing/with 1 cosigners and 5 effects/illegal/wrong GAT datum/proposal,578824044,1563219,13545 +Agora/Proposal/validator/advancing/with 1 cosigners and 5 effects/illegal/wrong GAT datum/stake,201040711,510637,8843 +Agora/Proposal/validator/advancing/with 1 cosigners and 5 effects/illegal/wrong GAT datum/authority,15875303,48540,5193 +Agora/Proposal/validator/advancing/with 1 cosigners and 5 effects/illegal/invalid governor output datum/proposal,578824044,1563219,13551 +Agora/Proposal/validator/advancing/with 1 cosigners and 5 effects/illegal/invalid governor output datum/stake,201040711,510637,8849 +Agora/Proposal/validator/advancing/with 1 cosigners and 5 effects/illegal/invalid governor output datum/authority,15875303,48540,5199 +Agora/Proposal/validator/advancing/with 5 cosigners and 1 effects/legal/to next state/from Draft to VotingReady/proposal,677995493,1927471,12799 +Agora/Proposal/validator/advancing/with 5 cosigners and 1 effects/legal/to next state/from Draft to VotingReady/stake,582713892,1530532,8765 +Agora/Proposal/validator/advancing/with 5 cosigners and 1 effects/legal/to next state/from VotingReady to Locked/proposal,362157571,996214,10395 +Agora/Proposal/validator/advancing/with 5 cosigners and 1 effects/legal/to next state/from VotingReady to Locked/stake,144761110,375734,6359 +Agora/Proposal/validator/advancing/with 5 cosigners and 1 effects/legal/to next state/from Locked to Finished/proposal,412058564,1136211,11547 +Agora/Proposal/validator/advancing/with 5 cosigners and 1 effects/legal/to next state/from Locked to Finished/stake,201040711,510637,7511 +Agora/Proposal/validator/advancing/with 5 cosigners and 1 effects/legal/to next state/from Locked to Finished/governor,501431939,1278882,11470 +Agora/Proposal/validator/advancing/with 5 cosigners and 1 effects/legal/to next state/from Locked to Finished/authority,15875303,48540,3862 +Agora/Proposal/validator/advancing/with 5 cosigners and 1 effects/legal/to failed state/from Draft to Finished/proposal,313129870,874717,10388 +Agora/Proposal/validator/advancing/with 5 cosigners and 1 effects/legal/to failed state/from Draft to Finished/stake,144761110,375734,6354 +Agora/Proposal/validator/advancing/with 5 cosigners and 1 effects/legal/to failed state/from VotingReady to Finished/proposal,349774107,961479,10389 +Agora/Proposal/validator/advancing/with 5 cosigners and 1 effects/legal/to failed state/from VotingReady to Finished/stake,144761110,375734,6355 +Agora/Proposal/validator/advancing/with 5 cosigners and 1 effects/legal/to failed state/from Locked to Finished/proposal,352036063,966287,10389 +Agora/Proposal/validator/advancing/with 5 cosigners and 1 effects/legal/to failed state/from Locked to Finished/stake,144761110,375734,6355 +Agora/Proposal/validator/advancing/with 5 cosigners and 1 effects/illegal/advance finished proposals/(negative test)/stake,582713892,1530532,8765 +Agora/Proposal/validator/advancing/with 5 cosigners and 1 effects/illegal/advance finished proposals/(negative test)/stake,144761110,375734,6359 +Agora/Proposal/validator/advancing/with 5 cosigners and 1 effects/illegal/advance finished proposals/(negative test)/stake,201040711,510637,7511 +Agora/Proposal/validator/advancing/with 5 cosigners and 1 effects/illegal/advance finished proposals/(negative test)/authority,15875303,48540,3862 +Agora/Proposal/validator/advancing/with 5 cosigners and 1 effects/illegal/insufficient cosigns/stake,568599606,1489522,8765 +Agora/Proposal/validator/advancing/with 5 cosigners and 1 effects/illegal/insufficient votes/stake,144761110,375734,6355 +Agora/Proposal/validator/advancing/with 5 cosigners and 1 effects/illegal/ambiguous winning effect/stake,144761110,375734,6363 +Agora/Proposal/validator/advancing/with 5 cosigners and 1 effects/illegal/to next state too late/from Draft/stake,582713892,1530532,8767 +Agora/Proposal/validator/advancing/with 5 cosigners and 1 effects/illegal/to next state too late/from VotingReady/stake,144761110,375734,6359 +Agora/Proposal/validator/advancing/with 5 cosigners and 1 effects/illegal/to next state too late/from Locked/stake,201040711,510637,7511 +Agora/Proposal/validator/advancing/with 5 cosigners and 1 effects/illegal/to next state too late/from Locked/governor,501431939,1278882,11470 +Agora/Proposal/validator/advancing/with 5 cosigners and 1 effects/illegal/to next state too late/from Locked/authority,15875303,48540,3862 +Agora/Proposal/validator/advancing/with 5 cosigners and 1 effects/illegal/altered output stake datum/from Locked/governor,501431939,1278882,11471 +Agora/Proposal/validator/advancing/with 5 cosigners and 1 effects/illegal/altered output stake datum/from Locked/authority,15875303,48540,3863 +Agora/Proposal/validator/advancing/with 5 cosigners and 1 effects/illegal/forget to mint GATs/proposal,387807518,1063602,10835 +Agora/Proposal/validator/advancing/with 5 cosigners and 1 effects/illegal/forget to mint GATs/stake,187940552,485026,6799 +Agora/Proposal/validator/advancing/with 5 cosigners and 1 effects/illegal/mint GATs for wrong validators/proposal,420142246,1160414,11774 +Agora/Proposal/validator/advancing/with 5 cosigners and 1 effects/illegal/mint GATs for wrong validators/stake,204588820,517864,7738 +Agora/Proposal/validator/advancing/with 5 cosigners and 1 effects/illegal/mint GATs for wrong validators/authority,17699300,53602,4089 +Agora/Proposal/validator/advancing/with 5 cosigners and 1 effects/illegal/mint GATs with bad token name/proposal,412058564,1136211,11369 +Agora/Proposal/validator/advancing/with 5 cosigners and 1 effects/illegal/mint GATs with bad token name/stake,201040711,510637,7333 +Agora/Proposal/validator/advancing/with 5 cosigners and 1 effects/illegal/wrong GAT datum/proposal,412058564,1136211,11541 +Agora/Proposal/validator/advancing/with 5 cosigners and 1 effects/illegal/wrong GAT datum/stake,201040711,510637,7505 +Agora/Proposal/validator/advancing/with 5 cosigners and 1 effects/illegal/wrong GAT datum/authority,15875303,48540,3856 +Agora/Proposal/validator/advancing/with 5 cosigners and 1 effects/illegal/invalid governor output datum/proposal,412058564,1136211,11547 +Agora/Proposal/validator/advancing/with 5 cosigners and 1 effects/illegal/invalid governor output datum/stake,201040711,510637,7511 +Agora/Proposal/validator/advancing/with 5 cosigners and 1 effects/illegal/invalid governor output datum/authority,15875303,48540,3862 +Agora/Proposal/validator/advancing/with 5 cosigners and 2 effects/legal/to next state/from Draft to VotingReady/proposal,725279200,2049739,13390 +Agora/Proposal/validator/advancing/with 5 cosigners and 2 effects/legal/to next state/from Draft to VotingReady/stake,582713892,1530532,9159 +Agora/Proposal/validator/advancing/with 5 cosigners and 2 effects/legal/to next state/from VotingReady to Locked/proposal,413136164,1128470,10985 +Agora/Proposal/validator/advancing/with 5 cosigners and 2 effects/legal/to next state/from VotingReady to Locked/stake,144761110,375734,6752 +Agora/Proposal/validator/advancing/with 5 cosigners and 2 effects/legal/to next state/from Locked to Finished/proposal,459342271,1258479,12138 +Agora/Proposal/validator/advancing/with 5 cosigners and 2 effects/legal/to next state/from Locked to Finished/stake,201040711,510637,7905 +Agora/Proposal/validator/advancing/with 5 cosigners and 2 effects/legal/to next state/from Locked to Finished/governor,521977563,1334719,11864 +Agora/Proposal/validator/advancing/with 5 cosigners and 2 effects/legal/to next state/from Locked to Finished/authority,15875303,48540,4256 +Agora/Proposal/validator/advancing/with 5 cosigners and 2 effects/legal/to failed state/from Draft to Finished/proposal,360413577,996985,10978 +Agora/Proposal/validator/advancing/with 5 cosigners and 2 effects/legal/to failed state/from Draft to Finished/stake,144761110,375734,6747 +Agora/Proposal/validator/advancing/with 5 cosigners and 2 effects/legal/to failed state/from VotingReady to Finished/proposal,397057814,1083747,10979 +Agora/Proposal/validator/advancing/with 5 cosigners and 2 effects/legal/to failed state/from VotingReady to Finished/stake,144761110,375734,6748 +Agora/Proposal/validator/advancing/with 5 cosigners and 2 effects/legal/to failed state/from Locked to Finished/proposal,399319770,1088555,10979 +Agora/Proposal/validator/advancing/with 5 cosigners and 2 effects/legal/to failed state/from Locked to Finished/stake,144761110,375734,6748 +Agora/Proposal/validator/advancing/with 5 cosigners and 2 effects/illegal/advance finished proposals/(negative test)/stake,582713892,1530532,9159 +Agora/Proposal/validator/advancing/with 5 cosigners and 2 effects/illegal/advance finished proposals/(negative test)/stake,144761110,375734,6752 +Agora/Proposal/validator/advancing/with 5 cosigners and 2 effects/illegal/advance finished proposals/(negative test)/stake,201040711,510637,7905 +Agora/Proposal/validator/advancing/with 5 cosigners and 2 effects/illegal/advance finished proposals/(negative test)/authority,15875303,48540,4256 +Agora/Proposal/validator/advancing/with 5 cosigners and 2 effects/illegal/insufficient cosigns/stake,568599606,1489522,9159 +Agora/Proposal/validator/advancing/with 5 cosigners and 2 effects/illegal/insufficient votes/stake,144761110,375734,6748 +Agora/Proposal/validator/advancing/with 5 cosigners and 2 effects/illegal/ambiguous winning effect/stake,144761110,375734,6760 +Agora/Proposal/validator/advancing/with 5 cosigners and 2 effects/illegal/to next state too late/from Draft/stake,582713892,1530532,9161 +Agora/Proposal/validator/advancing/with 5 cosigners and 2 effects/illegal/to next state too late/from VotingReady/stake,144761110,375734,6752 +Agora/Proposal/validator/advancing/with 5 cosigners and 2 effects/illegal/to next state too late/from Locked/stake,201040711,510637,7905 +Agora/Proposal/validator/advancing/with 5 cosigners and 2 effects/illegal/to next state too late/from Locked/governor,521977563,1334719,11864 +Agora/Proposal/validator/advancing/with 5 cosigners and 2 effects/illegal/to next state too late/from Locked/authority,15875303,48540,4256 +Agora/Proposal/validator/advancing/with 5 cosigners and 2 effects/illegal/altered output stake datum/from Locked/governor,521977563,1334719,11865 +Agora/Proposal/validator/advancing/with 5 cosigners and 2 effects/illegal/altered output stake datum/from Locked/authority,15875303,48540,4257 +Agora/Proposal/validator/advancing/with 5 cosigners and 2 effects/illegal/forget to mint GATs/proposal,435091225,1185870,11426 +Agora/Proposal/validator/advancing/with 5 cosigners and 2 effects/illegal/forget to mint GATs/stake,187940552,485026,7193 +Agora/Proposal/validator/advancing/with 5 cosigners and 2 effects/illegal/mint GATs for wrong validators/proposal,467425953,1282682,12365 +Agora/Proposal/validator/advancing/with 5 cosigners and 2 effects/illegal/mint GATs for wrong validators/stake,204588820,517864,8132 +Agora/Proposal/validator/advancing/with 5 cosigners and 2 effects/illegal/mint GATs for wrong validators/authority,17699300,53602,4483 +Agora/Proposal/validator/advancing/with 5 cosigners and 2 effects/illegal/mint GATs with bad token name/proposal,459342271,1258479,11959 +Agora/Proposal/validator/advancing/with 5 cosigners and 2 effects/illegal/mint GATs with bad token name/stake,201040711,510637,7726 +Agora/Proposal/validator/advancing/with 5 cosigners and 2 effects/illegal/wrong GAT datum/proposal,459342271,1258479,12132 +Agora/Proposal/validator/advancing/with 5 cosigners and 2 effects/illegal/wrong GAT datum/stake,201040711,510637,7899 +Agora/Proposal/validator/advancing/with 5 cosigners and 2 effects/illegal/wrong GAT datum/authority,15875303,48540,4250 +Agora/Proposal/validator/advancing/with 5 cosigners and 2 effects/illegal/invalid governor output datum/proposal,459342271,1258479,12138 +Agora/Proposal/validator/advancing/with 5 cosigners and 2 effects/illegal/invalid governor output datum/stake,201040711,510637,7905 +Agora/Proposal/validator/advancing/with 5 cosigners and 2 effects/illegal/invalid governor output datum/authority,15875303,48540,4256 +Agora/Proposal/validator/advancing/with 5 cosigners and 5 effects/legal/to next state/from Draft to VotingReady/proposal,867130321,2416543,15160 +Agora/Proposal/validator/advancing/with 5 cosigners and 5 effects/legal/to next state/from Draft to VotingReady/stake,582713892,1530532,10339 +Agora/Proposal/validator/advancing/with 5 cosigners and 5 effects/legal/to next state/from VotingReady to Locked/proposal,566071943,1525238,12756 +Agora/Proposal/validator/advancing/with 5 cosigners and 5 effects/legal/to next state/from VotingReady to Locked/stake,144761110,375734,7933 +Agora/Proposal/validator/advancing/with 5 cosigners and 5 effects/legal/to next state/from Locked to Finished/proposal,601193392,1625283,13908 +Agora/Proposal/validator/advancing/with 5 cosigners and 5 effects/legal/to next state/from Locked to Finished/stake,201040711,510637,9085 +Agora/Proposal/validator/advancing/with 5 cosigners and 5 effects/legal/to next state/from Locked to Finished/governor,583614435,1502230,13044 +Agora/Proposal/validator/advancing/with 5 cosigners and 5 effects/legal/to next state/from Locked to Finished/authority,15875303,48540,5436 +Agora/Proposal/validator/advancing/with 5 cosigners and 5 effects/legal/to failed state/from Draft to Finished/proposal,502264698,1363789,12749 +Agora/Proposal/validator/advancing/with 5 cosigners and 5 effects/legal/to failed state/from Draft to Finished/stake,144761110,375734,7928 +Agora/Proposal/validator/advancing/with 5 cosigners and 5 effects/legal/to failed state/from VotingReady to Finished/proposal,538908935,1450551,12750 +Agora/Proposal/validator/advancing/with 5 cosigners and 5 effects/legal/to failed state/from VotingReady to Finished/stake,144761110,375734,7929 +Agora/Proposal/validator/advancing/with 5 cosigners and 5 effects/legal/to failed state/from Locked to Finished/proposal,541170891,1455359,12750 +Agora/Proposal/validator/advancing/with 5 cosigners and 5 effects/legal/to failed state/from Locked to Finished/stake,144761110,375734,7929 +Agora/Proposal/validator/advancing/with 5 cosigners and 5 effects/illegal/advance finished proposals/(negative test)/stake,582713892,1530532,10339 +Agora/Proposal/validator/advancing/with 5 cosigners and 5 effects/illegal/advance finished proposals/(negative test)/stake,144761110,375734,7933 +Agora/Proposal/validator/advancing/with 5 cosigners and 5 effects/illegal/advance finished proposals/(negative test)/stake,201040711,510637,9085 +Agora/Proposal/validator/advancing/with 5 cosigners and 5 effects/illegal/advance finished proposals/(negative test)/authority,15875303,48540,5436 +Agora/Proposal/validator/advancing/with 5 cosigners and 5 effects/illegal/insufficient cosigns/stake,568599606,1489522,10339 +Agora/Proposal/validator/advancing/with 5 cosigners and 5 effects/illegal/insufficient votes/stake,144761110,375734,7929 +Agora/Proposal/validator/advancing/with 5 cosigners and 5 effects/illegal/ambiguous winning effect/stake,144761110,375734,7953 +Agora/Proposal/validator/advancing/with 5 cosigners and 5 effects/illegal/to next state too late/from Draft/stake,582713892,1530532,10341 +Agora/Proposal/validator/advancing/with 5 cosigners and 5 effects/illegal/to next state too late/from VotingReady/stake,144761110,375734,7933 +Agora/Proposal/validator/advancing/with 5 cosigners and 5 effects/illegal/to next state too late/from Locked/stake,201040711,510637,9085 +Agora/Proposal/validator/advancing/with 5 cosigners and 5 effects/illegal/to next state too late/from Locked/governor,583614435,1502230,13044 +Agora/Proposal/validator/advancing/with 5 cosigners and 5 effects/illegal/to next state too late/from Locked/authority,15875303,48540,5436 +Agora/Proposal/validator/advancing/with 5 cosigners and 5 effects/illegal/altered output stake datum/from Locked/governor,583614435,1502230,13045 +Agora/Proposal/validator/advancing/with 5 cosigners and 5 effects/illegal/altered output stake datum/from Locked/authority,15875303,48540,5437 +Agora/Proposal/validator/advancing/with 5 cosigners and 5 effects/illegal/forget to mint GATs/proposal,576942346,1552674,13197 +Agora/Proposal/validator/advancing/with 5 cosigners and 5 effects/illegal/forget to mint GATs/stake,187940552,485026,8374 +Agora/Proposal/validator/advancing/with 5 cosigners and 5 effects/illegal/mint GATs for wrong validators/proposal,609277074,1649486,14135 +Agora/Proposal/validator/advancing/with 5 cosigners and 5 effects/illegal/mint GATs for wrong validators/stake,204588820,517864,9312 +Agora/Proposal/validator/advancing/with 5 cosigners and 5 effects/illegal/mint GATs for wrong validators/authority,17699300,53602,5663 +Agora/Proposal/validator/advancing/with 5 cosigners and 5 effects/illegal/mint GATs with bad token name/proposal,601193392,1625283,13730 +Agora/Proposal/validator/advancing/with 5 cosigners and 5 effects/illegal/mint GATs with bad token name/stake,201040711,510637,8907 +Agora/Proposal/validator/advancing/with 5 cosigners and 5 effects/illegal/wrong GAT datum/proposal,601193392,1625283,13902 +Agora/Proposal/validator/advancing/with 5 cosigners and 5 effects/illegal/wrong GAT datum/stake,201040711,510637,9079 +Agora/Proposal/validator/advancing/with 5 cosigners and 5 effects/illegal/wrong GAT datum/authority,15875303,48540,5430 +Agora/Proposal/validator/advancing/with 5 cosigners and 5 effects/illegal/invalid governor output datum/proposal,601193392,1625283,13908 +Agora/Proposal/validator/advancing/with 5 cosigners and 5 effects/illegal/invalid governor output datum/stake,201040711,510637,9085 +Agora/Proposal/validator/advancing/with 5 cosigners and 5 effects/illegal/invalid governor output datum/authority,15875303,48540,5436 +Agora/Proposal/validator/advancing/with 10 cosigners and 1 effects/legal/to next state/from Draft to VotingReady/proposal,1245892718,3569074,16268 +Agora/Proposal/validator/advancing/with 10 cosigners and 1 effects/legal/to next state/from Draft to VotingReady/stake,1243243041,3300429,12083 +Agora/Proposal/validator/advancing/with 10 cosigners and 1 effects/legal/to next state/from VotingReady to Locked/proposal,390119256,1073794,10847 +Agora/Proposal/validator/advancing/with 10 cosigners and 1 effects/legal/to next state/from VotingReady to Locked/stake,144761110,375734,6660 +Agora/Proposal/validator/advancing/with 10 cosigners and 1 effects/legal/to next state/from Locked to Finished/proposal,440020249,1213791,11999 +Agora/Proposal/validator/advancing/with 10 cosigners and 1 effects/legal/to next state/from Locked to Finished/stake,201040711,510637,7812 +Agora/Proposal/validator/advancing/with 10 cosigners and 1 effects/legal/to next state/from Locked to Finished/governor,510416874,1304742,11771 +Agora/Proposal/validator/advancing/with 10 cosigners and 1 effects/legal/to next state/from Locked to Finished/authority,15875303,48540,4163 +Agora/Proposal/validator/advancing/with 10 cosigners and 1 effects/legal/to failed state/from Draft to Finished/proposal,341091555,952297,10840 +Agora/Proposal/validator/advancing/with 10 cosigners and 1 effects/legal/to failed state/from Draft to Finished/stake,144761110,375734,6655 +Agora/Proposal/validator/advancing/with 10 cosigners and 1 effects/legal/to failed state/from VotingReady to Finished/proposal,377735792,1039059,10841 +Agora/Proposal/validator/advancing/with 10 cosigners and 1 effects/legal/to failed state/from VotingReady to Finished/stake,144761110,375734,6656 +Agora/Proposal/validator/advancing/with 10 cosigners and 1 effects/legal/to failed state/from Locked to Finished/proposal,379997748,1043867,10841 +Agora/Proposal/validator/advancing/with 10 cosigners and 1 effects/legal/to failed state/from Locked to Finished/stake,144761110,375734,6656 +Agora/Proposal/validator/advancing/with 10 cosigners and 1 effects/illegal/advance finished proposals/(negative test)/stake,1243243041,3300429,12083 +Agora/Proposal/validator/advancing/with 10 cosigners and 1 effects/illegal/advance finished proposals/(negative test)/stake,144761110,375734,6660 +Agora/Proposal/validator/advancing/with 10 cosigners and 1 effects/illegal/advance finished proposals/(negative test)/stake,201040711,510637,7812 +Agora/Proposal/validator/advancing/with 10 cosigners and 1 effects/illegal/advance finished proposals/(negative test)/authority,15875303,48540,4163 +Agora/Proposal/validator/advancing/with 10 cosigners and 1 effects/illegal/insufficient cosigns/stake,1257357327,3341439,12083 +Agora/Proposal/validator/advancing/with 10 cosigners and 1 effects/illegal/insufficient votes/stake,144761110,375734,6656 +Agora/Proposal/validator/advancing/with 10 cosigners and 1 effects/illegal/ambiguous winning effect/stake,144761110,375734,6664 +Agora/Proposal/validator/advancing/with 10 cosigners and 1 effects/illegal/to next state too late/from Draft/stake,1243243041,3300429,12085 +Agora/Proposal/validator/advancing/with 10 cosigners and 1 effects/illegal/to next state too late/from VotingReady/stake,144761110,375734,6660 +Agora/Proposal/validator/advancing/with 10 cosigners and 1 effects/illegal/to next state too late/from Locked/stake,201040711,510637,7812 +Agora/Proposal/validator/advancing/with 10 cosigners and 1 effects/illegal/to next state too late/from Locked/governor,510416874,1304742,11771 +Agora/Proposal/validator/advancing/with 10 cosigners and 1 effects/illegal/to next state too late/from Locked/authority,15875303,48540,4163 +Agora/Proposal/validator/advancing/with 10 cosigners and 1 effects/illegal/altered output stake datum/from Locked/governor,510416874,1304742,11772 +Agora/Proposal/validator/advancing/with 10 cosigners and 1 effects/illegal/altered output stake datum/from Locked/authority,15875303,48540,4164 +Agora/Proposal/validator/advancing/with 10 cosigners and 1 effects/illegal/forget to mint GATs/proposal,415769203,1141182,11288 +Agora/Proposal/validator/advancing/with 10 cosigners and 1 effects/illegal/forget to mint GATs/stake,187940552,485026,7101 +Agora/Proposal/validator/advancing/with 10 cosigners and 1 effects/illegal/mint GATs for wrong validators/proposal,448103931,1237994,12226 +Agora/Proposal/validator/advancing/with 10 cosigners and 1 effects/illegal/mint GATs for wrong validators/stake,204588820,517864,8039 +Agora/Proposal/validator/advancing/with 10 cosigners and 1 effects/illegal/mint GATs for wrong validators/authority,17699300,53602,4390 +Agora/Proposal/validator/advancing/with 10 cosigners and 1 effects/illegal/mint GATs with bad token name/proposal,440020249,1213791,11821 +Agora/Proposal/validator/advancing/with 10 cosigners and 1 effects/illegal/mint GATs with bad token name/stake,201040711,510637,7634 +Agora/Proposal/validator/advancing/with 10 cosigners and 1 effects/illegal/wrong GAT datum/proposal,440020249,1213791,11993 +Agora/Proposal/validator/advancing/with 10 cosigners and 1 effects/illegal/wrong GAT datum/stake,201040711,510637,7806 +Agora/Proposal/validator/advancing/with 10 cosigners and 1 effects/illegal/wrong GAT datum/authority,15875303,48540,4157 +Agora/Proposal/validator/advancing/with 10 cosigners and 1 effects/illegal/invalid governor output datum/proposal,440020249,1213791,11999 +Agora/Proposal/validator/advancing/with 10 cosigners and 1 effects/illegal/invalid governor output datum/stake,201040711,510637,7812 +Agora/Proposal/validator/advancing/with 10 cosigners and 1 effects/illegal/invalid governor output datum/authority,15875303,48540,4163 +Agora/Proposal/validator/advancing/with 10 cosigners and 2 effects/legal/to next state/from Draft to VotingReady/proposal,1293176425,3691342,16858 +Agora/Proposal/validator/advancing/with 10 cosigners and 2 effects/legal/to next state/from Draft to VotingReady/stake,1243243041,3300429,12477 +Agora/Proposal/validator/advancing/with 10 cosigners and 2 effects/legal/to next state/from VotingReady to Locked/proposal,441097849,1206050,11436 +Agora/Proposal/validator/advancing/with 10 cosigners and 2 effects/legal/to next state/from VotingReady to Locked/stake,144761110,375734,7053 +Agora/Proposal/validator/advancing/with 10 cosigners and 2 effects/legal/to next state/from Locked to Finished/proposal,487303956,1336059,12589 +Agora/Proposal/validator/advancing/with 10 cosigners and 2 effects/legal/to next state/from Locked to Finished/stake,201040711,510637,8206 +Agora/Proposal/validator/advancing/with 10 cosigners and 2 effects/legal/to next state/from Locked to Finished/governor,530962498,1360579,12165 +Agora/Proposal/validator/advancing/with 10 cosigners and 2 effects/legal/to next state/from Locked to Finished/authority,15875303,48540,4557 +Agora/Proposal/validator/advancing/with 10 cosigners and 2 effects/legal/to failed state/from Draft to Finished/proposal,388375262,1074565,11429 +Agora/Proposal/validator/advancing/with 10 cosigners and 2 effects/legal/to failed state/from Draft to Finished/stake,144761110,375734,7048 +Agora/Proposal/validator/advancing/with 10 cosigners and 2 effects/legal/to failed state/from VotingReady to Finished/proposal,425019499,1161327,11430 +Agora/Proposal/validator/advancing/with 10 cosigners and 2 effects/legal/to failed state/from VotingReady to Finished/stake,144761110,375734,7049 +Agora/Proposal/validator/advancing/with 10 cosigners and 2 effects/legal/to failed state/from Locked to Finished/proposal,427281455,1166135,11430 +Agora/Proposal/validator/advancing/with 10 cosigners and 2 effects/legal/to failed state/from Locked to Finished/stake,144761110,375734,7049 +Agora/Proposal/validator/advancing/with 10 cosigners and 2 effects/illegal/advance finished proposals/(negative test)/stake,1243243041,3300429,12477 +Agora/Proposal/validator/advancing/with 10 cosigners and 2 effects/illegal/advance finished proposals/(negative test)/stake,144761110,375734,7053 +Agora/Proposal/validator/advancing/with 10 cosigners and 2 effects/illegal/advance finished proposals/(negative test)/stake,201040711,510637,8206 +Agora/Proposal/validator/advancing/with 10 cosigners and 2 effects/illegal/advance finished proposals/(negative test)/authority,15875303,48540,4557 +Agora/Proposal/validator/advancing/with 10 cosigners and 2 effects/illegal/insufficient cosigns/stake,1257357327,3341439,12477 +Agora/Proposal/validator/advancing/with 10 cosigners and 2 effects/illegal/insufficient votes/stake,144761110,375734,7049 +Agora/Proposal/validator/advancing/with 10 cosigners and 2 effects/illegal/ambiguous winning effect/stake,144761110,375734,7061 +Agora/Proposal/validator/advancing/with 10 cosigners and 2 effects/illegal/to next state too late/from Draft/stake,1243243041,3300429,12479 +Agora/Proposal/validator/advancing/with 10 cosigners and 2 effects/illegal/to next state too late/from VotingReady/stake,144761110,375734,7053 +Agora/Proposal/validator/advancing/with 10 cosigners and 2 effects/illegal/to next state too late/from Locked/stake,201040711,510637,8206 +Agora/Proposal/validator/advancing/with 10 cosigners and 2 effects/illegal/to next state too late/from Locked/governor,530962498,1360579,12165 +Agora/Proposal/validator/advancing/with 10 cosigners and 2 effects/illegal/to next state too late/from Locked/authority,15875303,48540,4557 +Agora/Proposal/validator/advancing/with 10 cosigners and 2 effects/illegal/altered output stake datum/from Locked/governor,530962498,1360579,12166 +Agora/Proposal/validator/advancing/with 10 cosigners and 2 effects/illegal/altered output stake datum/from Locked/authority,15875303,48540,4558 +Agora/Proposal/validator/advancing/with 10 cosigners and 2 effects/illegal/forget to mint GATs/proposal,463052910,1263450,11877 +Agora/Proposal/validator/advancing/with 10 cosigners and 2 effects/illegal/forget to mint GATs/stake,187940552,485026,7494 +Agora/Proposal/validator/advancing/with 10 cosigners and 2 effects/illegal/mint GATs for wrong validators/proposal,495387638,1360262,12816 +Agora/Proposal/validator/advancing/with 10 cosigners and 2 effects/illegal/mint GATs for wrong validators/stake,204588820,517864,8433 +Agora/Proposal/validator/advancing/with 10 cosigners and 2 effects/illegal/mint GATs for wrong validators/authority,17699300,53602,4784 +Agora/Proposal/validator/advancing/with 10 cosigners and 2 effects/illegal/mint GATs with bad token name/proposal,487303956,1336059,12410 +Agora/Proposal/validator/advancing/with 10 cosigners and 2 effects/illegal/mint GATs with bad token name/stake,201040711,510637,8027 +Agora/Proposal/validator/advancing/with 10 cosigners and 2 effects/illegal/wrong GAT datum/proposal,487303956,1336059,12583 +Agora/Proposal/validator/advancing/with 10 cosigners and 2 effects/illegal/wrong GAT datum/stake,201040711,510637,8200 +Agora/Proposal/validator/advancing/with 10 cosigners and 2 effects/illegal/wrong GAT datum/authority,15875303,48540,4551 +Agora/Proposal/validator/advancing/with 10 cosigners and 2 effects/illegal/invalid governor output datum/proposal,487303956,1336059,12589 +Agora/Proposal/validator/advancing/with 10 cosigners and 2 effects/illegal/invalid governor output datum/stake,201040711,510637,8206 +Agora/Proposal/validator/advancing/with 10 cosigners and 2 effects/illegal/invalid governor output datum/authority,15875303,48540,4557 +Agora/Proposal/validator/advancing/with 10 cosigners and 5 effects/legal/to next state/from Draft to VotingReady/proposal,1435027546,4058146,18629 +Agora/Proposal/validator/advancing/with 10 cosigners and 5 effects/legal/to next state/from Draft to VotingReady/stake,1243243041,3300429,13657 +Agora/Proposal/validator/advancing/with 10 cosigners and 5 effects/legal/to next state/from VotingReady to Locked/proposal,594033628,1602818,13208 +Agora/Proposal/validator/advancing/with 10 cosigners and 5 effects/legal/to next state/from VotingReady to Locked/stake,144761110,375734,8234 +Agora/Proposal/validator/advancing/with 10 cosigners and 5 effects/legal/to next state/from Locked to Finished/proposal,629155077,1702863,14361 +Agora/Proposal/validator/advancing/with 10 cosigners and 5 effects/legal/to next state/from Locked to Finished/stake,201040711,510637,9387 +Agora/Proposal/validator/advancing/with 10 cosigners and 5 effects/legal/to next state/from Locked to Finished/governor,592599370,1528090,13346 +Agora/Proposal/validator/advancing/with 10 cosigners and 5 effects/legal/to next state/from Locked to Finished/authority,15875303,48540,5738 +Agora/Proposal/validator/advancing/with 10 cosigners and 5 effects/legal/to failed state/from Draft to Finished/proposal,530226383,1441369,13201 +Agora/Proposal/validator/advancing/with 10 cosigners and 5 effects/legal/to failed state/from Draft to Finished/stake,144761110,375734,8229 +Agora/Proposal/validator/advancing/with 10 cosigners and 5 effects/legal/to failed state/from VotingReady to Finished/proposal,566870620,1528131,13202 +Agora/Proposal/validator/advancing/with 10 cosigners and 5 effects/legal/to failed state/from VotingReady to Finished/stake,144761110,375734,8230 +Agora/Proposal/validator/advancing/with 10 cosigners and 5 effects/legal/to failed state/from Locked to Finished/proposal,569132576,1532939,13202 +Agora/Proposal/validator/advancing/with 10 cosigners and 5 effects/legal/to failed state/from Locked to Finished/stake,144761110,375734,8230 +Agora/Proposal/validator/advancing/with 10 cosigners and 5 effects/illegal/advance finished proposals/(negative test)/stake,1243243041,3300429,13657 +Agora/Proposal/validator/advancing/with 10 cosigners and 5 effects/illegal/advance finished proposals/(negative test)/stake,144761110,375734,8234 +Agora/Proposal/validator/advancing/with 10 cosigners and 5 effects/illegal/advance finished proposals/(negative test)/stake,201040711,510637,9387 +Agora/Proposal/validator/advancing/with 10 cosigners and 5 effects/illegal/advance finished proposals/(negative test)/authority,15875303,48540,5738 +Agora/Proposal/validator/advancing/with 10 cosigners and 5 effects/illegal/insufficient cosigns/stake,1257357327,3341439,13657 +Agora/Proposal/validator/advancing/with 10 cosigners and 5 effects/illegal/insufficient votes/stake,144761110,375734,8230 +Agora/Proposal/validator/advancing/with 10 cosigners and 5 effects/illegal/ambiguous winning effect/stake,144761110,375734,8254 +Agora/Proposal/validator/advancing/with 10 cosigners and 5 effects/illegal/to next state too late/from Draft/stake,1243243041,3300429,13659 +Agora/Proposal/validator/advancing/with 10 cosigners and 5 effects/illegal/to next state too late/from VotingReady/stake,144761110,375734,8234 +Agora/Proposal/validator/advancing/with 10 cosigners and 5 effects/illegal/to next state too late/from Locked/stake,201040711,510637,9387 +Agora/Proposal/validator/advancing/with 10 cosigners and 5 effects/illegal/to next state too late/from Locked/governor,592599370,1528090,13346 +Agora/Proposal/validator/advancing/with 10 cosigners and 5 effects/illegal/to next state too late/from Locked/authority,15875303,48540,5738 +Agora/Proposal/validator/advancing/with 10 cosigners and 5 effects/illegal/altered output stake datum/from Locked/governor,592599370,1528090,13347 +Agora/Proposal/validator/advancing/with 10 cosigners and 5 effects/illegal/altered output stake datum/from Locked/authority,15875303,48540,5739 +Agora/Proposal/validator/advancing/with 10 cosigners and 5 effects/illegal/forget to mint GATs/proposal,604904031,1630254,13649 +Agora/Proposal/validator/advancing/with 10 cosigners and 5 effects/illegal/forget to mint GATs/stake,187940552,485026,8675 +Agora/Proposal/validator/advancing/with 10 cosigners and 5 effects/illegal/mint GATs for wrong validators/proposal,637238759,1727066,14587 +Agora/Proposal/validator/advancing/with 10 cosigners and 5 effects/illegal/mint GATs for wrong validators/stake,204588820,517864,9613 +Agora/Proposal/validator/advancing/with 10 cosigners and 5 effects/illegal/mint GATs for wrong validators/authority,17699300,53602,5964 +Agora/Proposal/validator/advancing/with 10 cosigners and 5 effects/illegal/mint GATs with bad token name/proposal,629155077,1702863,14182 +Agora/Proposal/validator/advancing/with 10 cosigners and 5 effects/illegal/mint GATs with bad token name/stake,201040711,510637,9208 +Agora/Proposal/validator/advancing/with 10 cosigners and 5 effects/illegal/wrong GAT datum/proposal,629155077,1702863,14355 +Agora/Proposal/validator/advancing/with 10 cosigners and 5 effects/illegal/wrong GAT datum/stake,201040711,510637,9381 +Agora/Proposal/validator/advancing/with 10 cosigners and 5 effects/illegal/wrong GAT datum/authority,15875303,48540,5731 +Agora/Proposal/validator/advancing/with 10 cosigners and 5 effects/illegal/invalid governor output datum/proposal,629155077,1702863,14361 +Agora/Proposal/validator/advancing/with 10 cosigners and 5 effects/illegal/invalid governor output datum/stake,201040711,510637,9387 +Agora/Proposal/validator/advancing/with 10 cosigners and 5 effects/illegal/invalid governor output datum/authority,15875303,48540,5738 +Agora/Proposal/validator/unlocking/legal/with 1 proposals/voter: retract votes while voting/stake,140863709,370195,5783 +Agora/Proposal/validator/unlocking/legal/with 1 proposals/voter: retract votes while voting/proposal,282615841,794299,9497 +Agora/Proposal/validator/unlocking/legal/with 1 proposals/voter/creator: retract votes while voting/stake,147212927,388303,5799 +Agora/Proposal/validator/unlocking/legal/with 1 proposals/voter/creator: retract votes while voting/proposal,300115413,843740,9508 +Agora/Proposal/validator/unlocking/legal/with 1 proposals/creator: remove creator locks when finished/stake,139825432,367397,5781 +Agora/Proposal/validator/unlocking/legal/with 1 proposals/creator: remove creator locks when finished/proposal,256687085,727957,9494 +Agora/Proposal/validator/unlocking/legal/with 1 proposals/voter/creator: remove all locks when finished/stake,143981681,379249,5797 +Agora/Proposal/validator/unlocking/legal/with 1 proposals/voter/creator: remove all locks when finished/proposal,264924554,752465,9506 +Agora/Proposal/validator/unlocking/legal/with 1 proposals/voter: unlock after voting/Locked/stake,140863709,370195,5787 +Agora/Proposal/validator/unlocking/legal/with 1 proposals/voter: unlock after voting/Locked/proposal,252614193,719732,9501 +Agora/Proposal/validator/unlocking/legal/with 1 proposals/voter: unlock after voting/Finished/stake,140863709,370195,5787 +Agora/Proposal/validator/unlocking/legal/with 1 proposals/voter: unlock after voting/Finished/proposal,253179682,720934,9501 +Agora/Proposal/validator/unlocking/legal/with 1 proposals/voter/creator: remove vote locks when locked/stake,147212927,388303,5803 +Agora/Proposal/validator/unlocking/legal/with 1 proposals/voter/creator: remove vote locks when locked/proposal,270679254,770375,9512 +Agora/Proposal/validator/unlocking/legal/with 5 proposals/voter: retract votes while voting/stake,297243845,781199,7876 +Agora/Proposal/validator/unlocking/legal/with 5 proposals/voter: retract votes while voting/proposal,425257089,1206963,11566 +Agora/Proposal/validator/unlocking/legal/with 5 proposals/voter/creator: retract votes while voting/stake,328989935,871739,7952 +Agora/Proposal/validator/unlocking/legal/with 5 proposals/voter/creator: retract votes while voting/proposal,494812989,1407716,11617 +Agora/Proposal/validator/unlocking/legal/with 5 proposals/creator: remove creator locks when finished/stake,292052460,767209,7865 +Agora/Proposal/validator/unlocking/legal/with 5 proposals/creator: remove creator locks when finished/proposal,364767897,1045813,11558 +Agora/Proposal/validator/unlocking/legal/with 5 proposals/voter/creator: remove all locks when finished/stake,312833705,826469,7946 +Agora/Proposal/validator/unlocking/legal/with 5 proposals/voter/creator: remove all locks when finished/proposal,402960090,1157169,11611 +Agora/Proposal/validator/unlocking/legal/with 5 proposals/voter: unlock after voting/Locked/stake,297243845,781199,7896 +Agora/Proposal/validator/unlocking/legal/with 5 proposals/voter: unlock after voting/Locked/proposal,364848113,1048780,11586 +Agora/Proposal/validator/unlocking/legal/with 5 proposals/voter: unlock after voting/Finished/stake,297243845,781199,7896 +Agora/Proposal/validator/unlocking/legal/with 5 proposals/voter: unlock after voting/Finished/proposal,365413602,1049982,11586 +Agora/Proposal/validator/unlocking/legal/with 5 proposals/voter/creator: remove vote locks when locked/stake,328989935,871739,7972 +Agora/Proposal/validator/unlocking/legal/with 5 proposals/voter/creator: remove vote locks when locked/proposal,434969502,1250735,11637 +Agora/Proposal/validator/unlocking/legal/with 10 proposals/voter: retract votes while voting/stake,492719015,1294954,10491 +Agora/Proposal/validator/unlocking/legal/with 10 proposals/voter: retract votes while voting/proposal,603558649,1722793,14151 +Agora/Proposal/validator/unlocking/legal/with 10 proposals/voter/creator: retract votes while voting/stake,556211195,1476034,10642 +Agora/Proposal/validator/unlocking/legal/with 10 proposals/voter/creator: retract votes while voting/proposal,738184959,2112686,14252 +Agora/Proposal/validator/unlocking/legal/with 10 proposals/creator: remove creator locks when finished/stake,482336245,1266974,10471 +Agora/Proposal/validator/unlocking/legal/with 10 proposals/creator: remove creator locks when finished/proposal,499868912,1443133,14139 +Agora/Proposal/validator/unlocking/legal/with 10 proposals/voter/creator: remove all locks when finished/stake,523898735,1385494,10631 +Agora/Proposal/validator/unlocking/legal/with 10 proposals/voter/creator: remove all locks when finished/proposal,575504510,1663049,14241 +Agora/Proposal/validator/unlocking/legal/with 10 proposals/voter: unlock after voting/Locked/stake,492719015,1294954,10531 +Agora/Proposal/validator/unlocking/legal/with 10 proposals/voter: unlock after voting/Locked/proposal,505140513,1460090,14191 +Agora/Proposal/validator/unlocking/legal/with 10 proposals/voter: unlock after voting/Finished/stake,492719015,1294954,10531 +Agora/Proposal/validator/unlocking/legal/with 10 proposals/voter: unlock after voting/Finished/proposal,505706002,1461292,14191 +Agora/Proposal/validator/unlocking/legal/with 10 proposals/voter/creator: remove vote locks when locked/stake,556211195,1476034,10682 +Agora/Proposal/validator/unlocking/legal/with 10 proposals/voter/creator: remove vote locks when locked/proposal,640332312,1851185,14292 +Agora/Proposal/validator/unlocking/legal/with 42 proposals/voter: retract votes while voting/stake,1743760103,4582986,27321 +Agora/Proposal/validator/unlocking/legal/with 42 proposals/voter: retract votes while voting/proposal,1744688633,5024105,30770 +Agora/Proposal/validator/unlocking/legal/with 42 proposals/voter/creator: retract votes while voting/stake,2010427259,5343522,28008 +Agora/Proposal/validator/unlocking/legal/with 42 proposals/voter/creator: retract votes while voting/proposal,2295765567,6624494,31228 +Agora/Proposal/validator/unlocking/legal/with 42 proposals/creator: remove creator locks when finished/stake,1700152469,4465470,27236 +Agora/Proposal/validator/unlocking/legal/with 42 proposals/creator: remove creator locks when finished/proposal,1364515408,3985981,30725 +Agora/Proposal/validator/unlocking/legal/with 42 proposals/voter/creator: remove all locks when finished/stake,1874714927,4963254,27947 +Agora/Proposal/validator/unlocking/legal/with 42 proposals/voter/creator: remove all locks when finished/proposal,1679788798,4900681,31167 +Agora/Proposal/validator/unlocking/legal/with 42 proposals/voter: unlock after voting/Locked/stake,1743760103,4582986,27489 +Agora/Proposal/validator/unlocking/legal/with 42 proposals/voter: unlock after voting/Locked/proposal,1403011873,4092474,30938 +Agora/Proposal/validator/unlocking/legal/with 42 proposals/voter: unlock after voting/Finished/stake,1743760103,4582986,27489 +Agora/Proposal/validator/unlocking/legal/with 42 proposals/voter: unlock after voting/Finished/proposal,1403577362,4093676,30938 +Agora/Proposal/validator/unlocking/legal/with 42 proposals/voter/creator: remove vote locks when locked/stake,2010427259,5343522,28177 +Agora/Proposal/validator/unlocking/legal/with 42 proposals/voter/creator: remove vote locks when locked/proposal,1954654296,5694065,31397 +"Agora/Proposal/validator/unlocking/illegal/with 1 proposals/retract votes while not voting/role: Voter , status: Draft/stake",140863709,370195,5783 +"Agora/Proposal/validator/unlocking/illegal/with 1 proposals/retract votes while not voting/role: Voter , status: Locked/stake",140863709,370195,5783 +"Agora/Proposal/validator/unlocking/illegal/with 1 proposals/retract votes while not voting/role: Voter , status: Finished/stake",140863709,370195,5783 +"Agora/Proposal/validator/unlocking/illegal/with 1 proposals/retract votes while not voting/role: Creator , status: Draft/stake",135454846,355547,5785 +"Agora/Proposal/validator/unlocking/illegal/with 1 proposals/retract votes while not voting/role: Creator , status: Locked/stake",135454846,355547,5785 +"Agora/Proposal/validator/unlocking/illegal/with 1 proposals/retract votes while not voting/role: Creator , status: Finished/stake",135454846,355547,5785 +"Agora/Proposal/validator/unlocking/illegal/with 1 proposals/retract votes while not voting/role: Both , status: Draft/stake",147212927,388303,5799 +"Agora/Proposal/validator/unlocking/illegal/with 1 proposals/retract votes while not voting/role: Both , status: Locked/stake",147212927,388303,5799 +"Agora/Proposal/validator/unlocking/illegal/with 1 proposals/retract votes while not voting/role: Both , status: Finished/stake",147212927,388303,5799 +"Agora/Proposal/validator/unlocking/illegal/with 1 proposals/retract votes while not voting/role: Irrelevant , status: Draft/stake",129105628,337439,5765 +"Agora/Proposal/validator/unlocking/illegal/with 1 proposals/retract votes while not voting/role: Irrelevant , status: Locked/stake",129105628,337439,5765 +"Agora/Proposal/validator/unlocking/illegal/with 1 proposals/retract votes while not voting/role: Irrelevant , status: Finished/stake",129105628,337439,5765 +Agora/Proposal/validator/unlocking/illegal/with 1 proposals/unlock an irrelevant stake/status: Draft retract votes: True/stake,129105628,337439,5765 +Agora/Proposal/validator/unlocking/illegal/with 1 proposals/unlock an irrelevant stake/status: Draft retract votes: False/stake,129105628,337439,5765 +Agora/Proposal/validator/unlocking/illegal/with 1 proposals/unlock an irrelevant stake/status: VotingReady retract votes: True/stake,129105628,337439,5765 +Agora/Proposal/validator/unlocking/illegal/with 1 proposals/unlock an irrelevant stake/status: VotingReady retract votes: False/stake,129105628,337439,5765 +Agora/Proposal/validator/unlocking/illegal/with 1 proposals/unlock an irrelevant stake/status: Locked retract votes: True/stake,129105628,337439,5765 +Agora/Proposal/validator/unlocking/illegal/with 1 proposals/unlock an irrelevant stake/status: Locked retract votes: False/stake,129105628,337439,5765 +Agora/Proposal/validator/unlocking/illegal/with 1 proposals/unlock an irrelevant stake/status: Finished retract votes: True/stake,129105628,337439,5765 +Agora/Proposal/validator/unlocking/illegal/with 1 proposals/unlock an irrelevant stake/status: Finished retract votes: False/stake,129105628,337439,5765 +Agora/Proposal/validator/unlocking/illegal/with 1 proposals/remove creator too early/status: Draft/stake,139825432,367397,5781 +Agora/Proposal/validator/unlocking/illegal/with 1 proposals/remove creator too early/status: VotingReady/stake,139825432,367397,5781 +Agora/Proposal/validator/unlocking/illegal/with 1 proposals/remove creator too early/status: Locked/stake,139825432,367397,5781 +Agora/Proposal/validator/unlocking/illegal/with 1 proposals/creator: retract votes/stake,139825432,367397,5779 +"Agora/Proposal/validator/unlocking/illegal/with 5 proposals/retract votes while not voting/role: Voter , status: Draft/stake",297243845,781199,7876 +"Agora/Proposal/validator/unlocking/illegal/with 5 proposals/retract votes while not voting/role: Voter , status: Locked/stake",297243845,781199,7876 +"Agora/Proposal/validator/unlocking/illegal/with 5 proposals/retract votes while not voting/role: Voter , status: Finished/stake",297243845,781199,7876 +"Agora/Proposal/validator/unlocking/illegal/with 5 proposals/retract votes while not voting/role: Creator , status: Draft/stake",285403194,749767,7882 +"Agora/Proposal/validator/unlocking/illegal/with 5 proposals/retract votes while not voting/role: Creator , status: Locked/stake",285403194,749767,7882 +"Agora/Proposal/validator/unlocking/illegal/with 5 proposals/retract votes while not voting/role: Creator , status: Finished/stake",285403194,749767,7882 +"Agora/Proposal/validator/unlocking/illegal/with 5 proposals/retract votes while not voting/role: Both , status: Draft/stake",328989935,871739,7952 +"Agora/Proposal/validator/unlocking/illegal/with 5 proposals/retract votes while not voting/role: Both , status: Locked/stake",328989935,871739,7952 +"Agora/Proposal/validator/unlocking/illegal/with 5 proposals/retract votes while not voting/role: Both , status: Finished/stake",328989935,871739,7952 +"Agora/Proposal/validator/unlocking/illegal/with 5 proposals/retract votes while not voting/role: Irrelevant , status: Draft/stake",253657104,659227,7793 +"Agora/Proposal/validator/unlocking/illegal/with 5 proposals/retract votes while not voting/role: Irrelevant , status: Locked/stake",253657104,659227,7793 +"Agora/Proposal/validator/unlocking/illegal/with 5 proposals/retract votes while not voting/role: Irrelevant , status: Finished/stake",253657104,659227,7793 +Agora/Proposal/validator/unlocking/illegal/with 5 proposals/unlock an irrelevant stake/status: Draft retract votes: True/stake,253657104,659227,7793 +Agora/Proposal/validator/unlocking/illegal/with 5 proposals/unlock an irrelevant stake/status: Draft retract votes: False/stake,253657104,659227,7793 +Agora/Proposal/validator/unlocking/illegal/with 5 proposals/unlock an irrelevant stake/status: VotingReady retract votes: True/stake,253657104,659227,7793 +Agora/Proposal/validator/unlocking/illegal/with 5 proposals/unlock an irrelevant stake/status: VotingReady retract votes: False/stake,253657104,659227,7793 +Agora/Proposal/validator/unlocking/illegal/with 5 proposals/unlock an irrelevant stake/status: Locked retract votes: True/stake,253657104,659227,7793 +Agora/Proposal/validator/unlocking/illegal/with 5 proposals/unlock an irrelevant stake/status: Locked retract votes: False/stake,253657104,659227,7793 +Agora/Proposal/validator/unlocking/illegal/with 5 proposals/unlock an irrelevant stake/status: Finished retract votes: True/stake,253657104,659227,7793 +Agora/Proposal/validator/unlocking/illegal/with 5 proposals/unlock an irrelevant stake/status: Finished retract votes: False/stake,253657104,659227,7793 +Agora/Proposal/validator/unlocking/illegal/with 5 proposals/remove creator too early/status: Draft/stake,292052460,767209,7865 +Agora/Proposal/validator/unlocking/illegal/with 5 proposals/remove creator too early/status: VotingReady/stake,292052460,767209,7865 +Agora/Proposal/validator/unlocking/illegal/with 5 proposals/remove creator too early/status: Locked/stake,292052460,767209,7865 +Agora/Proposal/validator/unlocking/illegal/with 5 proposals/creator: retract votes/stake,292052460,767209,7855 +"Agora/Proposal/validator/unlocking/illegal/with 10 proposals/retract votes while not voting/role: Voter , status: Draft/stake",492719015,1294954,10491 +"Agora/Proposal/validator/unlocking/illegal/with 10 proposals/retract votes while not voting/role: Voter , status: Locked/stake",492719015,1294954,10491 +"Agora/Proposal/validator/unlocking/illegal/with 10 proposals/retract votes while not voting/role: Voter , status: Finished/stake",492719015,1294954,10491 +"Agora/Proposal/validator/unlocking/illegal/with 10 proposals/retract votes while not voting/role: Creator , status: Draft/stake",472838629,1242542,10502 +"Agora/Proposal/validator/unlocking/illegal/with 10 proposals/retract votes while not voting/role: Creator , status: Locked/stake",472838629,1242542,10502 +"Agora/Proposal/validator/unlocking/illegal/with 10 proposals/retract votes while not voting/role: Creator , status: Finished/stake",472838629,1242542,10502 +"Agora/Proposal/validator/unlocking/illegal/with 10 proposals/retract votes while not voting/role: Both , status: Draft/stake",556211195,1476034,10642 +"Agora/Proposal/validator/unlocking/illegal/with 10 proposals/retract votes while not voting/role: Both , status: Locked/stake",556211195,1476034,10642 +"Agora/Proposal/validator/unlocking/illegal/with 10 proposals/retract votes while not voting/role: Both , status: Finished/stake",556211195,1476034,10642 +"Agora/Proposal/validator/unlocking/illegal/with 10 proposals/retract votes while not voting/role: Irrelevant , status: Draft/stake",409346449,1061462,10328 +"Agora/Proposal/validator/unlocking/illegal/with 10 proposals/retract votes while not voting/role: Irrelevant , status: Locked/stake",409346449,1061462,10328 +"Agora/Proposal/validator/unlocking/illegal/with 10 proposals/retract votes while not voting/role: Irrelevant , status: Finished/stake",409346449,1061462,10328 +Agora/Proposal/validator/unlocking/illegal/with 10 proposals/unlock an irrelevant stake/status: Draft retract votes: True/stake,409346449,1061462,10328 +Agora/Proposal/validator/unlocking/illegal/with 10 proposals/unlock an irrelevant stake/status: Draft retract votes: False/stake,409346449,1061462,10328 +Agora/Proposal/validator/unlocking/illegal/with 10 proposals/unlock an irrelevant stake/status: VotingReady retract votes: True/stake,409346449,1061462,10328 +Agora/Proposal/validator/unlocking/illegal/with 10 proposals/unlock an irrelevant stake/status: VotingReady retract votes: False/stake,409346449,1061462,10328 +Agora/Proposal/validator/unlocking/illegal/with 10 proposals/unlock an irrelevant stake/status: Locked retract votes: True/stake,409346449,1061462,10328 +Agora/Proposal/validator/unlocking/illegal/with 10 proposals/unlock an irrelevant stake/status: Locked retract votes: False/stake,409346449,1061462,10328 +Agora/Proposal/validator/unlocking/illegal/with 10 proposals/unlock an irrelevant stake/status: Finished retract votes: True/stake,409346449,1061462,10328 +Agora/Proposal/validator/unlocking/illegal/with 10 proposals/unlock an irrelevant stake/status: Finished retract votes: False/stake,409346449,1061462,10328 +Agora/Proposal/validator/unlocking/illegal/with 10 proposals/remove creator too early/status: Draft/stake,482336245,1266974,10471 +Agora/Proposal/validator/unlocking/illegal/with 10 proposals/remove creator too early/status: VotingReady/stake,482336245,1266974,10471 +Agora/Proposal/validator/unlocking/illegal/with 10 proposals/remove creator too early/status: Locked/stake,482336245,1266974,10471 +Agora/Proposal/validator/unlocking/illegal/with 10 proposals/creator: retract votes/stake,482336245,1266974,10450 +"Agora/Proposal/validator/unlocking/illegal/with 42 proposals/retract votes while not voting/role: Voter , status: Draft/stake",1743760103,4582986,27321 +"Agora/Proposal/validator/unlocking/illegal/with 42 proposals/retract votes while not voting/role: Voter , status: Locked/stake",1743760103,4582986,27321 +"Agora/Proposal/validator/unlocking/illegal/with 42 proposals/retract votes while not voting/role: Voter , status: Finished/stake",1743760103,4582986,27321 +"Agora/Proposal/validator/unlocking/illegal/with 42 proposals/retract votes while not voting/role: Creator , status: Draft/stake",1672425413,4396302,27382 +"Agora/Proposal/validator/unlocking/illegal/with 42 proposals/retract votes while not voting/role: Creator , status: Locked/stake",1672425413,4396302,27382 +"Agora/Proposal/validator/unlocking/illegal/with 42 proposals/retract votes while not voting/role: Creator , status: Finished/stake",1672425413,4396302,27382 +"Agora/Proposal/validator/unlocking/illegal/with 42 proposals/retract votes while not voting/role: Both , status: Draft/stake",2010427259,5343522,28008 +"Agora/Proposal/validator/unlocking/illegal/with 42 proposals/retract votes while not voting/role: Both , status: Locked/stake",2010427259,5343522,28008 +"Agora/Proposal/validator/unlocking/illegal/with 42 proposals/retract votes while not voting/role: Both , status: Finished/stake",2010427259,5343522,28008 +"Agora/Proposal/validator/unlocking/illegal/with 42 proposals/retract votes while not voting/role: Irrelevant , status: Draft/stake",1405758257,3635766,26608 +"Agora/Proposal/validator/unlocking/illegal/with 42 proposals/retract votes while not voting/role: Irrelevant , status: Locked/stake",1405758257,3635766,26608 +"Agora/Proposal/validator/unlocking/illegal/with 42 proposals/retract votes while not voting/role: Irrelevant , status: Finished/stake",1405758257,3635766,26608 +Agora/Proposal/validator/unlocking/illegal/with 42 proposals/unlock an irrelevant stake/status: Draft retract votes: True/stake,1405758257,3635766,26608 +Agora/Proposal/validator/unlocking/illegal/with 42 proposals/unlock an irrelevant stake/status: Draft retract votes: False/stake,1405758257,3635766,26608 +Agora/Proposal/validator/unlocking/illegal/with 42 proposals/unlock an irrelevant stake/status: VotingReady retract votes: True/stake,1405758257,3635766,26608 +Agora/Proposal/validator/unlocking/illegal/with 42 proposals/unlock an irrelevant stake/status: VotingReady retract votes: False/stake,1405758257,3635766,26608 +Agora/Proposal/validator/unlocking/illegal/with 42 proposals/unlock an irrelevant stake/status: Locked retract votes: True/stake,1405758257,3635766,26608 +Agora/Proposal/validator/unlocking/illegal/with 42 proposals/unlock an irrelevant stake/status: Locked retract votes: False/stake,1405758257,3635766,26608 +Agora/Proposal/validator/unlocking/illegal/with 42 proposals/unlock an irrelevant stake/status: Finished retract votes: True/stake,1405758257,3635766,26608 +Agora/Proposal/validator/unlocking/illegal/with 42 proposals/unlock an irrelevant stake/status: Finished retract votes: False/stake,1405758257,3635766,26608 +Agora/Proposal/validator/unlocking/illegal/with 42 proposals/remove creator too early/status: Draft/stake,1700152469,4465470,27236 +Agora/Proposal/validator/unlocking/illegal/with 42 proposals/remove creator too early/status: VotingReady/stake,1700152469,4465470,27236 +Agora/Proposal/validator/unlocking/illegal/with 42 proposals/remove creator too early/status: Locked/stake,1700152469,4465470,27236 +Agora/Proposal/validator/unlocking/illegal/with 42 proposals/creator: retract votes/stake,1700152469,4465470,27152 +Agora/AuthorityToken/singleAuthorityTokenBurned/Correct simple,19822997,52452,427 +Agora/AuthorityToken/singleAuthorityTokenBurned/Correct many inputs,32009395,84810,527 +Agora/Treasury/Validator/Positive/Allows for effect changes,31553082,81982,1423 +Agora/AuthorityToken/singleAuthorityTokenBurned/Correct simple,19822997,52452,427 +Agora/AuthorityToken/singleAuthorityTokenBurned/Correct many inputs,32009395,84810,527 +Agora/Governor/policy/totally legal,70301827,197578,2576 +Agora/Governor/validator/mutate/legal,119848510,323653,9297 diff --git a/cabal.project b/cabal.project index 2d2f2793..96f675f2 100644 --- a/cabal.project +++ b/cabal.project @@ -3,7 +3,4 @@ packages: ./. benchmarks: true tests: true -package plutarch - flags: +development - -test-show-details: direct \ No newline at end of file +test-show-details: direct diff --git a/flake.lock b/flake.lock index a252426c..0537e793 100644 --- a/flake.lock +++ b/flake.lock @@ -32,6 +32,86 @@ "type": "github" } }, + "HTTP_11": { + "flake": false, + "locked": { + "lastModified": 1451647621, + "narHash": "sha256-oHIyw3x0iKBexEo49YeUDV1k74ZtyYKGR2gNJXXRxts=", + "owner": "phadej", + "repo": "HTTP", + "rev": "9bc0996d412fef1787449d841277ef663ad9a915", + "type": "github" + }, + "original": { + "owner": "phadej", + "repo": "HTTP", + "type": "github" + } + }, + "HTTP_12": { + "flake": false, + "locked": { + "lastModified": 1451647621, + "narHash": "sha256-oHIyw3x0iKBexEo49YeUDV1k74ZtyYKGR2gNJXXRxts=", + "owner": "phadej", + "repo": "HTTP", + "rev": "9bc0996d412fef1787449d841277ef663ad9a915", + "type": "github" + }, + "original": { + "owner": "phadej", + "repo": "HTTP", + "type": "github" + } + }, + "HTTP_13": { + "flake": false, + "locked": { + "lastModified": 1451647621, + "narHash": "sha256-oHIyw3x0iKBexEo49YeUDV1k74ZtyYKGR2gNJXXRxts=", + "owner": "phadej", + "repo": "HTTP", + "rev": "9bc0996d412fef1787449d841277ef663ad9a915", + "type": "github" + }, + "original": { + "owner": "phadej", + "repo": "HTTP", + "type": "github" + } + }, + "HTTP_14": { + "flake": false, + "locked": { + "lastModified": 1451647621, + "narHash": "sha256-oHIyw3x0iKBexEo49YeUDV1k74ZtyYKGR2gNJXXRxts=", + "owner": "phadej", + "repo": "HTTP", + "rev": "9bc0996d412fef1787449d841277ef663ad9a915", + "type": "github" + }, + "original": { + "owner": "phadej", + "repo": "HTTP", + "type": "github" + } + }, + "HTTP_15": { + "flake": false, + "locked": { + "lastModified": 1451647621, + "narHash": "sha256-oHIyw3x0iKBexEo49YeUDV1k74ZtyYKGR2gNJXXRxts=", + "owner": "phadej", + "repo": "HTTP", + "rev": "9bc0996d412fef1787449d841277ef663ad9a915", + "type": "github" + }, + "original": { + "owner": "phadej", + "repo": "HTTP", + "type": "github" + } + }, "HTTP_2": { "flake": false, "locked": { @@ -160,23 +240,24 @@ "type": "github" } }, - "Shrinker": { + "cabal-32": { "flake": false, "locked": { - "lastModified": 1642430208, - "narHash": "sha256-tfWyB7zCLzncwRpyl7eUOzuOBbg9KLu6sxSxRaFlOug=", - "owner": "Plutonomicon", - "repo": "Shrinker", - "rev": "0e60707996b876c7bd23a348f54545217ce2e556", + "lastModified": 1603716527, + "narHash": "sha256-X0TFfdD4KZpwl0Zr6x+PLxUt/VyKQfX7ylXHdmZIL+w=", + "owner": "haskell", + "repo": "cabal", + "rev": "48bf10787e27364730dd37a42b603cee8d6af7ee", "type": "github" }, "original": { - "owner": "Plutonomicon", - "repo": "Shrinker", + "owner": "haskell", + "ref": "3.2", + "repo": "cabal", "type": "github" } }, - "cabal-32": { + "cabal-32_10": { "flake": false, "locked": { "lastModified": 1603716527, @@ -193,7 +274,75 @@ "type": "github" } }, - "cabal-32_10": { + "cabal-32_11": { + "flake": false, + "locked": { + "lastModified": 1603716527, + "narHash": "sha256-X0TFfdD4KZpwl0Zr6x+PLxUt/VyKQfX7ylXHdmZIL+w=", + "owner": "haskell", + "repo": "cabal", + "rev": "48bf10787e27364730dd37a42b603cee8d6af7ee", + "type": "github" + }, + "original": { + "owner": "haskell", + "ref": "3.2", + "repo": "cabal", + "type": "github" + } + }, + "cabal-32_12": { + "flake": false, + "locked": { + "lastModified": 1603716527, + "narHash": "sha256-X0TFfdD4KZpwl0Zr6x+PLxUt/VyKQfX7ylXHdmZIL+w=", + "owner": "haskell", + "repo": "cabal", + "rev": "48bf10787e27364730dd37a42b603cee8d6af7ee", + "type": "github" + }, + "original": { + "owner": "haskell", + "ref": "3.2", + "repo": "cabal", + "type": "github" + } + }, + "cabal-32_13": { + "flake": false, + "locked": { + "lastModified": 1603716527, + "narHash": "sha256-X0TFfdD4KZpwl0Zr6x+PLxUt/VyKQfX7ylXHdmZIL+w=", + "owner": "haskell", + "repo": "cabal", + "rev": "48bf10787e27364730dd37a42b603cee8d6af7ee", + "type": "github" + }, + "original": { + "owner": "haskell", + "ref": "3.2", + "repo": "cabal", + "type": "github" + } + }, + "cabal-32_14": { + "flake": false, + "locked": { + "lastModified": 1603716527, + "narHash": "sha256-X0TFfdD4KZpwl0Zr6x+PLxUt/VyKQfX7ylXHdmZIL+w=", + "owner": "haskell", + "repo": "cabal", + "rev": "48bf10787e27364730dd37a42b603cee8d6af7ee", + "type": "github" + }, + "original": { + "owner": "haskell", + "ref": "3.2", + "repo": "cabal", + "type": "github" + } + }, + "cabal-32_15": { "flake": false, "locked": { "lastModified": 1603716527, @@ -380,6 +529,91 @@ "type": "github" } }, + "cabal-34_11": { + "flake": false, + "locked": { + "lastModified": 1640353650, + "narHash": "sha256-N1t6M3/wqj90AEdRkeC8i923gQYUpzSr8b40qVOZ1Rk=", + "owner": "haskell", + "repo": "cabal", + "rev": "942639c18c0cd8ec53e0a6f8d120091af35312cd", + "type": "github" + }, + "original": { + "owner": "haskell", + "ref": "3.4", + "repo": "cabal", + "type": "github" + } + }, + "cabal-34_12": { + "flake": false, + "locked": { + "lastModified": 1640353650, + "narHash": "sha256-N1t6M3/wqj90AEdRkeC8i923gQYUpzSr8b40qVOZ1Rk=", + "owner": "haskell", + "repo": "cabal", + "rev": "942639c18c0cd8ec53e0a6f8d120091af35312cd", + "type": "github" + }, + "original": { + "owner": "haskell", + "ref": "3.4", + "repo": "cabal", + "type": "github" + } + }, + "cabal-34_13": { + "flake": false, + "locked": { + "lastModified": 1640353650, + "narHash": "sha256-N1t6M3/wqj90AEdRkeC8i923gQYUpzSr8b40qVOZ1Rk=", + "owner": "haskell", + "repo": "cabal", + "rev": "942639c18c0cd8ec53e0a6f8d120091af35312cd", + "type": "github" + }, + "original": { + "owner": "haskell", + "ref": "3.4", + "repo": "cabal", + "type": "github" + } + }, + "cabal-34_14": { + "flake": false, + "locked": { + "lastModified": 1640353650, + "narHash": "sha256-N1t6M3/wqj90AEdRkeC8i923gQYUpzSr8b40qVOZ1Rk=", + "owner": "haskell", + "repo": "cabal", + "rev": "942639c18c0cd8ec53e0a6f8d120091af35312cd", + "type": "github" + }, + "original": { + "owner": "haskell", + "ref": "3.4", + "repo": "cabal", + "type": "github" + } + }, + "cabal-34_15": { + "flake": false, + "locked": { + "lastModified": 1640353650, + "narHash": "sha256-N1t6M3/wqj90AEdRkeC8i923gQYUpzSr8b40qVOZ1Rk=", + "owner": "haskell", + "repo": "cabal", + "rev": "942639c18c0cd8ec53e0a6f8d120091af35312cd", + "type": "github" + }, + "original": { + "owner": "haskell", + "ref": "3.4", + "repo": "cabal", + "type": "github" + } + }, "cabal-34_2": { "flake": false, "locked": { @@ -550,7 +784,7 @@ "type": "github" } }, - "cabal-36_2": { + "cabal-36_11": { "flake": false, "locked": { "lastModified": 1641652457, @@ -567,7 +801,7 @@ "type": "github" } }, - "cabal-36_3": { + "cabal-36_12": { "flake": false, "locked": { "lastModified": 1641652457, @@ -584,7 +818,7 @@ "type": "github" } }, - "cabal-36_4": { + "cabal-36_13": { "flake": false, "locked": { "lastModified": 1641652457, @@ -601,7 +835,7 @@ "type": "github" } }, - "cabal-36_5": { + "cabal-36_14": { "flake": false, "locked": { "lastModified": 1641652457, @@ -618,7 +852,7 @@ "type": "github" } }, - "cabal-36_6": { + "cabal-36_15": { "flake": false, "locked": { "lastModified": 1641652457, @@ -635,7 +869,7 @@ "type": "github" } }, - "cabal-36_7": { + "cabal-36_2": { "flake": false, "locked": { "lastModified": 1641652457, @@ -652,7 +886,7 @@ "type": "github" } }, - "cabal-36_8": { + "cabal-36_3": { "flake": false, "locked": { "lastModified": 1641652457, @@ -669,7 +903,7 @@ "type": "github" } }, - "cabal-36_9": { + "cabal-36_4": { "flake": false, "locked": { "lastModified": 1641652457, @@ -686,14 +920,99 @@ "type": "github" } }, - "cardano-base": { + "cabal-36_5": { "flake": false, "locked": { - "lastModified": 1652788515, - "narHash": "sha256-l0KgomRi6YhEoOlFnBYEXhnZO2+PW68rhfUrbMXjhCQ=", - "owner": "input-output-hk", - "repo": "cardano-base", - "rev": "631cb6cf1fa01ab346233b610a38b3b4cba6e6ab", + "lastModified": 1641652457, + "narHash": "sha256-BlFPKP4C4HRUJeAbdembX1Rms1LD380q9s0qVDeoAak=", + "owner": "haskell", + "repo": "cabal", + "rev": "f27667f8ec360c475027dcaee0138c937477b070", + "type": "github" + }, + "original": { + "owner": "haskell", + "ref": "3.6", + "repo": "cabal", + "type": "github" + } + }, + "cabal-36_6": { + "flake": false, + "locked": { + "lastModified": 1641652457, + "narHash": "sha256-BlFPKP4C4HRUJeAbdembX1Rms1LD380q9s0qVDeoAak=", + "owner": "haskell", + "repo": "cabal", + "rev": "f27667f8ec360c475027dcaee0138c937477b070", + "type": "github" + }, + "original": { + "owner": "haskell", + "ref": "3.6", + "repo": "cabal", + "type": "github" + } + }, + "cabal-36_7": { + "flake": false, + "locked": { + "lastModified": 1641652457, + "narHash": "sha256-BlFPKP4C4HRUJeAbdembX1Rms1LD380q9s0qVDeoAak=", + "owner": "haskell", + "repo": "cabal", + "rev": "f27667f8ec360c475027dcaee0138c937477b070", + "type": "github" + }, + "original": { + "owner": "haskell", + "ref": "3.6", + "repo": "cabal", + "type": "github" + } + }, + "cabal-36_8": { + "flake": false, + "locked": { + "lastModified": 1641652457, + "narHash": "sha256-BlFPKP4C4HRUJeAbdembX1Rms1LD380q9s0qVDeoAak=", + "owner": "haskell", + "repo": "cabal", + "rev": "f27667f8ec360c475027dcaee0138c937477b070", + "type": "github" + }, + "original": { + "owner": "haskell", + "ref": "3.6", + "repo": "cabal", + "type": "github" + } + }, + "cabal-36_9": { + "flake": false, + "locked": { + "lastModified": 1641652457, + "narHash": "sha256-BlFPKP4C4HRUJeAbdembX1Rms1LD380q9s0qVDeoAak=", + "owner": "haskell", + "repo": "cabal", + "rev": "f27667f8ec360c475027dcaee0138c937477b070", + "type": "github" + }, + "original": { + "owner": "haskell", + "ref": "3.6", + "repo": "cabal", + "type": "github" + } + }, + "cardano-base": { + "flake": false, + "locked": { + "lastModified": 1652788515, + "narHash": "sha256-l0KgomRi6YhEoOlFnBYEXhnZO2+PW68rhfUrbMXjhCQ=", + "owner": "input-output-hk", + "repo": "cardano-base", + "rev": "631cb6cf1fa01ab346233b610a38b3b4cba6e6ab", "type": "github" }, "original": { @@ -705,11 +1024,91 @@ "cardano-base_10": { "flake": false, "locked": { - "lastModified": 1638456794, - "narHash": "sha256-0KAO6dWqupJzRyjWjAFLZrt0hA6pozeKsDv1Fnysib8=", + "lastModified": 1652788515, + "narHash": "sha256-l0KgomRi6YhEoOlFnBYEXhnZO2+PW68rhfUrbMXjhCQ=", + "owner": "input-output-hk", + "repo": "cardano-base", + "rev": "631cb6cf1fa01ab346233b610a38b3b4cba6e6ab", + "type": "github" + }, + "original": { + "owner": "input-output-hk", + "repo": "cardano-base", + "type": "github" + } + }, + "cardano-base_11": { + "flake": false, + "locked": { + "lastModified": 1652788515, + "narHash": "sha256-l0KgomRi6YhEoOlFnBYEXhnZO2+PW68rhfUrbMXjhCQ=", + "owner": "input-output-hk", + "repo": "cardano-base", + "rev": "631cb6cf1fa01ab346233b610a38b3b4cba6e6ab", + "type": "github" + }, + "original": { + "owner": "input-output-hk", + "repo": "cardano-base", + "type": "github" + } + }, + "cardano-base_12": { + "flake": false, + "locked": { + "lastModified": 1652788515, + "narHash": "sha256-l0KgomRi6YhEoOlFnBYEXhnZO2+PW68rhfUrbMXjhCQ=", + "owner": "input-output-hk", + "repo": "cardano-base", + "rev": "631cb6cf1fa01ab346233b610a38b3b4cba6e6ab", + "type": "github" + }, + "original": { + "owner": "input-output-hk", + "repo": "cardano-base", + "type": "github" + } + }, + "cardano-base_13": { + "flake": false, + "locked": { + "lastModified": 1652788515, + "narHash": "sha256-l0KgomRi6YhEoOlFnBYEXhnZO2+PW68rhfUrbMXjhCQ=", + "owner": "input-output-hk", + "repo": "cardano-base", + "rev": "631cb6cf1fa01ab346233b610a38b3b4cba6e6ab", + "type": "github" + }, + "original": { + "owner": "input-output-hk", + "repo": "cardano-base", + "type": "github" + } + }, + "cardano-base_14": { + "flake": false, + "locked": { + "lastModified": 1652788515, + "narHash": "sha256-l0KgomRi6YhEoOlFnBYEXhnZO2+PW68rhfUrbMXjhCQ=", + "owner": "input-output-hk", + "repo": "cardano-base", + "rev": "631cb6cf1fa01ab346233b610a38b3b4cba6e6ab", + "type": "github" + }, + "original": { + "owner": "input-output-hk", + "repo": "cardano-base", + "type": "github" + } + }, + "cardano-base_15": { + "flake": false, + "locked": { + "lastModified": 1652788515, + "narHash": "sha256-l0KgomRi6YhEoOlFnBYEXhnZO2+PW68rhfUrbMXjhCQ=", "owner": "input-output-hk", "repo": "cardano-base", - "rev": "4fae3f0149fd8925be94707d3ae0e36c0d67bd58", + "rev": "631cb6cf1fa01ab346233b610a38b3b4cba6e6ab", "type": "github" }, "original": { @@ -880,6 +1279,91 @@ "type": "github" } }, + "cardano-crypto_11": { + "flake": false, + "locked": { + "lastModified": 1621376239, + "narHash": "sha256-oxIOVlgm07FAEmgGRF1C2me9TXqVxQulEOcJ22zpTRs=", + "owner": "input-output-hk", + "repo": "cardano-crypto", + "rev": "07397f0e50da97eaa0575d93bee7ac4b2b2576ec", + "type": "github" + }, + "original": { + "owner": "input-output-hk", + "repo": "cardano-crypto", + "rev": "07397f0e50da97eaa0575d93bee7ac4b2b2576ec", + "type": "github" + } + }, + "cardano-crypto_12": { + "flake": false, + "locked": { + "lastModified": 1621376239, + "narHash": "sha256-oxIOVlgm07FAEmgGRF1C2me9TXqVxQulEOcJ22zpTRs=", + "owner": "input-output-hk", + "repo": "cardano-crypto", + "rev": "07397f0e50da97eaa0575d93bee7ac4b2b2576ec", + "type": "github" + }, + "original": { + "owner": "input-output-hk", + "repo": "cardano-crypto", + "rev": "07397f0e50da97eaa0575d93bee7ac4b2b2576ec", + "type": "github" + } + }, + "cardano-crypto_13": { + "flake": false, + "locked": { + "lastModified": 1621376239, + "narHash": "sha256-oxIOVlgm07FAEmgGRF1C2me9TXqVxQulEOcJ22zpTRs=", + "owner": "input-output-hk", + "repo": "cardano-crypto", + "rev": "07397f0e50da97eaa0575d93bee7ac4b2b2576ec", + "type": "github" + }, + "original": { + "owner": "input-output-hk", + "repo": "cardano-crypto", + "rev": "07397f0e50da97eaa0575d93bee7ac4b2b2576ec", + "type": "github" + } + }, + "cardano-crypto_14": { + "flake": false, + "locked": { + "lastModified": 1621376239, + "narHash": "sha256-oxIOVlgm07FAEmgGRF1C2me9TXqVxQulEOcJ22zpTRs=", + "owner": "input-output-hk", + "repo": "cardano-crypto", + "rev": "07397f0e50da97eaa0575d93bee7ac4b2b2576ec", + "type": "github" + }, + "original": { + "owner": "input-output-hk", + "repo": "cardano-crypto", + "rev": "07397f0e50da97eaa0575d93bee7ac4b2b2576ec", + "type": "github" + } + }, + "cardano-crypto_15": { + "flake": false, + "locked": { + "lastModified": 1621376239, + "narHash": "sha256-oxIOVlgm07FAEmgGRF1C2me9TXqVxQulEOcJ22zpTRs=", + "owner": "input-output-hk", + "repo": "cardano-crypto", + "rev": "07397f0e50da97eaa0575d93bee7ac4b2b2576ec", + "type": "github" + }, + "original": { + "owner": "input-output-hk", + "repo": "cardano-crypto", + "rev": "07397f0e50da97eaa0575d93bee7ac4b2b2576ec", + "type": "github" + } + }, "cardano-crypto_2": { "flake": false, "locked": { @@ -1036,21 +1520,21 @@ "cardano-prelude_10": { "flake": false, "locked": { - "lastModified": 1641566029, - "narHash": "sha256-CylaHhO4zbZ1dEAv8yWp1swP1xys/s2Sbxg3a2pdnCI=", - "owner": "locallycompact", + "lastModified": 1653997332, + "narHash": "sha256-E+YSfUsvxdoOr7n7fz4xd7zb4z8XBRGNYOKipc2A1pw=", + "owner": "mlabs-haskell", "repo": "cardano-prelude", - "rev": "93f95047bb36a055bdd56fb0cafd887c072cdce2", + "rev": "713c7ae79a4d538fcd653c976a652913df1567b9", "type": "github" }, "original": { - "owner": "locallycompact", + "owner": "mlabs-haskell", "repo": "cardano-prelude", - "rev": "93f95047bb36a055bdd56fb0cafd887c072cdce2", + "rev": "713c7ae79a4d538fcd653c976a652913df1567b9", "type": "github" } }, - "cardano-prelude_2": { + "cardano-prelude_11": { "flake": false, "locked": { "lastModified": 1653997332, @@ -1067,7 +1551,7 @@ "type": "github" } }, - "cardano-prelude_3": { + "cardano-prelude_12": { "flake": false, "locked": { "lastModified": 1653997332, @@ -1084,7 +1568,7 @@ "type": "github" } }, - "cardano-prelude_4": { + "cardano-prelude_13": { "flake": false, "locked": { "lastModified": 1653997332, @@ -1101,7 +1585,7 @@ "type": "github" } }, - "cardano-prelude_5": { + "cardano-prelude_14": { "flake": false, "locked": { "lastModified": 1653997332, @@ -1118,7 +1602,7 @@ "type": "github" } }, - "cardano-prelude_6": { + "cardano-prelude_15": { "flake": false, "locked": { "lastModified": 1653997332, @@ -1135,7 +1619,92 @@ "type": "github" } }, - "cardano-prelude_7": { + "cardano-prelude_2": { + "flake": false, + "locked": { + "lastModified": 1653997332, + "narHash": "sha256-E+YSfUsvxdoOr7n7fz4xd7zb4z8XBRGNYOKipc2A1pw=", + "owner": "mlabs-haskell", + "repo": "cardano-prelude", + "rev": "713c7ae79a4d538fcd653c976a652913df1567b9", + "type": "github" + }, + "original": { + "owner": "mlabs-haskell", + "repo": "cardano-prelude", + "rev": "713c7ae79a4d538fcd653c976a652913df1567b9", + "type": "github" + } + }, + "cardano-prelude_3": { + "flake": false, + "locked": { + "lastModified": 1653997332, + "narHash": "sha256-E+YSfUsvxdoOr7n7fz4xd7zb4z8XBRGNYOKipc2A1pw=", + "owner": "mlabs-haskell", + "repo": "cardano-prelude", + "rev": "713c7ae79a4d538fcd653c976a652913df1567b9", + "type": "github" + }, + "original": { + "owner": "mlabs-haskell", + "repo": "cardano-prelude", + "rev": "713c7ae79a4d538fcd653c976a652913df1567b9", + "type": "github" + } + }, + "cardano-prelude_4": { + "flake": false, + "locked": { + "lastModified": 1653997332, + "narHash": "sha256-E+YSfUsvxdoOr7n7fz4xd7zb4z8XBRGNYOKipc2A1pw=", + "owner": "mlabs-haskell", + "repo": "cardano-prelude", + "rev": "713c7ae79a4d538fcd653c976a652913df1567b9", + "type": "github" + }, + "original": { + "owner": "mlabs-haskell", + "repo": "cardano-prelude", + "rev": "713c7ae79a4d538fcd653c976a652913df1567b9", + "type": "github" + } + }, + "cardano-prelude_5": { + "flake": false, + "locked": { + "lastModified": 1653997332, + "narHash": "sha256-E+YSfUsvxdoOr7n7fz4xd7zb4z8XBRGNYOKipc2A1pw=", + "owner": "mlabs-haskell", + "repo": "cardano-prelude", + "rev": "713c7ae79a4d538fcd653c976a652913df1567b9", + "type": "github" + }, + "original": { + "owner": "mlabs-haskell", + "repo": "cardano-prelude", + "rev": "713c7ae79a4d538fcd653c976a652913df1567b9", + "type": "github" + } + }, + "cardano-prelude_6": { + "flake": false, + "locked": { + "lastModified": 1653997332, + "narHash": "sha256-E+YSfUsvxdoOr7n7fz4xd7zb4z8XBRGNYOKipc2A1pw=", + "owner": "mlabs-haskell", + "repo": "cardano-prelude", + "rev": "713c7ae79a4d538fcd653c976a652913df1567b9", + "type": "github" + }, + "original": { + "owner": "mlabs-haskell", + "repo": "cardano-prelude", + "rev": "713c7ae79a4d538fcd653c976a652913df1567b9", + "type": "github" + } + }, + "cardano-prelude_7": { "flake": false, "locked": { "lastModified": 1653997332, @@ -1218,6 +1787,86 @@ "type": "github" } }, + "cardano-repo-tool_11": { + "flake": false, + "locked": { + "lastModified": 1624584417, + "narHash": "sha256-YSepT97PagR/1jTYV/Yer8a2GjFe9+tTwaTCHxuK50M=", + "owner": "input-output-hk", + "repo": "cardano-repo-tool", + "rev": "30e826ed8f00e3e154453b122a6f3d779b2f73ec", + "type": "github" + }, + "original": { + "owner": "input-output-hk", + "repo": "cardano-repo-tool", + "type": "github" + } + }, + "cardano-repo-tool_12": { + "flake": false, + "locked": { + "lastModified": 1624584417, + "narHash": "sha256-YSepT97PagR/1jTYV/Yer8a2GjFe9+tTwaTCHxuK50M=", + "owner": "input-output-hk", + "repo": "cardano-repo-tool", + "rev": "30e826ed8f00e3e154453b122a6f3d779b2f73ec", + "type": "github" + }, + "original": { + "owner": "input-output-hk", + "repo": "cardano-repo-tool", + "type": "github" + } + }, + "cardano-repo-tool_13": { + "flake": false, + "locked": { + "lastModified": 1624584417, + "narHash": "sha256-YSepT97PagR/1jTYV/Yer8a2GjFe9+tTwaTCHxuK50M=", + "owner": "input-output-hk", + "repo": "cardano-repo-tool", + "rev": "30e826ed8f00e3e154453b122a6f3d779b2f73ec", + "type": "github" + }, + "original": { + "owner": "input-output-hk", + "repo": "cardano-repo-tool", + "type": "github" + } + }, + "cardano-repo-tool_14": { + "flake": false, + "locked": { + "lastModified": 1624584417, + "narHash": "sha256-YSepT97PagR/1jTYV/Yer8a2GjFe9+tTwaTCHxuK50M=", + "owner": "input-output-hk", + "repo": "cardano-repo-tool", + "rev": "30e826ed8f00e3e154453b122a6f3d779b2f73ec", + "type": "github" + }, + "original": { + "owner": "input-output-hk", + "repo": "cardano-repo-tool", + "type": "github" + } + }, + "cardano-repo-tool_15": { + "flake": false, + "locked": { + "lastModified": 1624584417, + "narHash": "sha256-YSepT97PagR/1jTYV/Yer8a2GjFe9+tTwaTCHxuK50M=", + "owner": "input-output-hk", + "repo": "cardano-repo-tool", + "rev": "30e826ed8f00e3e154453b122a6f3d779b2f73ec", + "type": "github" + }, + "original": { + "owner": "input-output-hk", + "repo": "cardano-repo-tool", + "type": "github" + } + }, "cardano-repo-tool_2": { "flake": false, "locked": { @@ -1378,7 +2027,7 @@ "type": "github" } }, - "cardano-shell_2": { + "cardano-shell_11": { "flake": false, "locked": { "lastModified": 1608537748, @@ -1394,7 +2043,7 @@ "type": "github" } }, - "cardano-shell_3": { + "cardano-shell_12": { "flake": false, "locked": { "lastModified": 1608537748, @@ -1410,7 +2059,7 @@ "type": "github" } }, - "cardano-shell_4": { + "cardano-shell_13": { "flake": false, "locked": { "lastModified": 1608537748, @@ -1426,7 +2075,7 @@ "type": "github" } }, - "cardano-shell_5": { + "cardano-shell_14": { "flake": false, "locked": { "lastModified": 1608537748, @@ -1442,7 +2091,7 @@ "type": "github" } }, - "cardano-shell_6": { + "cardano-shell_15": { "flake": false, "locked": { "lastModified": 1608537748, @@ -1458,7 +2107,7 @@ "type": "github" } }, - "cardano-shell_7": { + "cardano-shell_2": { "flake": false, "locked": { "lastModified": 1608537748, @@ -1474,7 +2123,7 @@ "type": "github" } }, - "cardano-shell_8": { + "cardano-shell_3": { "flake": false, "locked": { "lastModified": 1608537748, @@ -1490,7 +2139,7 @@ "type": "github" } }, - "cardano-shell_9": { + "cardano-shell_4": { "flake": false, "locked": { "lastModified": 1608537748, @@ -1506,2263 +2155,1881 @@ "type": "github" } }, - "cryptonite": { + "cardano-shell_5": { "flake": false, "locked": { - "lastModified": 1639749289, - "narHash": "sha256-/KS2S0f9r4c/q+IUGwkFOY9jbZkyK3dl0xMpDbULeqc=", - "owner": "haskell-crypto", - "repo": "cryptonite", - "rev": "cec291d988f0f17828384f3358214ab9bf724a13", + "lastModified": 1608537748, + "narHash": "sha256-PulY1GfiMgKVnBci3ex4ptk2UNYMXqGjJOxcPy2KYT4=", + "owner": "input-output-hk", + "repo": "cardano-shell", + "rev": "9392c75087cb9a3d453998f4230930dea3a95725", "type": "github" }, "original": { - "owner": "haskell-crypto", - "repo": "cryptonite", - "rev": "cec291d988f0f17828384f3358214ab9bf724a13", + "owner": "input-output-hk", + "repo": "cardano-shell", "type": "github" } }, - "ema": { - "inputs": { - "flake-compat": "flake-compat", - "flake-utils": "flake-utils", - "nixpkgs": "nixpkgs" - }, + "cardano-shell_6": { + "flake": false, "locked": { - "lastModified": 1653742730, - "narHash": "sha256-NyhjoMbm3h1aTskIU6jowNClSgA92bUcGcVNPfWNWgE=", - "owner": "srid", - "repo": "ema", - "rev": "50d9499db16b4e334776d8e8cffcd144c67f9fc4", + "lastModified": 1608537748, + "narHash": "sha256-PulY1GfiMgKVnBci3ex4ptk2UNYMXqGjJOxcPy2KYT4=", + "owner": "input-output-hk", + "repo": "cardano-shell", + "rev": "9392c75087cb9a3d453998f4230930dea3a95725", "type": "github" }, "original": { - "owner": "srid", - "ref": "multisite", - "repo": "ema", + "owner": "input-output-hk", + "repo": "cardano-shell", "type": "github" } }, - "ema_2": { - "inputs": { - "flake-compat": "flake-compat_3", - "flake-utils": "flake-utils_4", - "nixpkgs": "nixpkgs_6" - }, + "cardano-shell_7": { + "flake": false, "locked": { - "lastModified": 1653742730, - "narHash": "sha256-NyhjoMbm3h1aTskIU6jowNClSgA92bUcGcVNPfWNWgE=", - "owner": "srid", - "repo": "ema", - "rev": "50d9499db16b4e334776d8e8cffcd144c67f9fc4", + "lastModified": 1608537748, + "narHash": "sha256-PulY1GfiMgKVnBci3ex4ptk2UNYMXqGjJOxcPy2KYT4=", + "owner": "input-output-hk", + "repo": "cardano-shell", + "rev": "9392c75087cb9a3d453998f4230930dea3a95725", "type": "github" }, "original": { - "owner": "srid", - "ref": "multisite", - "repo": "ema", + "owner": "input-output-hk", + "repo": "cardano-shell", "type": "github" } }, - "ema_3": { - "inputs": { - "flake-compat": "flake-compat_5", - "flake-utils": "flake-utils_8", - "nixpkgs": "nixpkgs_14" - }, + "cardano-shell_8": { + "flake": false, "locked": { - "lastModified": 1653742730, - "narHash": "sha256-NyhjoMbm3h1aTskIU6jowNClSgA92bUcGcVNPfWNWgE=", - "owner": "srid", - "repo": "ema", - "rev": "50d9499db16b4e334776d8e8cffcd144c67f9fc4", + "lastModified": 1608537748, + "narHash": "sha256-PulY1GfiMgKVnBci3ex4ptk2UNYMXqGjJOxcPy2KYT4=", + "owner": "input-output-hk", + "repo": "cardano-shell", + "rev": "9392c75087cb9a3d453998f4230930dea3a95725", "type": "github" }, "original": { - "owner": "srid", - "ref": "multisite", - "repo": "ema", + "owner": "input-output-hk", + "repo": "cardano-shell", "type": "github" } }, - "ema_4": { - "inputs": { - "flake-compat": "flake-compat_7", - "flake-utils": "flake-utils_11", - "nixpkgs": "nixpkgs_19" - }, + "cardano-shell_9": { + "flake": false, "locked": { - "lastModified": 1653742730, - "narHash": "sha256-NyhjoMbm3h1aTskIU6jowNClSgA92bUcGcVNPfWNWgE=", - "owner": "srid", - "repo": "ema", - "rev": "50d9499db16b4e334776d8e8cffcd144c67f9fc4", + "lastModified": 1608537748, + "narHash": "sha256-PulY1GfiMgKVnBci3ex4ptk2UNYMXqGjJOxcPy2KYT4=", + "owner": "input-output-hk", + "repo": "cardano-shell", + "rev": "9392c75087cb9a3d453998f4230930dea3a95725", "type": "github" }, "original": { - "owner": "srid", - "ref": "multisite", - "repo": "ema", + "owner": "input-output-hk", + "repo": "cardano-shell", "type": "github" } }, - "ema_5": { - "inputs": { - "flake-compat": "flake-compat_9", - "flake-utils": "flake-utils_14", - "nixpkgs": "nixpkgs_24" - }, + "flake-utils": { "locked": { - "lastModified": 1653742730, - "narHash": "sha256-NyhjoMbm3h1aTskIU6jowNClSgA92bUcGcVNPfWNWgE=", - "owner": "srid", - "repo": "ema", - "rev": "50d9499db16b4e334776d8e8cffcd144c67f9fc4", + "lastModified": 1644229661, + "narHash": "sha256-1YdnJAsNy69bpcjuoKdOYQX0YxZBiCYZo4Twxerqv7k=", + "owner": "numtide", + "repo": "flake-utils", + "rev": "3cecb5b042f7f209c56ffd8371b2711a290ec797", "type": "github" }, "original": { - "owner": "srid", - "ref": "multisite", - "repo": "ema", + "owner": "numtide", + "repo": "flake-utils", "type": "github" } }, - "ema_6": { - "inputs": { - "flake-compat": "flake-compat_11", - "flake-utils": "flake-utils_17", - "nixpkgs": "nixpkgs_29" - }, + "flake-utils_10": { "locked": { - "lastModified": 1653742730, - "narHash": "sha256-NyhjoMbm3h1aTskIU6jowNClSgA92bUcGcVNPfWNWgE=", - "owner": "srid", - "repo": "ema", - "rev": "50d9499db16b4e334776d8e8cffcd144c67f9fc4", + "lastModified": 1644229661, + "narHash": "sha256-1YdnJAsNy69bpcjuoKdOYQX0YxZBiCYZo4Twxerqv7k=", + "owner": "numtide", + "repo": "flake-utils", + "rev": "3cecb5b042f7f209c56ffd8371b2711a290ec797", "type": "github" }, "original": { - "owner": "srid", - "ref": "multisite", - "repo": "ema", + "owner": "numtide", + "repo": "flake-utils", "type": "github" } }, - "ema_7": { - "inputs": { - "flake-compat": "flake-compat_13", - "flake-utils": "flake-utils_20", - "nixpkgs": "nixpkgs_34" - }, + "flake-utils_11": { "locked": { - "lastModified": 1653742730, - "narHash": "sha256-NyhjoMbm3h1aTskIU6jowNClSgA92bUcGcVNPfWNWgE=", - "owner": "srid", - "repo": "ema", - "rev": "50d9499db16b4e334776d8e8cffcd144c67f9fc4", + "lastModified": 1644229661, + "narHash": "sha256-1YdnJAsNy69bpcjuoKdOYQX0YxZBiCYZo4Twxerqv7k=", + "owner": "numtide", + "repo": "flake-utils", + "rev": "3cecb5b042f7f209c56ffd8371b2711a290ec797", "type": "github" }, "original": { - "owner": "srid", - "ref": "multisite", - "repo": "ema", + "owner": "numtide", + "repo": "flake-utils", "type": "github" } }, - "ema_8": { - "inputs": { - "flake-compat": "flake-compat_15", - "flake-utils": "flake-utils_23", - "nixpkgs": "nixpkgs_39" - }, + "flake-utils_12": { "locked": { - "lastModified": 1653742730, - "narHash": "sha256-NyhjoMbm3h1aTskIU6jowNClSgA92bUcGcVNPfWNWgE=", - "owner": "srid", - "repo": "ema", - "rev": "50d9499db16b4e334776d8e8cffcd144c67f9fc4", + "lastModified": 1644229661, + "narHash": "sha256-1YdnJAsNy69bpcjuoKdOYQX0YxZBiCYZo4Twxerqv7k=", + "owner": "numtide", + "repo": "flake-utils", + "rev": "3cecb5b042f7f209c56ffd8371b2711a290ec797", "type": "github" }, "original": { - "owner": "srid", - "ref": "multisite", - "repo": "ema", + "owner": "numtide", + "repo": "flake-utils", "type": "github" } }, - "ema_9": { - "inputs": { - "flake-compat": "flake-compat_17", - "flake-utils": "flake-utils_26", - "lint-utils": "lint-utils", - "nixpkgs": "nixpkgs_44" - }, + "flake-utils_13": { "locked": { - "lastModified": 1650932571, - "narHash": "sha256-rdpfJ+10a1uBPtHMNoAcpDE183RzpILRpsMgxj/YJek=", - "owner": "srid", - "repo": "ema", - "rev": "05c8a2127391ee4b593fa6541bc9078eb44ad10f", + "lastModified": 1644229661, + "narHash": "sha256-1YdnJAsNy69bpcjuoKdOYQX0YxZBiCYZo4Twxerqv7k=", + "owner": "numtide", + "repo": "flake-utils", + "rev": "3cecb5b042f7f209c56ffd8371b2711a290ec797", "type": "github" }, "original": { - "owner": "srid", - "ref": "multisite", - "repo": "ema", + "owner": "numtide", + "repo": "flake-utils", "type": "github" } }, - "emanote": { - "inputs": { - "ema": "ema", - "flake-compat": [ - "liqwid-plutarch-extra", - "plutarch", - "emanote", - "ema", - "flake-compat" - ], - "flake-utils": [ - "liqwid-plutarch-extra", - "plutarch", - "emanote", - "ema", - "flake-utils" - ], - "heist": "heist", - "ixset-typed": "ixset-typed", - "nixpkgs": [ - "liqwid-plutarch-extra", - "plutarch", - "emanote", - "ema", - "nixpkgs" - ], - "pandoc-link-context": "pandoc-link-context", - "tailwind-haskell": "tailwind-haskell" - }, + "flake-utils_14": { "locked": { - "lastModified": 1653742875, - "narHash": "sha256-2IFMkA6/T0nCQHQcC8UhYWh8q8FQyGDBKfcDIhBJ3JM=", - "owner": "srid", - "repo": "emanote", - "rev": "ab5155ef400ce83a744362a4b953315d7ee6a8c3", + "lastModified": 1644229661, + "narHash": "sha256-1YdnJAsNy69bpcjuoKdOYQX0YxZBiCYZo4Twxerqv7k=", + "owner": "numtide", + "repo": "flake-utils", + "rev": "3cecb5b042f7f209c56ffd8371b2711a290ec797", "type": "github" }, "original": { - "owner": "srid", - "ref": "master", - "repo": "emanote", + "owner": "numtide", + "repo": "flake-utils", "type": "github" } }, - "emanote_2": { - "inputs": { - "ema": "ema_2", - "flake-compat": [ - "liqwid-plutarch-extra", - "plutarch-quickcheck", - "plutarch", - "emanote", - "ema", - "flake-compat" - ], - "flake-utils": [ - "liqwid-plutarch-extra", - "plutarch-quickcheck", - "plutarch", - "emanote", - "ema", - "flake-utils" - ], - "heist": "heist_2", - "ixset-typed": "ixset-typed_2", - "nixpkgs": [ - "liqwid-plutarch-extra", - "plutarch-quickcheck", - "plutarch", - "emanote", - "ema", - "nixpkgs" - ], - "pandoc-link-context": "pandoc-link-context_2", - "tailwind-haskell": "tailwind-haskell_2" - }, + "flake-utils_15": { "locked": { - "lastModified": 1653742875, - "narHash": "sha256-2IFMkA6/T0nCQHQcC8UhYWh8q8FQyGDBKfcDIhBJ3JM=", - "owner": "srid", - "repo": "emanote", - "rev": "ab5155ef400ce83a744362a4b953315d7ee6a8c3", + "lastModified": 1644229661, + "narHash": "sha256-1YdnJAsNy69bpcjuoKdOYQX0YxZBiCYZo4Twxerqv7k=", + "owner": "numtide", + "repo": "flake-utils", + "rev": "3cecb5b042f7f209c56ffd8371b2711a290ec797", "type": "github" }, "original": { - "owner": "srid", - "ref": "master", - "repo": "emanote", + "owner": "numtide", + "repo": "flake-utils", "type": "github" } }, - "emanote_3": { - "inputs": { - "ema": "ema_3", - "flake-compat": [ - "plutarch-context-builder", - "plutarch", - "emanote", - "ema", - "flake-compat" - ], - "flake-utils": [ - "plutarch-context-builder", - "plutarch", - "emanote", - "ema", - "flake-utils" - ], - "heist": "heist_3", - "ixset-typed": "ixset-typed_3", - "nixpkgs": [ - "plutarch-context-builder", - "plutarch", - "emanote", - "ema", - "nixpkgs" - ], - "pandoc-link-context": "pandoc-link-context_3", - "tailwind-haskell": "tailwind-haskell_3" - }, + "flake-utils_2": { "locked": { - "lastModified": 1653742875, - "narHash": "sha256-2IFMkA6/T0nCQHQcC8UhYWh8q8FQyGDBKfcDIhBJ3JM=", - "owner": "srid", - "repo": "emanote", - "rev": "ab5155ef400ce83a744362a4b953315d7ee6a8c3", + "lastModified": 1644229661, + "narHash": "sha256-1YdnJAsNy69bpcjuoKdOYQX0YxZBiCYZo4Twxerqv7k=", + "owner": "numtide", + "repo": "flake-utils", + "rev": "3cecb5b042f7f209c56ffd8371b2711a290ec797", "type": "github" }, "original": { - "owner": "srid", - "ref": "master", - "repo": "emanote", + "owner": "numtide", + "repo": "flake-utils", "type": "github" } }, - "emanote_4": { - "inputs": { - "ema": "ema_4", - "flake-compat": [ - "plutarch-numeric", - "plutarch", - "emanote", - "ema", - "flake-compat" - ], - "flake-utils": [ - "plutarch-numeric", - "plutarch", - "emanote", - "ema", - "flake-utils" - ], - "heist": "heist_4", - "ixset-typed": "ixset-typed_4", - "nixpkgs": [ - "plutarch-numeric", - "plutarch", - "emanote", - "ema", - "nixpkgs" - ], - "pandoc-link-context": "pandoc-link-context_4", - "tailwind-haskell": "tailwind-haskell_4" - }, + "flake-utils_3": { "locked": { - "lastModified": 1653742875, - "narHash": "sha256-2IFMkA6/T0nCQHQcC8UhYWh8q8FQyGDBKfcDIhBJ3JM=", - "owner": "srid", - "repo": "emanote", - "rev": "ab5155ef400ce83a744362a4b953315d7ee6a8c3", + "lastModified": 1644229661, + "narHash": "sha256-1YdnJAsNy69bpcjuoKdOYQX0YxZBiCYZo4Twxerqv7k=", + "owner": "numtide", + "repo": "flake-utils", + "rev": "3cecb5b042f7f209c56ffd8371b2711a290ec797", "type": "github" }, "original": { - "owner": "srid", - "ref": "master", - "repo": "emanote", + "owner": "numtide", + "repo": "flake-utils", "type": "github" } }, - "emanote_5": { - "inputs": { - "ema": "ema_5", - "flake-compat": [ - "plutarch-quickcheck", - "plutarch", - "emanote", - "ema", - "flake-compat" - ], - "flake-utils": [ - "plutarch-quickcheck", - "plutarch", - "emanote", - "ema", - "flake-utils" - ], - "heist": "heist_5", - "ixset-typed": "ixset-typed_5", - "nixpkgs": [ - "plutarch-quickcheck", - "plutarch", - "emanote", - "ema", - "nixpkgs" - ], - "pandoc-link-context": "pandoc-link-context_5", - "tailwind-haskell": "tailwind-haskell_5" - }, + "flake-utils_4": { "locked": { - "lastModified": 1653742875, - "narHash": "sha256-2IFMkA6/T0nCQHQcC8UhYWh8q8FQyGDBKfcDIhBJ3JM=", - "owner": "srid", - "repo": "emanote", - "rev": "ab5155ef400ce83a744362a4b953315d7ee6a8c3", + "lastModified": 1644229661, + "narHash": "sha256-1YdnJAsNy69bpcjuoKdOYQX0YxZBiCYZo4Twxerqv7k=", + "owner": "numtide", + "repo": "flake-utils", + "rev": "3cecb5b042f7f209c56ffd8371b2711a290ec797", "type": "github" }, "original": { - "owner": "srid", - "ref": "master", - "repo": "emanote", + "owner": "numtide", + "repo": "flake-utils", "type": "github" } }, - "emanote_6": { - "inputs": { - "ema": "ema_6", - "flake-compat": [ - "plutarch-safe-money", - "liqwid-plutarch-extra", - "plutarch", - "emanote", - "ema", - "flake-compat" - ], - "flake-utils": [ - "plutarch-safe-money", - "liqwid-plutarch-extra", - "plutarch", - "emanote", - "ema", - "flake-utils" - ], - "heist": "heist_6", - "ixset-typed": "ixset-typed_6", - "nixpkgs": [ - "plutarch-safe-money", - "liqwid-plutarch-extra", - "plutarch", - "emanote", - "ema", - "nixpkgs" - ], - "pandoc-link-context": "pandoc-link-context_6", - "tailwind-haskell": "tailwind-haskell_6" - }, + "flake-utils_5": { "locked": { - "lastModified": 1653742875, - "narHash": "sha256-2IFMkA6/T0nCQHQcC8UhYWh8q8FQyGDBKfcDIhBJ3JM=", - "owner": "srid", - "repo": "emanote", - "rev": "ab5155ef400ce83a744362a4b953315d7ee6a8c3", + "lastModified": 1644229661, + "narHash": "sha256-1YdnJAsNy69bpcjuoKdOYQX0YxZBiCYZo4Twxerqv7k=", + "owner": "numtide", + "repo": "flake-utils", + "rev": "3cecb5b042f7f209c56ffd8371b2711a290ec797", "type": "github" }, "original": { - "owner": "srid", - "ref": "master", - "repo": "emanote", + "owner": "numtide", + "repo": "flake-utils", "type": "github" } }, - "emanote_7": { - "inputs": { - "ema": "ema_7", - "flake-compat": [ - "plutarch-safe-money", - "liqwid-plutarch-extra", - "plutarch-quickcheck", - "plutarch", - "emanote", - "ema", - "flake-compat" - ], - "flake-utils": [ - "plutarch-safe-money", - "liqwid-plutarch-extra", - "plutarch-quickcheck", - "plutarch", - "emanote", - "ema", - "flake-utils" - ], - "heist": "heist_7", - "ixset-typed": "ixset-typed_7", - "nixpkgs": [ - "plutarch-safe-money", - "liqwid-plutarch-extra", - "plutarch-quickcheck", - "plutarch", - "emanote", - "ema", - "nixpkgs" - ], - "pandoc-link-context": "pandoc-link-context_7", - "tailwind-haskell": "tailwind-haskell_7" - }, + "flake-utils_6": { "locked": { - "lastModified": 1653742875, - "narHash": "sha256-2IFMkA6/T0nCQHQcC8UhYWh8q8FQyGDBKfcDIhBJ3JM=", - "owner": "srid", - "repo": "emanote", - "rev": "ab5155ef400ce83a744362a4b953315d7ee6a8c3", + "lastModified": 1644229661, + "narHash": "sha256-1YdnJAsNy69bpcjuoKdOYQX0YxZBiCYZo4Twxerqv7k=", + "owner": "numtide", + "repo": "flake-utils", + "rev": "3cecb5b042f7f209c56ffd8371b2711a290ec797", "type": "github" }, "original": { - "owner": "srid", - "ref": "master", - "repo": "emanote", + "owner": "numtide", + "repo": "flake-utils", "type": "github" } }, - "emanote_8": { - "inputs": { - "ema": "ema_8", - "flake-compat": [ - "plutarch-safe-money", - "plutarch", - "emanote", - "ema", - "flake-compat" - ], - "flake-utils": [ - "plutarch-safe-money", - "plutarch", - "emanote", - "ema", - "flake-utils" - ], - "heist": "heist_8", - "ixset-typed": "ixset-typed_8", - "nixpkgs": [ - "plutarch-safe-money", - "plutarch", - "emanote", - "ema", - "nixpkgs" - ], - "pandoc-link-context": "pandoc-link-context_8", - "tailwind-haskell": "tailwind-haskell_8" - }, + "flake-utils_7": { "locked": { - "lastModified": 1653742875, - "narHash": "sha256-2IFMkA6/T0nCQHQcC8UhYWh8q8FQyGDBKfcDIhBJ3JM=", - "owner": "srid", - "repo": "emanote", - "rev": "ab5155ef400ce83a744362a4b953315d7ee6a8c3", + "lastModified": 1644229661, + "narHash": "sha256-1YdnJAsNy69bpcjuoKdOYQX0YxZBiCYZo4Twxerqv7k=", + "owner": "numtide", + "repo": "flake-utils", + "rev": "3cecb5b042f7f209c56ffd8371b2711a290ec797", "type": "github" }, "original": { - "owner": "srid", - "ref": "master", - "repo": "emanote", + "owner": "numtide", + "repo": "flake-utils", "type": "github" } }, - "emanote_9": { - "inputs": { - "ema": "ema_9", - "flake-compat": [ - "plutarch-safe-money", - "plutarch-numeric", - "plutarch", - "emanote", - "ema", - "flake-compat" - ], - "flake-utils": [ - "plutarch-safe-money", - "plutarch-numeric", - "plutarch", - "emanote", - "ema", - "flake-utils" - ], - "heist": "heist_9", - "ixset-typed": "ixset-typed_9", - "nixpkgs": [ - "plutarch-safe-money", - "plutarch-numeric", - "plutarch", - "emanote", - "ema", - "nixpkgs" - ], - "pandoc-link-context": "pandoc-link-context_9", - "pathtree": "pathtree", - "tailwind-haskell": "tailwind-haskell_9", - "unionmount": "unionmount" - }, + "flake-utils_8": { "locked": { - "lastModified": 1651699367, - "narHash": "sha256-f+whlGwxzv5Lcem+rxBgIgnkU+KcckogtWbRwZ6nM4I=", - "owner": "srid", - "repo": "emanote", - "rev": "2b6558fde2999ec22f645cb95322995b780f09f1", + "lastModified": 1644229661, + "narHash": "sha256-1YdnJAsNy69bpcjuoKdOYQX0YxZBiCYZo4Twxerqv7k=", + "owner": "numtide", + "repo": "flake-utils", + "rev": "3cecb5b042f7f209c56ffd8371b2711a290ec797", "type": "github" }, "original": { - "owner": "srid", - "ref": "master", - "repo": "emanote", + "owner": "numtide", + "repo": "flake-utils", "type": "github" } }, - "flake-compat": { - "flake": false, + "flake-utils_9": { "locked": { - "lastModified": 1650374568, - "narHash": "sha256-Z+s0J8/r907g149rllvwhb4pKi8Wam5ij0st8PwAh+E=", - "owner": "edolstra", - "repo": "flake-compat", - "rev": "b4a34015c698c7793d592d66adbab377907a2be8", + "lastModified": 1644229661, + "narHash": "sha256-1YdnJAsNy69bpcjuoKdOYQX0YxZBiCYZo4Twxerqv7k=", + "owner": "numtide", + "repo": "flake-utils", + "rev": "3cecb5b042f7f209c56ffd8371b2711a290ec797", "type": "github" }, "original": { - "owner": "edolstra", - "repo": "flake-compat", + "owner": "numtide", + "repo": "flake-utils", "type": "github" } }, - "flake-compat_10": { + "flat": { "flake": false, "locked": { - "lastModified": 1641205782, - "narHash": "sha256-4jY7RCWUoZ9cKD8co0/4tFARpWB+57+r1bLLvXNJliY=", - "owner": "edolstra", - "repo": "flake-compat", - "rev": "b7547d3eed6f32d06102ead8991ec52ab0a4f1a7", + "lastModified": 1651403785, + "narHash": "sha256-g+jGep1IXdw4q01W67J6f6OODY91QzIlW1+Eu8pR+u0=", + "owner": "Quid2", + "repo": "flat", + "rev": "559617e058098b776b431e2a67346ad3adea2440", "type": "github" }, "original": { - "owner": "edolstra", - "repo": "flake-compat", + "owner": "Quid2", + "repo": "flat", "type": "github" } }, - "flake-compat_11": { + "flat_10": { "flake": false, "locked": { - "lastModified": 1650374568, - "narHash": "sha256-Z+s0J8/r907g149rllvwhb4pKi8Wam5ij0st8PwAh+E=", - "owner": "edolstra", - "repo": "flake-compat", - "rev": "b4a34015c698c7793d592d66adbab377907a2be8", + "lastModified": 1651403785, + "narHash": "sha256-g+jGep1IXdw4q01W67J6f6OODY91QzIlW1+Eu8pR+u0=", + "owner": "Quid2", + "repo": "flat", + "rev": "559617e058098b776b431e2a67346ad3adea2440", "type": "github" }, "original": { - "owner": "edolstra", - "repo": "flake-compat", + "owner": "Quid2", + "repo": "flat", "type": "github" } }, - "flake-compat_12": { + "flat_11": { "flake": false, "locked": { - "lastModified": 1641205782, - "narHash": "sha256-4jY7RCWUoZ9cKD8co0/4tFARpWB+57+r1bLLvXNJliY=", - "owner": "edolstra", - "repo": "flake-compat", - "rev": "b7547d3eed6f32d06102ead8991ec52ab0a4f1a7", + "lastModified": 1651403785, + "narHash": "sha256-g+jGep1IXdw4q01W67J6f6OODY91QzIlW1+Eu8pR+u0=", + "owner": "Quid2", + "repo": "flat", + "rev": "559617e058098b776b431e2a67346ad3adea2440", "type": "github" }, "original": { - "owner": "edolstra", - "repo": "flake-compat", + "owner": "Quid2", + "repo": "flat", "type": "github" } }, - "flake-compat_13": { + "flat_12": { "flake": false, "locked": { - "lastModified": 1650374568, - "narHash": "sha256-Z+s0J8/r907g149rllvwhb4pKi8Wam5ij0st8PwAh+E=", - "owner": "edolstra", - "repo": "flake-compat", - "rev": "b4a34015c698c7793d592d66adbab377907a2be8", + "lastModified": 1651403785, + "narHash": "sha256-g+jGep1IXdw4q01W67J6f6OODY91QzIlW1+Eu8pR+u0=", + "owner": "Quid2", + "repo": "flat", + "rev": "559617e058098b776b431e2a67346ad3adea2440", "type": "github" }, "original": { - "owner": "edolstra", - "repo": "flake-compat", + "owner": "Quid2", + "repo": "flat", "type": "github" } }, - "flake-compat_14": { + "flat_13": { "flake": false, "locked": { - "lastModified": 1641205782, - "narHash": "sha256-4jY7RCWUoZ9cKD8co0/4tFARpWB+57+r1bLLvXNJliY=", - "owner": "edolstra", - "repo": "flake-compat", - "rev": "b7547d3eed6f32d06102ead8991ec52ab0a4f1a7", + "lastModified": 1651403785, + "narHash": "sha256-g+jGep1IXdw4q01W67J6f6OODY91QzIlW1+Eu8pR+u0=", + "owner": "Quid2", + "repo": "flat", + "rev": "559617e058098b776b431e2a67346ad3adea2440", "type": "github" }, "original": { - "owner": "edolstra", - "repo": "flake-compat", + "owner": "Quid2", + "repo": "flat", "type": "github" } }, - "flake-compat_15": { + "flat_14": { "flake": false, "locked": { - "lastModified": 1650374568, - "narHash": "sha256-Z+s0J8/r907g149rllvwhb4pKi8Wam5ij0st8PwAh+E=", - "owner": "edolstra", - "repo": "flake-compat", - "rev": "b4a34015c698c7793d592d66adbab377907a2be8", + "lastModified": 1651403785, + "narHash": "sha256-g+jGep1IXdw4q01W67J6f6OODY91QzIlW1+Eu8pR+u0=", + "owner": "Quid2", + "repo": "flat", + "rev": "559617e058098b776b431e2a67346ad3adea2440", "type": "github" }, "original": { - "owner": "edolstra", - "repo": "flake-compat", + "owner": "Quid2", + "repo": "flat", "type": "github" } }, - "flake-compat_16": { + "flat_15": { "flake": false, "locked": { - "lastModified": 1641205782, - "narHash": "sha256-4jY7RCWUoZ9cKD8co0/4tFARpWB+57+r1bLLvXNJliY=", - "owner": "edolstra", - "repo": "flake-compat", - "rev": "b7547d3eed6f32d06102ead8991ec52ab0a4f1a7", + "lastModified": 1651403785, + "narHash": "sha256-g+jGep1IXdw4q01W67J6f6OODY91QzIlW1+Eu8pR+u0=", + "owner": "Quid2", + "repo": "flat", + "rev": "559617e058098b776b431e2a67346ad3adea2440", "type": "github" }, "original": { - "owner": "edolstra", - "repo": "flake-compat", + "owner": "Quid2", + "repo": "flat", "type": "github" } }, - "flake-compat_17": { + "flat_2": { "flake": false, "locked": { - "lastModified": 1648199409, - "narHash": "sha256-JwPKdC2PoVBkG6E+eWw3j6BMR6sL3COpYWfif7RVb8Y=", - "owner": "edolstra", - "repo": "flake-compat", - "rev": "64a525ee38886ab9028e6f61790de0832aa3ef03", + "lastModified": 1651403785, + "narHash": "sha256-g+jGep1IXdw4q01W67J6f6OODY91QzIlW1+Eu8pR+u0=", + "owner": "Quid2", + "repo": "flat", + "rev": "559617e058098b776b431e2a67346ad3adea2440", "type": "github" }, "original": { - "owner": "edolstra", - "repo": "flake-compat", + "owner": "Quid2", + "repo": "flat", "type": "github" } }, - "flake-compat_18": { + "flat_3": { "flake": false, "locked": { - "lastModified": 1641205782, - "narHash": "sha256-4jY7RCWUoZ9cKD8co0/4tFARpWB+57+r1bLLvXNJliY=", - "owner": "edolstra", - "repo": "flake-compat", - "rev": "b7547d3eed6f32d06102ead8991ec52ab0a4f1a7", + "lastModified": 1651403785, + "narHash": "sha256-g+jGep1IXdw4q01W67J6f6OODY91QzIlW1+Eu8pR+u0=", + "owner": "Quid2", + "repo": "flat", + "rev": "559617e058098b776b431e2a67346ad3adea2440", "type": "github" }, "original": { - "owner": "edolstra", - "repo": "flake-compat", + "owner": "Quid2", + "repo": "flat", "type": "github" } }, - "flake-compat_19": { + "flat_4": { "flake": false, "locked": { - "lastModified": 1641205782, - "narHash": "sha256-4jY7RCWUoZ9cKD8co0/4tFARpWB+57+r1bLLvXNJliY=", - "owner": "edolstra", - "repo": "flake-compat", - "rev": "b7547d3eed6f32d06102ead8991ec52ab0a4f1a7", + "lastModified": 1651403785, + "narHash": "sha256-g+jGep1IXdw4q01W67J6f6OODY91QzIlW1+Eu8pR+u0=", + "owner": "Quid2", + "repo": "flat", + "rev": "559617e058098b776b431e2a67346ad3adea2440", "type": "github" }, "original": { - "owner": "edolstra", - "repo": "flake-compat", + "owner": "Quid2", + "repo": "flat", "type": "github" } }, - "flake-compat_2": { + "flat_5": { "flake": false, "locked": { - "lastModified": 1641205782, - "narHash": "sha256-4jY7RCWUoZ9cKD8co0/4tFARpWB+57+r1bLLvXNJliY=", - "owner": "edolstra", - "repo": "flake-compat", - "rev": "b7547d3eed6f32d06102ead8991ec52ab0a4f1a7", + "lastModified": 1651403785, + "narHash": "sha256-g+jGep1IXdw4q01W67J6f6OODY91QzIlW1+Eu8pR+u0=", + "owner": "Quid2", + "repo": "flat", + "rev": "559617e058098b776b431e2a67346ad3adea2440", "type": "github" }, "original": { - "owner": "edolstra", - "repo": "flake-compat", + "owner": "Quid2", + "repo": "flat", "type": "github" } }, - "flake-compat_20": { + "flat_6": { "flake": false, "locked": { - "lastModified": 1627913399, - "narHash": "sha256-hY8g6H2KFL8ownSiFeMOjwPC8P0ueXpCVEbxgda3pko=", - "owner": "edolstra", - "repo": "flake-compat", - "rev": "12c64ca55c1014cdc1b16ed5a804aa8576601ff2", + "lastModified": 1651403785, + "narHash": "sha256-g+jGep1IXdw4q01W67J6f6OODY91QzIlW1+Eu8pR+u0=", + "owner": "Quid2", + "repo": "flat", + "rev": "559617e058098b776b431e2a67346ad3adea2440", "type": "github" }, "original": { - "owner": "edolstra", - "repo": "flake-compat", + "owner": "Quid2", + "repo": "flat", "type": "github" } }, - "flake-compat_3": { + "flat_7": { "flake": false, "locked": { - "lastModified": 1650374568, - "narHash": "sha256-Z+s0J8/r907g149rllvwhb4pKi8Wam5ij0st8PwAh+E=", - "owner": "edolstra", - "repo": "flake-compat", - "rev": "b4a34015c698c7793d592d66adbab377907a2be8", + "lastModified": 1651403785, + "narHash": "sha256-g+jGep1IXdw4q01W67J6f6OODY91QzIlW1+Eu8pR+u0=", + "owner": "Quid2", + "repo": "flat", + "rev": "559617e058098b776b431e2a67346ad3adea2440", "type": "github" }, "original": { - "owner": "edolstra", - "repo": "flake-compat", + "owner": "Quid2", + "repo": "flat", "type": "github" } }, - "flake-compat_4": { + "flat_8": { "flake": false, "locked": { - "lastModified": 1641205782, - "narHash": "sha256-4jY7RCWUoZ9cKD8co0/4tFARpWB+57+r1bLLvXNJliY=", - "owner": "edolstra", - "repo": "flake-compat", - "rev": "b7547d3eed6f32d06102ead8991ec52ab0a4f1a7", + "lastModified": 1651403785, + "narHash": "sha256-g+jGep1IXdw4q01W67J6f6OODY91QzIlW1+Eu8pR+u0=", + "owner": "Quid2", + "repo": "flat", + "rev": "559617e058098b776b431e2a67346ad3adea2440", "type": "github" }, "original": { - "owner": "edolstra", - "repo": "flake-compat", + "owner": "Quid2", + "repo": "flat", "type": "github" } }, - "flake-compat_5": { + "flat_9": { "flake": false, "locked": { - "lastModified": 1650374568, - "narHash": "sha256-Z+s0J8/r907g149rllvwhb4pKi8Wam5ij0st8PwAh+E=", - "owner": "edolstra", - "repo": "flake-compat", - "rev": "b4a34015c698c7793d592d66adbab377907a2be8", + "lastModified": 1651403785, + "narHash": "sha256-g+jGep1IXdw4q01W67J6f6OODY91QzIlW1+Eu8pR+u0=", + "owner": "Quid2", + "repo": "flat", + "rev": "559617e058098b776b431e2a67346ad3adea2440", "type": "github" }, "original": { - "owner": "edolstra", - "repo": "flake-compat", + "owner": "Quid2", + "repo": "flat", "type": "github" } }, - "flake-compat_6": { + "ghc-8.6.5-iohk": { "flake": false, "locked": { - "lastModified": 1641205782, - "narHash": "sha256-4jY7RCWUoZ9cKD8co0/4tFARpWB+57+r1bLLvXNJliY=", - "owner": "edolstra", - "repo": "flake-compat", - "rev": "b7547d3eed6f32d06102ead8991ec52ab0a4f1a7", + "lastModified": 1600920045, + "narHash": "sha256-DO6kxJz248djebZLpSzTGD6s8WRpNI9BTwUeOf5RwY8=", + "owner": "input-output-hk", + "repo": "ghc", + "rev": "95713a6ecce4551240da7c96b6176f980af75cae", "type": "github" }, "original": { - "owner": "edolstra", - "repo": "flake-compat", + "owner": "input-output-hk", + "ref": "release/8.6.5-iohk", + "repo": "ghc", "type": "github" } }, - "flake-compat_7": { + "ghc-8.6.5-iohk_10": { "flake": false, "locked": { - "lastModified": 1650374568, - "narHash": "sha256-Z+s0J8/r907g149rllvwhb4pKi8Wam5ij0st8PwAh+E=", - "owner": "edolstra", - "repo": "flake-compat", - "rev": "b4a34015c698c7793d592d66adbab377907a2be8", + "lastModified": 1600920045, + "narHash": "sha256-DO6kxJz248djebZLpSzTGD6s8WRpNI9BTwUeOf5RwY8=", + "owner": "input-output-hk", + "repo": "ghc", + "rev": "95713a6ecce4551240da7c96b6176f980af75cae", "type": "github" }, "original": { - "owner": "edolstra", - "repo": "flake-compat", + "owner": "input-output-hk", + "ref": "release/8.6.5-iohk", + "repo": "ghc", "type": "github" } }, - "flake-compat_8": { + "ghc-8.6.5-iohk_11": { "flake": false, "locked": { - "lastModified": 1641205782, - "narHash": "sha256-4jY7RCWUoZ9cKD8co0/4tFARpWB+57+r1bLLvXNJliY=", - "owner": "edolstra", - "repo": "flake-compat", - "rev": "b7547d3eed6f32d06102ead8991ec52ab0a4f1a7", + "lastModified": 1600920045, + "narHash": "sha256-DO6kxJz248djebZLpSzTGD6s8WRpNI9BTwUeOf5RwY8=", + "owner": "input-output-hk", + "repo": "ghc", + "rev": "95713a6ecce4551240da7c96b6176f980af75cae", "type": "github" }, "original": { - "owner": "edolstra", - "repo": "flake-compat", + "owner": "input-output-hk", + "ref": "release/8.6.5-iohk", + "repo": "ghc", "type": "github" } }, - "flake-compat_9": { + "ghc-8.6.5-iohk_12": { "flake": false, "locked": { - "lastModified": 1650374568, - "narHash": "sha256-Z+s0J8/r907g149rllvwhb4pKi8Wam5ij0st8PwAh+E=", - "owner": "edolstra", - "repo": "flake-compat", - "rev": "b4a34015c698c7793d592d66adbab377907a2be8", + "lastModified": 1600920045, + "narHash": "sha256-DO6kxJz248djebZLpSzTGD6s8WRpNI9BTwUeOf5RwY8=", + "owner": "input-output-hk", + "repo": "ghc", + "rev": "95713a6ecce4551240da7c96b6176f980af75cae", "type": "github" }, "original": { - "owner": "edolstra", - "repo": "flake-compat", + "owner": "input-output-hk", + "ref": "release/8.6.5-iohk", + "repo": "ghc", "type": "github" } }, - "flake-utils": { + "ghc-8.6.5-iohk_13": { + "flake": false, "locked": { - "lastModified": 1652776076, - "narHash": "sha256-gzTw/v1vj4dOVbpBSJX4J0DwUR6LIyXo7/SuuTJp1kM=", - "owner": "numtide", - "repo": "flake-utils", - "rev": "04c1b180862888302ddfb2e3ad9eaa63afc60cf8", + "lastModified": 1600920045, + "narHash": "sha256-DO6kxJz248djebZLpSzTGD6s8WRpNI9BTwUeOf5RwY8=", + "owner": "input-output-hk", + "repo": "ghc", + "rev": "95713a6ecce4551240da7c96b6176f980af75cae", "type": "github" }, "original": { - "owner": "numtide", - "ref": "v1.0.0", - "repo": "flake-utils", + "owner": "input-output-hk", + "ref": "release/8.6.5-iohk", + "repo": "ghc", "type": "github" } }, - "flake-utils_10": { + "ghc-8.6.5-iohk_14": { + "flake": false, "locked": { - "lastModified": 1644229661, - "narHash": "sha256-1YdnJAsNy69bpcjuoKdOYQX0YxZBiCYZo4Twxerqv7k=", - "owner": "numtide", - "repo": "flake-utils", - "rev": "3cecb5b042f7f209c56ffd8371b2711a290ec797", + "lastModified": 1600920045, + "narHash": "sha256-DO6kxJz248djebZLpSzTGD6s8WRpNI9BTwUeOf5RwY8=", + "owner": "input-output-hk", + "repo": "ghc", + "rev": "95713a6ecce4551240da7c96b6176f980af75cae", "type": "github" }, "original": { - "owner": "numtide", - "repo": "flake-utils", + "owner": "input-output-hk", + "ref": "release/8.6.5-iohk", + "repo": "ghc", "type": "github" } }, - "flake-utils_11": { + "ghc-8.6.5-iohk_15": { + "flake": false, "locked": { - "lastModified": 1652776076, - "narHash": "sha256-gzTw/v1vj4dOVbpBSJX4J0DwUR6LIyXo7/SuuTJp1kM=", - "owner": "numtide", - "repo": "flake-utils", - "rev": "04c1b180862888302ddfb2e3ad9eaa63afc60cf8", + "lastModified": 1600920045, + "narHash": "sha256-DO6kxJz248djebZLpSzTGD6s8WRpNI9BTwUeOf5RwY8=", + "owner": "input-output-hk", + "repo": "ghc", + "rev": "95713a6ecce4551240da7c96b6176f980af75cae", "type": "github" }, "original": { - "owner": "numtide", - "ref": "v1.0.0", - "repo": "flake-utils", + "owner": "input-output-hk", + "ref": "release/8.6.5-iohk", + "repo": "ghc", "type": "github" } }, - "flake-utils_12": { + "ghc-8.6.5-iohk_2": { + "flake": false, "locked": { - "lastModified": 1652776076, - "narHash": "sha256-gzTw/v1vj4dOVbpBSJX4J0DwUR6LIyXo7/SuuTJp1kM=", - "owner": "numtide", - "repo": "flake-utils", - "rev": "04c1b180862888302ddfb2e3ad9eaa63afc60cf8", + "lastModified": 1600920045, + "narHash": "sha256-DO6kxJz248djebZLpSzTGD6s8WRpNI9BTwUeOf5RwY8=", + "owner": "input-output-hk", + "repo": "ghc", + "rev": "95713a6ecce4551240da7c96b6176f980af75cae", "type": "github" }, "original": { - "owner": "numtide", - "ref": "v1.0.0", - "repo": "flake-utils", + "owner": "input-output-hk", + "ref": "release/8.6.5-iohk", + "repo": "ghc", "type": "github" } }, - "flake-utils_13": { + "ghc-8.6.5-iohk_3": { + "flake": false, "locked": { - "lastModified": 1644229661, - "narHash": "sha256-1YdnJAsNy69bpcjuoKdOYQX0YxZBiCYZo4Twxerqv7k=", - "owner": "numtide", - "repo": "flake-utils", - "rev": "3cecb5b042f7f209c56ffd8371b2711a290ec797", + "lastModified": 1600920045, + "narHash": "sha256-DO6kxJz248djebZLpSzTGD6s8WRpNI9BTwUeOf5RwY8=", + "owner": "input-output-hk", + "repo": "ghc", + "rev": "95713a6ecce4551240da7c96b6176f980af75cae", "type": "github" }, "original": { - "owner": "numtide", - "repo": "flake-utils", + "owner": "input-output-hk", + "ref": "release/8.6.5-iohk", + "repo": "ghc", "type": "github" } }, - "flake-utils_14": { + "ghc-8.6.5-iohk_4": { + "flake": false, "locked": { - "lastModified": 1652776076, - "narHash": "sha256-gzTw/v1vj4dOVbpBSJX4J0DwUR6LIyXo7/SuuTJp1kM=", - "owner": "numtide", - "repo": "flake-utils", - "rev": "04c1b180862888302ddfb2e3ad9eaa63afc60cf8", + "lastModified": 1600920045, + "narHash": "sha256-DO6kxJz248djebZLpSzTGD6s8WRpNI9BTwUeOf5RwY8=", + "owner": "input-output-hk", + "repo": "ghc", + "rev": "95713a6ecce4551240da7c96b6176f980af75cae", "type": "github" }, "original": { - "owner": "numtide", - "ref": "v1.0.0", - "repo": "flake-utils", + "owner": "input-output-hk", + "ref": "release/8.6.5-iohk", + "repo": "ghc", "type": "github" } }, - "flake-utils_15": { + "ghc-8.6.5-iohk_5": { + "flake": false, "locked": { - "lastModified": 1652776076, - "narHash": "sha256-gzTw/v1vj4dOVbpBSJX4J0DwUR6LIyXo7/SuuTJp1kM=", - "owner": "numtide", - "repo": "flake-utils", - "rev": "04c1b180862888302ddfb2e3ad9eaa63afc60cf8", + "lastModified": 1600920045, + "narHash": "sha256-DO6kxJz248djebZLpSzTGD6s8WRpNI9BTwUeOf5RwY8=", + "owner": "input-output-hk", + "repo": "ghc", + "rev": "95713a6ecce4551240da7c96b6176f980af75cae", "type": "github" }, "original": { - "owner": "numtide", - "ref": "v1.0.0", - "repo": "flake-utils", + "owner": "input-output-hk", + "ref": "release/8.6.5-iohk", + "repo": "ghc", "type": "github" } }, - "flake-utils_16": { + "ghc-8.6.5-iohk_6": { + "flake": false, "locked": { - "lastModified": 1644229661, - "narHash": "sha256-1YdnJAsNy69bpcjuoKdOYQX0YxZBiCYZo4Twxerqv7k=", - "owner": "numtide", - "repo": "flake-utils", - "rev": "3cecb5b042f7f209c56ffd8371b2711a290ec797", + "lastModified": 1600920045, + "narHash": "sha256-DO6kxJz248djebZLpSzTGD6s8WRpNI9BTwUeOf5RwY8=", + "owner": "input-output-hk", + "repo": "ghc", + "rev": "95713a6ecce4551240da7c96b6176f980af75cae", "type": "github" }, "original": { - "owner": "numtide", - "repo": "flake-utils", + "owner": "input-output-hk", + "ref": "release/8.6.5-iohk", + "repo": "ghc", "type": "github" } }, - "flake-utils_17": { + "ghc-8.6.5-iohk_7": { + "flake": false, "locked": { - "lastModified": 1652776076, - "narHash": "sha256-gzTw/v1vj4dOVbpBSJX4J0DwUR6LIyXo7/SuuTJp1kM=", - "owner": "numtide", - "repo": "flake-utils", - "rev": "04c1b180862888302ddfb2e3ad9eaa63afc60cf8", + "lastModified": 1600920045, + "narHash": "sha256-DO6kxJz248djebZLpSzTGD6s8WRpNI9BTwUeOf5RwY8=", + "owner": "input-output-hk", + "repo": "ghc", + "rev": "95713a6ecce4551240da7c96b6176f980af75cae", "type": "github" }, "original": { - "owner": "numtide", - "ref": "v1.0.0", - "repo": "flake-utils", + "owner": "input-output-hk", + "ref": "release/8.6.5-iohk", + "repo": "ghc", "type": "github" } }, - "flake-utils_18": { + "ghc-8.6.5-iohk_8": { + "flake": false, "locked": { - "lastModified": 1652776076, - "narHash": "sha256-gzTw/v1vj4dOVbpBSJX4J0DwUR6LIyXo7/SuuTJp1kM=", - "owner": "numtide", - "repo": "flake-utils", - "rev": "04c1b180862888302ddfb2e3ad9eaa63afc60cf8", + "lastModified": 1600920045, + "narHash": "sha256-DO6kxJz248djebZLpSzTGD6s8WRpNI9BTwUeOf5RwY8=", + "owner": "input-output-hk", + "repo": "ghc", + "rev": "95713a6ecce4551240da7c96b6176f980af75cae", "type": "github" }, "original": { - "owner": "numtide", - "ref": "v1.0.0", - "repo": "flake-utils", + "owner": "input-output-hk", + "ref": "release/8.6.5-iohk", + "repo": "ghc", "type": "github" } }, - "flake-utils_19": { + "ghc-8.6.5-iohk_9": { + "flake": false, "locked": { - "lastModified": 1644229661, - "narHash": "sha256-1YdnJAsNy69bpcjuoKdOYQX0YxZBiCYZo4Twxerqv7k=", - "owner": "numtide", - "repo": "flake-utils", - "rev": "3cecb5b042f7f209c56ffd8371b2711a290ec797", + "lastModified": 1600920045, + "narHash": "sha256-DO6kxJz248djebZLpSzTGD6s8WRpNI9BTwUeOf5RwY8=", + "owner": "input-output-hk", + "repo": "ghc", + "rev": "95713a6ecce4551240da7c96b6176f980af75cae", "type": "github" }, "original": { - "owner": "numtide", - "repo": "flake-utils", + "owner": "input-output-hk", + "ref": "release/8.6.5-iohk", + "repo": "ghc", "type": "github" } }, - "flake-utils_2": { + "gitignore-nix": { + "flake": false, "locked": { - "lastModified": 1652776076, - "narHash": "sha256-gzTw/v1vj4dOVbpBSJX4J0DwUR6LIyXo7/SuuTJp1kM=", - "owner": "numtide", - "repo": "flake-utils", - "rev": "04c1b180862888302ddfb2e3ad9eaa63afc60cf8", + "lastModified": 1611672876, + "narHash": "sha256-qHu3uZ/o9jBHiA3MEKHJ06k7w4heOhA+4HCSIvflRxo=", + "owner": "hercules-ci", + "repo": "gitignore.nix", + "rev": "211907489e9f198594c0eb0ca9256a1949c9d412", "type": "github" }, "original": { - "owner": "numtide", - "ref": "v1.0.0", - "repo": "flake-utils", + "owner": "hercules-ci", + "repo": "gitignore.nix", "type": "github" } }, - "flake-utils_20": { + "gitignore-nix_10": { + "flake": false, "locked": { - "lastModified": 1652776076, - "narHash": "sha256-gzTw/v1vj4dOVbpBSJX4J0DwUR6LIyXo7/SuuTJp1kM=", - "owner": "numtide", - "repo": "flake-utils", - "rev": "04c1b180862888302ddfb2e3ad9eaa63afc60cf8", + "lastModified": 1611672876, + "narHash": "sha256-qHu3uZ/o9jBHiA3MEKHJ06k7w4heOhA+4HCSIvflRxo=", + "owner": "hercules-ci", + "repo": "gitignore.nix", + "rev": "211907489e9f198594c0eb0ca9256a1949c9d412", "type": "github" }, "original": { - "owner": "numtide", - "ref": "v1.0.0", - "repo": "flake-utils", + "owner": "hercules-ci", + "repo": "gitignore.nix", "type": "github" } }, - "flake-utils_21": { + "gitignore-nix_11": { + "flake": false, "locked": { - "lastModified": 1652776076, - "narHash": "sha256-gzTw/v1vj4dOVbpBSJX4J0DwUR6LIyXo7/SuuTJp1kM=", - "owner": "numtide", - "repo": "flake-utils", - "rev": "04c1b180862888302ddfb2e3ad9eaa63afc60cf8", + "lastModified": 1611672876, + "narHash": "sha256-qHu3uZ/o9jBHiA3MEKHJ06k7w4heOhA+4HCSIvflRxo=", + "owner": "hercules-ci", + "repo": "gitignore.nix", + "rev": "211907489e9f198594c0eb0ca9256a1949c9d412", "type": "github" }, "original": { - "owner": "numtide", - "ref": "v1.0.0", - "repo": "flake-utils", + "owner": "hercules-ci", + "repo": "gitignore.nix", "type": "github" } }, - "flake-utils_22": { + "gitignore-nix_12": { + "flake": false, "locked": { - "lastModified": 1644229661, - "narHash": "sha256-1YdnJAsNy69bpcjuoKdOYQX0YxZBiCYZo4Twxerqv7k=", - "owner": "numtide", - "repo": "flake-utils", - "rev": "3cecb5b042f7f209c56ffd8371b2711a290ec797", + "lastModified": 1611672876, + "narHash": "sha256-qHu3uZ/o9jBHiA3MEKHJ06k7w4heOhA+4HCSIvflRxo=", + "owner": "hercules-ci", + "repo": "gitignore.nix", + "rev": "211907489e9f198594c0eb0ca9256a1949c9d412", "type": "github" }, "original": { - "owner": "numtide", - "repo": "flake-utils", + "owner": "hercules-ci", + "repo": "gitignore.nix", "type": "github" } }, - "flake-utils_23": { + "gitignore-nix_13": { + "flake": false, "locked": { - "lastModified": 1652776076, - "narHash": "sha256-gzTw/v1vj4dOVbpBSJX4J0DwUR6LIyXo7/SuuTJp1kM=", - "owner": "numtide", - "repo": "flake-utils", - "rev": "04c1b180862888302ddfb2e3ad9eaa63afc60cf8", + "lastModified": 1611672876, + "narHash": "sha256-qHu3uZ/o9jBHiA3MEKHJ06k7w4heOhA+4HCSIvflRxo=", + "owner": "hercules-ci", + "repo": "gitignore.nix", + "rev": "211907489e9f198594c0eb0ca9256a1949c9d412", "type": "github" }, "original": { - "owner": "numtide", - "ref": "v1.0.0", - "repo": "flake-utils", + "owner": "hercules-ci", + "repo": "gitignore.nix", "type": "github" } }, - "flake-utils_24": { + "gitignore-nix_14": { + "flake": false, "locked": { - "lastModified": 1652776076, - "narHash": "sha256-gzTw/v1vj4dOVbpBSJX4J0DwUR6LIyXo7/SuuTJp1kM=", - "owner": "numtide", - "repo": "flake-utils", - "rev": "04c1b180862888302ddfb2e3ad9eaa63afc60cf8", + "lastModified": 1611672876, + "narHash": "sha256-qHu3uZ/o9jBHiA3MEKHJ06k7w4heOhA+4HCSIvflRxo=", + "owner": "hercules-ci", + "repo": "gitignore.nix", + "rev": "211907489e9f198594c0eb0ca9256a1949c9d412", "type": "github" }, "original": { - "owner": "numtide", - "ref": "v1.0.0", - "repo": "flake-utils", + "owner": "hercules-ci", + "repo": "gitignore.nix", "type": "github" } }, - "flake-utils_25": { + "gitignore-nix_15": { + "flake": false, "locked": { - "lastModified": 1644229661, - "narHash": "sha256-1YdnJAsNy69bpcjuoKdOYQX0YxZBiCYZo4Twxerqv7k=", - "owner": "numtide", - "repo": "flake-utils", - "rev": "3cecb5b042f7f209c56ffd8371b2711a290ec797", + "lastModified": 1611672876, + "narHash": "sha256-qHu3uZ/o9jBHiA3MEKHJ06k7w4heOhA+4HCSIvflRxo=", + "owner": "hercules-ci", + "repo": "gitignore.nix", + "rev": "211907489e9f198594c0eb0ca9256a1949c9d412", "type": "github" }, "original": { - "owner": "numtide", - "repo": "flake-utils", + "owner": "hercules-ci", + "repo": "gitignore.nix", "type": "github" } }, - "flake-utils_26": { + "gitignore-nix_2": { + "flake": false, "locked": { - "lastModified": 1648297722, - "narHash": "sha256-W+qlPsiZd8F3XkzXOzAoR+mpFqzm3ekQkJNa+PIh1BQ=", - "owner": "numtide", - "repo": "flake-utils", - "rev": "0f8662f1319ad6abf89b3380dd2722369fc51ade", + "lastModified": 1611672876, + "narHash": "sha256-qHu3uZ/o9jBHiA3MEKHJ06k7w4heOhA+4HCSIvflRxo=", + "owner": "hercules-ci", + "repo": "gitignore.nix", + "rev": "211907489e9f198594c0eb0ca9256a1949c9d412", "type": "github" }, "original": { - "owner": "numtide", - "repo": "flake-utils", + "owner": "hercules-ci", + "repo": "gitignore.nix", "type": "github" } }, - "flake-utils_27": { + "gitignore-nix_3": { + "flake": false, "locked": { - "lastModified": 1644229661, - "narHash": "sha256-1YdnJAsNy69bpcjuoKdOYQX0YxZBiCYZo4Twxerqv7k=", - "owner": "numtide", - "repo": "flake-utils", - "rev": "3cecb5b042f7f209c56ffd8371b2711a290ec797", + "lastModified": 1611672876, + "narHash": "sha256-qHu3uZ/o9jBHiA3MEKHJ06k7w4heOhA+4HCSIvflRxo=", + "owner": "hercules-ci", + "repo": "gitignore.nix", + "rev": "211907489e9f198594c0eb0ca9256a1949c9d412", "type": "github" }, "original": { - "owner": "numtide", - "repo": "flake-utils", + "owner": "hercules-ci", + "repo": "gitignore.nix", "type": "github" } }, - "flake-utils_28": { + "gitignore-nix_4": { + "flake": false, "locked": { - "lastModified": 1642700792, - "narHash": "sha256-XqHrk7hFb+zBvRg6Ghl+AZDq03ov6OshJLiSWOoX5es=", - "owner": "numtide", - "repo": "flake-utils", - "rev": "846b2ae0fc4cc943637d3d1def4454213e203cba", + "lastModified": 1611672876, + "narHash": "sha256-qHu3uZ/o9jBHiA3MEKHJ06k7w4heOhA+4HCSIvflRxo=", + "owner": "hercules-ci", + "repo": "gitignore.nix", + "rev": "211907489e9f198594c0eb0ca9256a1949c9d412", "type": "github" }, "original": { - "owner": "numtide", - "repo": "flake-utils", + "owner": "hercules-ci", + "repo": "gitignore.nix", "type": "github" } }, - "flake-utils_29": { + "gitignore-nix_5": { + "flake": false, "locked": { - "lastModified": 1642700792, - "narHash": "sha256-XqHrk7hFb+zBvRg6Ghl+AZDq03ov6OshJLiSWOoX5es=", - "owner": "numtide", - "repo": "flake-utils", - "rev": "846b2ae0fc4cc943637d3d1def4454213e203cba", + "lastModified": 1611672876, + "narHash": "sha256-qHu3uZ/o9jBHiA3MEKHJ06k7w4heOhA+4HCSIvflRxo=", + "owner": "hercules-ci", + "repo": "gitignore.nix", + "rev": "211907489e9f198594c0eb0ca9256a1949c9d412", "type": "github" }, "original": { - "owner": "numtide", - "repo": "flake-utils", + "owner": "hercules-ci", + "repo": "gitignore.nix", "type": "github" } }, - "flake-utils_3": { + "gitignore-nix_6": { + "flake": false, "locked": { - "lastModified": 1644229661, - "narHash": "sha256-1YdnJAsNy69bpcjuoKdOYQX0YxZBiCYZo4Twxerqv7k=", - "owner": "numtide", - "repo": "flake-utils", - "rev": "3cecb5b042f7f209c56ffd8371b2711a290ec797", + "lastModified": 1611672876, + "narHash": "sha256-qHu3uZ/o9jBHiA3MEKHJ06k7w4heOhA+4HCSIvflRxo=", + "owner": "hercules-ci", + "repo": "gitignore.nix", + "rev": "211907489e9f198594c0eb0ca9256a1949c9d412", "type": "github" }, "original": { - "owner": "numtide", - "repo": "flake-utils", + "owner": "hercules-ci", + "repo": "gitignore.nix", "type": "github" } }, - "flake-utils_30": { + "gitignore-nix_7": { + "flake": false, "locked": { - "lastModified": 1631561581, - "narHash": "sha256-3VQMV5zvxaVLvqqUrNz3iJelLw30mIVSfZmAaauM3dA=", - "owner": "numtide", - "repo": "flake-utils", - "rev": "7e5bf3925f6fbdfaf50a2a7ca0be2879c4261d19", + "lastModified": 1611672876, + "narHash": "sha256-qHu3uZ/o9jBHiA3MEKHJ06k7w4heOhA+4HCSIvflRxo=", + "owner": "hercules-ci", + "repo": "gitignore.nix", + "rev": "211907489e9f198594c0eb0ca9256a1949c9d412", "type": "github" }, "original": { - "owner": "numtide", - "repo": "flake-utils", + "owner": "hercules-ci", + "repo": "gitignore.nix", "type": "github" } }, - "flake-utils_31": { + "gitignore-nix_8": { + "flake": false, "locked": { - "lastModified": 1644229661, - "narHash": "sha256-1YdnJAsNy69bpcjuoKdOYQX0YxZBiCYZo4Twxerqv7k=", - "owner": "numtide", - "repo": "flake-utils", - "rev": "3cecb5b042f7f209c56ffd8371b2711a290ec797", + "lastModified": 1611672876, + "narHash": "sha256-qHu3uZ/o9jBHiA3MEKHJ06k7w4heOhA+4HCSIvflRxo=", + "owner": "hercules-ci", + "repo": "gitignore.nix", + "rev": "211907489e9f198594c0eb0ca9256a1949c9d412", "type": "github" }, "original": { - "owner": "numtide", - "repo": "flake-utils", + "owner": "hercules-ci", + "repo": "gitignore.nix", "type": "github" } }, - "flake-utils_4": { + "gitignore-nix_9": { + "flake": false, "locked": { - "lastModified": 1652776076, - "narHash": "sha256-gzTw/v1vj4dOVbpBSJX4J0DwUR6LIyXo7/SuuTJp1kM=", - "owner": "numtide", - "repo": "flake-utils", - "rev": "04c1b180862888302ddfb2e3ad9eaa63afc60cf8", + "lastModified": 1611672876, + "narHash": "sha256-qHu3uZ/o9jBHiA3MEKHJ06k7w4heOhA+4HCSIvflRxo=", + "owner": "hercules-ci", + "repo": "gitignore.nix", + "rev": "211907489e9f198594c0eb0ca9256a1949c9d412", "type": "github" }, "original": { - "owner": "numtide", - "ref": "v1.0.0", - "repo": "flake-utils", + "owner": "hercules-ci", + "repo": "gitignore.nix", "type": "github" } }, - "flake-utils_5": { + "hackage": { + "flake": false, "locked": { - "lastModified": 1652776076, - "narHash": "sha256-gzTw/v1vj4dOVbpBSJX4J0DwUR6LIyXo7/SuuTJp1kM=", - "owner": "numtide", - "repo": "flake-utils", - "rev": "04c1b180862888302ddfb2e3ad9eaa63afc60cf8", + "lastModified": 1654046237, + "narHash": "sha256-FpM9zE+Q+WrvCiaZBCg5U1g0bYpiZOCxY8V3R5ydBu8=", + "owner": "input-output-hk", + "repo": "hackage.nix", + "rev": "eeae1790b9c6a880d96e4a7214fdf0a73bdd6fc0", "type": "github" }, "original": { - "owner": "numtide", - "ref": "v1.0.0", - "repo": "flake-utils", + "owner": "input-output-hk", + "repo": "hackage.nix", "type": "github" } }, - "flake-utils_6": { + "hackage-nix": { + "flake": false, "locked": { - "lastModified": 1644229661, - "narHash": "sha256-1YdnJAsNy69bpcjuoKdOYQX0YxZBiCYZo4Twxerqv7k=", - "owner": "numtide", - "repo": "flake-utils", - "rev": "3cecb5b042f7f209c56ffd8371b2711a290ec797", + "lastModified": 1651108473, + "narHash": "sha256-zHGCnBdwKvrcYanjf3GARTWF8V2pyJl1QNONUNZSoc0=", + "owner": "input-output-hk", + "repo": "hackage.nix", + "rev": "dbab3b292c3400d028a2257e3acd2ac0249da774", "type": "github" }, "original": { - "owner": "numtide", - "repo": "flake-utils", + "owner": "input-output-hk", + "repo": "hackage.nix", "type": "github" } }, - "flake-utils_7": { + "hackage-nix_10": { + "flake": false, "locked": { - "lastModified": 1644229661, - "narHash": "sha256-1YdnJAsNy69bpcjuoKdOYQX0YxZBiCYZo4Twxerqv7k=", - "owner": "numtide", - "repo": "flake-utils", - "rev": "3cecb5b042f7f209c56ffd8371b2711a290ec797", + "lastModified": 1651108473, + "narHash": "sha256-zHGCnBdwKvrcYanjf3GARTWF8V2pyJl1QNONUNZSoc0=", + "owner": "input-output-hk", + "repo": "hackage.nix", + "rev": "dbab3b292c3400d028a2257e3acd2ac0249da774", "type": "github" }, "original": { - "owner": "numtide", - "repo": "flake-utils", + "owner": "input-output-hk", + "repo": "hackage.nix", "type": "github" } }, - "flake-utils_8": { + "hackage-nix_11": { + "flake": false, "locked": { - "lastModified": 1652776076, - "narHash": "sha256-gzTw/v1vj4dOVbpBSJX4J0DwUR6LIyXo7/SuuTJp1kM=", - "owner": "numtide", - "repo": "flake-utils", - "rev": "04c1b180862888302ddfb2e3ad9eaa63afc60cf8", + "lastModified": 1651108473, + "narHash": "sha256-zHGCnBdwKvrcYanjf3GARTWF8V2pyJl1QNONUNZSoc0=", + "owner": "input-output-hk", + "repo": "hackage.nix", + "rev": "dbab3b292c3400d028a2257e3acd2ac0249da774", "type": "github" }, "original": { - "owner": "numtide", - "ref": "v1.0.0", - "repo": "flake-utils", + "owner": "input-output-hk", + "repo": "hackage.nix", "type": "github" } }, - "flake-utils_9": { + "hackage-nix_12": { + "flake": false, "locked": { - "lastModified": 1652776076, - "narHash": "sha256-gzTw/v1vj4dOVbpBSJX4J0DwUR6LIyXo7/SuuTJp1kM=", - "owner": "numtide", - "repo": "flake-utils", - "rev": "04c1b180862888302ddfb2e3ad9eaa63afc60cf8", + "lastModified": 1651108473, + "narHash": "sha256-zHGCnBdwKvrcYanjf3GARTWF8V2pyJl1QNONUNZSoc0=", + "owner": "input-output-hk", + "repo": "hackage.nix", + "rev": "dbab3b292c3400d028a2257e3acd2ac0249da774", "type": "github" }, "original": { - "owner": "numtide", - "ref": "v1.0.0", - "repo": "flake-utils", + "owner": "input-output-hk", + "repo": "hackage.nix", "type": "github" } }, - "flat": { + "hackage-nix_13": { "flake": false, "locked": { - "lastModified": 1651403785, - "narHash": "sha256-g+jGep1IXdw4q01W67J6f6OODY91QzIlW1+Eu8pR+u0=", - "owner": "Quid2", - "repo": "flat", - "rev": "559617e058098b776b431e2a67346ad3adea2440", + "lastModified": 1651108473, + "narHash": "sha256-zHGCnBdwKvrcYanjf3GARTWF8V2pyJl1QNONUNZSoc0=", + "owner": "input-output-hk", + "repo": "hackage.nix", + "rev": "dbab3b292c3400d028a2257e3acd2ac0249da774", "type": "github" }, "original": { - "owner": "Quid2", - "repo": "flat", + "owner": "input-output-hk", + "repo": "hackage.nix", "type": "github" } }, - "flat_10": { + "hackage-nix_14": { "flake": false, "locked": { - "lastModified": 1641898475, - "narHash": "sha256-D7jJ4t0T1ZvXbO61r3HQj77hZ5hWF/P1L8X9+MnfD6c=", - "owner": "Quid2", - "repo": "flat", - "rev": "41a040c413351e021982bb78bd00f750628f8060", + "lastModified": 1651108473, + "narHash": "sha256-zHGCnBdwKvrcYanjf3GARTWF8V2pyJl1QNONUNZSoc0=", + "owner": "input-output-hk", + "repo": "hackage.nix", + "rev": "dbab3b292c3400d028a2257e3acd2ac0249da774", "type": "github" }, "original": { - "owner": "Quid2", - "repo": "flat", - "rev": "41a040c413351e021982bb78bd00f750628f8060", + "owner": "input-output-hk", + "repo": "hackage.nix", "type": "github" } }, - "flat_2": { + "hackage-nix_15": { "flake": false, "locked": { - "lastModified": 1651403785, - "narHash": "sha256-g+jGep1IXdw4q01W67J6f6OODY91QzIlW1+Eu8pR+u0=", - "owner": "Quid2", - "repo": "flat", - "rev": "559617e058098b776b431e2a67346ad3adea2440", + "lastModified": 1651108473, + "narHash": "sha256-zHGCnBdwKvrcYanjf3GARTWF8V2pyJl1QNONUNZSoc0=", + "owner": "input-output-hk", + "repo": "hackage.nix", + "rev": "dbab3b292c3400d028a2257e3acd2ac0249da774", "type": "github" }, "original": { - "owner": "Quid2", - "repo": "flat", + "owner": "input-output-hk", + "repo": "hackage.nix", "type": "github" } }, - "flat_3": { + "hackage-nix_2": { "flake": false, "locked": { - "lastModified": 1651403785, - "narHash": "sha256-g+jGep1IXdw4q01W67J6f6OODY91QzIlW1+Eu8pR+u0=", - "owner": "Quid2", - "repo": "flat", - "rev": "559617e058098b776b431e2a67346ad3adea2440", + "lastModified": 1651108473, + "narHash": "sha256-zHGCnBdwKvrcYanjf3GARTWF8V2pyJl1QNONUNZSoc0=", + "owner": "input-output-hk", + "repo": "hackage.nix", + "rev": "dbab3b292c3400d028a2257e3acd2ac0249da774", "type": "github" }, "original": { - "owner": "Quid2", - "repo": "flat", + "owner": "input-output-hk", + "repo": "hackage.nix", "type": "github" } }, - "flat_4": { + "hackage-nix_3": { "flake": false, "locked": { - "lastModified": 1651403785, - "narHash": "sha256-g+jGep1IXdw4q01W67J6f6OODY91QzIlW1+Eu8pR+u0=", - "owner": "Quid2", - "repo": "flat", - "rev": "559617e058098b776b431e2a67346ad3adea2440", + "lastModified": 1651108473, + "narHash": "sha256-zHGCnBdwKvrcYanjf3GARTWF8V2pyJl1QNONUNZSoc0=", + "owner": "input-output-hk", + "repo": "hackage.nix", + "rev": "dbab3b292c3400d028a2257e3acd2ac0249da774", "type": "github" }, "original": { - "owner": "Quid2", - "repo": "flat", + "owner": "input-output-hk", + "repo": "hackage.nix", "type": "github" } }, - "flat_5": { + "hackage-nix_4": { "flake": false, "locked": { - "lastModified": 1651403785, - "narHash": "sha256-g+jGep1IXdw4q01W67J6f6OODY91QzIlW1+Eu8pR+u0=", - "owner": "Quid2", - "repo": "flat", - "rev": "559617e058098b776b431e2a67346ad3adea2440", + "lastModified": 1651108473, + "narHash": "sha256-zHGCnBdwKvrcYanjf3GARTWF8V2pyJl1QNONUNZSoc0=", + "owner": "input-output-hk", + "repo": "hackage.nix", + "rev": "dbab3b292c3400d028a2257e3acd2ac0249da774", "type": "github" }, "original": { - "owner": "Quid2", - "repo": "flat", + "owner": "input-output-hk", + "repo": "hackage.nix", "type": "github" } }, - "flat_6": { + "hackage-nix_5": { "flake": false, "locked": { - "lastModified": 1651403785, - "narHash": "sha256-g+jGep1IXdw4q01W67J6f6OODY91QzIlW1+Eu8pR+u0=", - "owner": "Quid2", - "repo": "flat", - "rev": "559617e058098b776b431e2a67346ad3adea2440", + "lastModified": 1651108473, + "narHash": "sha256-zHGCnBdwKvrcYanjf3GARTWF8V2pyJl1QNONUNZSoc0=", + "owner": "input-output-hk", + "repo": "hackage.nix", + "rev": "dbab3b292c3400d028a2257e3acd2ac0249da774", "type": "github" }, "original": { - "owner": "Quid2", - "repo": "flat", + "owner": "input-output-hk", + "repo": "hackage.nix", "type": "github" } }, - "flat_7": { + "hackage-nix_6": { "flake": false, "locked": { - "lastModified": 1651403785, - "narHash": "sha256-g+jGep1IXdw4q01W67J6f6OODY91QzIlW1+Eu8pR+u0=", - "owner": "Quid2", - "repo": "flat", - "rev": "559617e058098b776b431e2a67346ad3adea2440", + "lastModified": 1651108473, + "narHash": "sha256-zHGCnBdwKvrcYanjf3GARTWF8V2pyJl1QNONUNZSoc0=", + "owner": "input-output-hk", + "repo": "hackage.nix", + "rev": "dbab3b292c3400d028a2257e3acd2ac0249da774", "type": "github" }, "original": { - "owner": "Quid2", - "repo": "flat", + "owner": "input-output-hk", + "repo": "hackage.nix", "type": "github" } }, - "flat_8": { + "hackage-nix_7": { "flake": false, "locked": { - "lastModified": 1651403785, - "narHash": "sha256-g+jGep1IXdw4q01W67J6f6OODY91QzIlW1+Eu8pR+u0=", - "owner": "Quid2", - "repo": "flat", - "rev": "559617e058098b776b431e2a67346ad3adea2440", + "lastModified": 1651108473, + "narHash": "sha256-zHGCnBdwKvrcYanjf3GARTWF8V2pyJl1QNONUNZSoc0=", + "owner": "input-output-hk", + "repo": "hackage.nix", + "rev": "dbab3b292c3400d028a2257e3acd2ac0249da774", "type": "github" }, "original": { - "owner": "Quid2", - "repo": "flat", + "owner": "input-output-hk", + "repo": "hackage.nix", "type": "github" } }, - "flat_9": { + "hackage-nix_8": { "flake": false, "locked": { - "lastModified": 1651403785, - "narHash": "sha256-g+jGep1IXdw4q01W67J6f6OODY91QzIlW1+Eu8pR+u0=", - "owner": "Quid2", - "repo": "flat", - "rev": "559617e058098b776b431e2a67346ad3adea2440", + "lastModified": 1651108473, + "narHash": "sha256-zHGCnBdwKvrcYanjf3GARTWF8V2pyJl1QNONUNZSoc0=", + "owner": "input-output-hk", + "repo": "hackage.nix", + "rev": "dbab3b292c3400d028a2257e3acd2ac0249da774", "type": "github" }, "original": { - "owner": "Quid2", - "repo": "flat", + "owner": "input-output-hk", + "repo": "hackage.nix", "type": "github" } }, - "foundation": { + "hackage-nix_9": { "flake": false, "locked": { - "lastModified": 1635711016, - "narHash": "sha256-5TRuljpwt50DLjyFjiFj6quFncu8RT0d8/0jlzsenuc=", - "owner": "haskell-foundation", - "repo": "foundation", - "rev": "0bb195e1fea06d144dafc5af9a0ff79af0a5f4a0", + "lastModified": 1651108473, + "narHash": "sha256-zHGCnBdwKvrcYanjf3GARTWF8V2pyJl1QNONUNZSoc0=", + "owner": "input-output-hk", + "repo": "hackage.nix", + "rev": "dbab3b292c3400d028a2257e3acd2ac0249da774", "type": "github" }, "original": { - "owner": "haskell-foundation", - "repo": "foundation", - "rev": "0bb195e1fea06d144dafc5af9a0ff79af0a5f4a0", + "owner": "input-output-hk", + "repo": "hackage.nix", "type": "github" } }, - "ghc-8.6.5-iohk": { + "hackage_10": { "flake": false, "locked": { - "lastModified": 1600920045, - "narHash": "sha256-DO6kxJz248djebZLpSzTGD6s8WRpNI9BTwUeOf5RwY8=", + "lastModified": 1654046237, + "narHash": "sha256-FpM9zE+Q+WrvCiaZBCg5U1g0bYpiZOCxY8V3R5ydBu8=", "owner": "input-output-hk", - "repo": "ghc", - "rev": "95713a6ecce4551240da7c96b6176f980af75cae", + "repo": "hackage.nix", + "rev": "eeae1790b9c6a880d96e4a7214fdf0a73bdd6fc0", "type": "github" }, "original": { "owner": "input-output-hk", - "ref": "release/8.6.5-iohk", - "repo": "ghc", + "repo": "hackage.nix", "type": "github" } }, - "ghc-8.6.5-iohk_10": { + "hackage_11": { "flake": false, "locked": { - "lastModified": 1600920045, - "narHash": "sha256-DO6kxJz248djebZLpSzTGD6s8WRpNI9BTwUeOf5RwY8=", + "lastModified": 1654046237, + "narHash": "sha256-FpM9zE+Q+WrvCiaZBCg5U1g0bYpiZOCxY8V3R5ydBu8=", "owner": "input-output-hk", - "repo": "ghc", - "rev": "95713a6ecce4551240da7c96b6176f980af75cae", + "repo": "hackage.nix", + "rev": "eeae1790b9c6a880d96e4a7214fdf0a73bdd6fc0", "type": "github" }, "original": { "owner": "input-output-hk", - "ref": "release/8.6.5-iohk", - "repo": "ghc", + "repo": "hackage.nix", "type": "github" } }, - "ghc-8.6.5-iohk_2": { + "hackage_12": { "flake": false, "locked": { - "lastModified": 1600920045, - "narHash": "sha256-DO6kxJz248djebZLpSzTGD6s8WRpNI9BTwUeOf5RwY8=", + "lastModified": 1654046237, + "narHash": "sha256-FpM9zE+Q+WrvCiaZBCg5U1g0bYpiZOCxY8V3R5ydBu8=", "owner": "input-output-hk", - "repo": "ghc", - "rev": "95713a6ecce4551240da7c96b6176f980af75cae", + "repo": "hackage.nix", + "rev": "eeae1790b9c6a880d96e4a7214fdf0a73bdd6fc0", "type": "github" }, "original": { "owner": "input-output-hk", - "ref": "release/8.6.5-iohk", - "repo": "ghc", + "repo": "hackage.nix", "type": "github" } }, - "ghc-8.6.5-iohk_3": { + "hackage_13": { "flake": false, "locked": { - "lastModified": 1600920045, - "narHash": "sha256-DO6kxJz248djebZLpSzTGD6s8WRpNI9BTwUeOf5RwY8=", + "lastModified": 1654046237, + "narHash": "sha256-FpM9zE+Q+WrvCiaZBCg5U1g0bYpiZOCxY8V3R5ydBu8=", "owner": "input-output-hk", - "repo": "ghc", - "rev": "95713a6ecce4551240da7c96b6176f980af75cae", + "repo": "hackage.nix", + "rev": "eeae1790b9c6a880d96e4a7214fdf0a73bdd6fc0", "type": "github" }, "original": { "owner": "input-output-hk", - "ref": "release/8.6.5-iohk", - "repo": "ghc", + "repo": "hackage.nix", "type": "github" } }, - "ghc-8.6.5-iohk_4": { + "hackage_14": { "flake": false, "locked": { - "lastModified": 1600920045, - "narHash": "sha256-DO6kxJz248djebZLpSzTGD6s8WRpNI9BTwUeOf5RwY8=", + "lastModified": 1654046237, + "narHash": "sha256-FpM9zE+Q+WrvCiaZBCg5U1g0bYpiZOCxY8V3R5ydBu8=", "owner": "input-output-hk", - "repo": "ghc", - "rev": "95713a6ecce4551240da7c96b6176f980af75cae", + "repo": "hackage.nix", + "rev": "eeae1790b9c6a880d96e4a7214fdf0a73bdd6fc0", "type": "github" }, "original": { "owner": "input-output-hk", - "ref": "release/8.6.5-iohk", - "repo": "ghc", + "repo": "hackage.nix", "type": "github" } }, - "ghc-8.6.5-iohk_5": { + "hackage_15": { "flake": false, "locked": { - "lastModified": 1600920045, - "narHash": "sha256-DO6kxJz248djebZLpSzTGD6s8WRpNI9BTwUeOf5RwY8=", + "lastModified": 1654046237, + "narHash": "sha256-FpM9zE+Q+WrvCiaZBCg5U1g0bYpiZOCxY8V3R5ydBu8=", "owner": "input-output-hk", - "repo": "ghc", - "rev": "95713a6ecce4551240da7c96b6176f980af75cae", + "repo": "hackage.nix", + "rev": "eeae1790b9c6a880d96e4a7214fdf0a73bdd6fc0", "type": "github" }, "original": { "owner": "input-output-hk", - "ref": "release/8.6.5-iohk", - "repo": "ghc", + "repo": "hackage.nix", "type": "github" } }, - "ghc-8.6.5-iohk_6": { + "hackage_2": { "flake": false, "locked": { - "lastModified": 1600920045, - "narHash": "sha256-DO6kxJz248djebZLpSzTGD6s8WRpNI9BTwUeOf5RwY8=", + "lastModified": 1654046237, + "narHash": "sha256-FpM9zE+Q+WrvCiaZBCg5U1g0bYpiZOCxY8V3R5ydBu8=", "owner": "input-output-hk", - "repo": "ghc", - "rev": "95713a6ecce4551240da7c96b6176f980af75cae", + "repo": "hackage.nix", + "rev": "eeae1790b9c6a880d96e4a7214fdf0a73bdd6fc0", "type": "github" }, "original": { "owner": "input-output-hk", - "ref": "release/8.6.5-iohk", - "repo": "ghc", + "repo": "hackage.nix", "type": "github" } }, - "ghc-8.6.5-iohk_7": { + "hackage_3": { "flake": false, "locked": { - "lastModified": 1600920045, - "narHash": "sha256-DO6kxJz248djebZLpSzTGD6s8WRpNI9BTwUeOf5RwY8=", + "lastModified": 1654046237, + "narHash": "sha256-FpM9zE+Q+WrvCiaZBCg5U1g0bYpiZOCxY8V3R5ydBu8=", "owner": "input-output-hk", - "repo": "ghc", - "rev": "95713a6ecce4551240da7c96b6176f980af75cae", + "repo": "hackage.nix", + "rev": "eeae1790b9c6a880d96e4a7214fdf0a73bdd6fc0", "type": "github" }, "original": { "owner": "input-output-hk", - "ref": "release/8.6.5-iohk", - "repo": "ghc", + "repo": "hackage.nix", "type": "github" } }, - "ghc-8.6.5-iohk_8": { + "hackage_4": { "flake": false, "locked": { - "lastModified": 1600920045, - "narHash": "sha256-DO6kxJz248djebZLpSzTGD6s8WRpNI9BTwUeOf5RwY8=", + "lastModified": 1654046237, + "narHash": "sha256-FpM9zE+Q+WrvCiaZBCg5U1g0bYpiZOCxY8V3R5ydBu8=", "owner": "input-output-hk", - "repo": "ghc", - "rev": "95713a6ecce4551240da7c96b6176f980af75cae", + "repo": "hackage.nix", + "rev": "eeae1790b9c6a880d96e4a7214fdf0a73bdd6fc0", "type": "github" }, "original": { "owner": "input-output-hk", - "ref": "release/8.6.5-iohk", - "repo": "ghc", + "repo": "hackage.nix", "type": "github" } }, - "ghc-8.6.5-iohk_9": { + "hackage_5": { "flake": false, "locked": { - "lastModified": 1600920045, - "narHash": "sha256-DO6kxJz248djebZLpSzTGD6s8WRpNI9BTwUeOf5RwY8=", + "lastModified": 1654046237, + "narHash": "sha256-FpM9zE+Q+WrvCiaZBCg5U1g0bYpiZOCxY8V3R5ydBu8=", "owner": "input-output-hk", - "repo": "ghc", - "rev": "95713a6ecce4551240da7c96b6176f980af75cae", + "repo": "hackage.nix", + "rev": "eeae1790b9c6a880d96e4a7214fdf0a73bdd6fc0", "type": "github" }, "original": { "owner": "input-output-hk", - "ref": "release/8.6.5-iohk", - "repo": "ghc", + "repo": "hackage.nix", "type": "github" } }, - "gitignore-nix": { + "hackage_6": { "flake": false, "locked": { - "lastModified": 1611672876, - "narHash": "sha256-qHu3uZ/o9jBHiA3MEKHJ06k7w4heOhA+4HCSIvflRxo=", - "owner": "hercules-ci", - "repo": "gitignore.nix", - "rev": "211907489e9f198594c0eb0ca9256a1949c9d412", + "lastModified": 1654046237, + "narHash": "sha256-FpM9zE+Q+WrvCiaZBCg5U1g0bYpiZOCxY8V3R5ydBu8=", + "owner": "input-output-hk", + "repo": "hackage.nix", + "rev": "eeae1790b9c6a880d96e4a7214fdf0a73bdd6fc0", "type": "github" }, "original": { - "owner": "hercules-ci", - "repo": "gitignore.nix", + "owner": "input-output-hk", + "repo": "hackage.nix", "type": "github" } }, - "gitignore-nix_10": { + "hackage_7": { "flake": false, "locked": { - "lastModified": 1611672876, - "narHash": "sha256-qHu3uZ/o9jBHiA3MEKHJ06k7w4heOhA+4HCSIvflRxo=", - "owner": "hercules-ci", - "repo": "gitignore.nix", - "rev": "211907489e9f198594c0eb0ca9256a1949c9d412", + "lastModified": 1654046237, + "narHash": "sha256-FpM9zE+Q+WrvCiaZBCg5U1g0bYpiZOCxY8V3R5ydBu8=", + "owner": "input-output-hk", + "repo": "hackage.nix", + "rev": "eeae1790b9c6a880d96e4a7214fdf0a73bdd6fc0", "type": "github" }, "original": { - "owner": "hercules-ci", - "repo": "gitignore.nix", + "owner": "input-output-hk", + "repo": "hackage.nix", "type": "github" } }, - "gitignore-nix_2": { + "hackage_8": { "flake": false, "locked": { - "lastModified": 1611672876, - "narHash": "sha256-qHu3uZ/o9jBHiA3MEKHJ06k7w4heOhA+4HCSIvflRxo=", - "owner": "hercules-ci", - "repo": "gitignore.nix", - "rev": "211907489e9f198594c0eb0ca9256a1949c9d412", + "lastModified": 1654046237, + "narHash": "sha256-FpM9zE+Q+WrvCiaZBCg5U1g0bYpiZOCxY8V3R5ydBu8=", + "owner": "input-output-hk", + "repo": "hackage.nix", + "rev": "eeae1790b9c6a880d96e4a7214fdf0a73bdd6fc0", "type": "github" }, "original": { - "owner": "hercules-ci", - "repo": "gitignore.nix", + "owner": "input-output-hk", + "repo": "hackage.nix", "type": "github" } }, - "gitignore-nix_3": { + "hackage_9": { "flake": false, "locked": { - "lastModified": 1611672876, - "narHash": "sha256-qHu3uZ/o9jBHiA3MEKHJ06k7w4heOhA+4HCSIvflRxo=", - "owner": "hercules-ci", - "repo": "gitignore.nix", - "rev": "211907489e9f198594c0eb0ca9256a1949c9d412", + "lastModified": 1654046237, + "narHash": "sha256-FpM9zE+Q+WrvCiaZBCg5U1g0bYpiZOCxY8V3R5ydBu8=", + "owner": "input-output-hk", + "repo": "hackage.nix", + "rev": "eeae1790b9c6a880d96e4a7214fdf0a73bdd6fc0", "type": "github" }, "original": { - "owner": "hercules-ci", - "repo": "gitignore.nix", + "owner": "input-output-hk", + "repo": "hackage.nix", "type": "github" } }, - "gitignore-nix_4": { + "haskell-language-server": { "flake": false, "locked": { - "lastModified": 1611672876, - "narHash": "sha256-qHu3uZ/o9jBHiA3MEKHJ06k7w4heOhA+4HCSIvflRxo=", - "owner": "hercules-ci", - "repo": "gitignore.nix", - "rev": "211907489e9f198594c0eb0ca9256a1949c9d412", + "lastModified": 1653778781, + "narHash": "sha256-oEVBaYRLjD4gC3vQuT0DCgmCSIeWSwGPVXXSKJDFUK0=", + "owner": "haskell", + "repo": "haskell-language-server", + "rev": "8c47d6ce2a8409a285a3f4c3f0e10c25fb4dd848", "type": "github" }, "original": { - "owner": "hercules-ci", - "repo": "gitignore.nix", + "owner": "haskell", + "repo": "haskell-language-server", "type": "github" } }, - "gitignore-nix_5": { + "haskell-language-server_10": { "flake": false, "locked": { - "lastModified": 1611672876, - "narHash": "sha256-qHu3uZ/o9jBHiA3MEKHJ06k7w4heOhA+4HCSIvflRxo=", - "owner": "hercules-ci", - "repo": "gitignore.nix", - "rev": "211907489e9f198594c0eb0ca9256a1949c9d412", + "lastModified": 1650980856, + "narHash": "sha256-uiwsfh/K3IABZDYj7JUZNIAPRVqH6g/r8X6QKg8DrZE=", + "owner": "haskell", + "repo": "haskell-language-server", + "rev": "b5a37f7fc360596899cb2945f363030f44156415", "type": "github" }, "original": { - "owner": "hercules-ci", - "repo": "gitignore.nix", + "owner": "haskell", + "ref": "1.7.0.0", + "repo": "haskell-language-server", "type": "github" } }, - "gitignore-nix_6": { + "haskell-language-server_11": { "flake": false, "locked": { - "lastModified": 1611672876, - "narHash": "sha256-qHu3uZ/o9jBHiA3MEKHJ06k7w4heOhA+4HCSIvflRxo=", - "owner": "hercules-ci", - "repo": "gitignore.nix", - "rev": "211907489e9f198594c0eb0ca9256a1949c9d412", + "lastModified": 1653778781, + "narHash": "sha256-oEVBaYRLjD4gC3vQuT0DCgmCSIeWSwGPVXXSKJDFUK0=", + "owner": "haskell", + "repo": "haskell-language-server", + "rev": "8c47d6ce2a8409a285a3f4c3f0e10c25fb4dd848", "type": "github" }, "original": { - "owner": "hercules-ci", - "repo": "gitignore.nix", + "owner": "haskell", + "repo": "haskell-language-server", "type": "github" } }, - "gitignore-nix_7": { + "haskell-language-server_12": { "flake": false, "locked": { - "lastModified": 1611672876, - "narHash": "sha256-qHu3uZ/o9jBHiA3MEKHJ06k7w4heOhA+4HCSIvflRxo=", - "owner": "hercules-ci", - "repo": "gitignore.nix", - "rev": "211907489e9f198594c0eb0ca9256a1949c9d412", + "lastModified": 1650980856, + "narHash": "sha256-uiwsfh/K3IABZDYj7JUZNIAPRVqH6g/r8X6QKg8DrZE=", + "owner": "haskell", + "repo": "haskell-language-server", + "rev": "b5a37f7fc360596899cb2945f363030f44156415", "type": "github" }, "original": { - "owner": "hercules-ci", - "repo": "gitignore.nix", + "owner": "haskell", + "ref": "1.7.0.0", + "repo": "haskell-language-server", "type": "github" } }, - "gitignore-nix_8": { + "haskell-language-server_13": { "flake": false, "locked": { - "lastModified": 1611672876, - "narHash": "sha256-qHu3uZ/o9jBHiA3MEKHJ06k7w4heOhA+4HCSIvflRxo=", - "owner": "hercules-ci", - "repo": "gitignore.nix", - "rev": "211907489e9f198594c0eb0ca9256a1949c9d412", + "lastModified": 1653778781, + "narHash": "sha256-oEVBaYRLjD4gC3vQuT0DCgmCSIeWSwGPVXXSKJDFUK0=", + "owner": "haskell", + "repo": "haskell-language-server", + "rev": "8c47d6ce2a8409a285a3f4c3f0e10c25fb4dd848", "type": "github" }, "original": { - "owner": "hercules-ci", - "repo": "gitignore.nix", + "owner": "haskell", + "repo": "haskell-language-server", "type": "github" } }, - "gitignore-nix_9": { + "haskell-language-server_14": { "flake": false, "locked": { - "lastModified": 1611672876, - "narHash": "sha256-qHu3uZ/o9jBHiA3MEKHJ06k7w4heOhA+4HCSIvflRxo=", - "owner": "hercules-ci", - "repo": "gitignore.nix", - "rev": "211907489e9f198594c0eb0ca9256a1949c9d412", + "lastModified": 1650980856, + "narHash": "sha256-uiwsfh/K3IABZDYj7JUZNIAPRVqH6g/r8X6QKg8DrZE=", + "owner": "haskell", + "repo": "haskell-language-server", + "rev": "b5a37f7fc360596899cb2945f363030f44156415", "type": "github" }, "original": { - "owner": "hercules-ci", - "repo": "gitignore.nix", + "owner": "haskell", + "ref": "1.7.0.0", + "repo": "haskell-language-server", "type": "github" } }, - "hackage": { + "haskell-language-server_15": { "flake": false, "locked": { - "lastModified": 1654046237, - "narHash": "sha256-FpM9zE+Q+WrvCiaZBCg5U1g0bYpiZOCxY8V3R5ydBu8=", - "owner": "input-output-hk", - "repo": "hackage.nix", - "rev": "eeae1790b9c6a880d96e4a7214fdf0a73bdd6fc0", + "lastModified": 1653778781, + "narHash": "sha256-oEVBaYRLjD4gC3vQuT0DCgmCSIeWSwGPVXXSKJDFUK0=", + "owner": "haskell", + "repo": "haskell-language-server", + "rev": "8c47d6ce2a8409a285a3f4c3f0e10c25fb4dd848", "type": "github" }, "original": { - "owner": "input-output-hk", - "repo": "hackage.nix", + "owner": "haskell", + "repo": "haskell-language-server", "type": "github" } }, - "hackage-nix": { + "haskell-language-server_16": { "flake": false, "locked": { - "lastModified": 1651108473, - "narHash": "sha256-zHGCnBdwKvrcYanjf3GARTWF8V2pyJl1QNONUNZSoc0=", - "owner": "input-output-hk", - "repo": "hackage.nix", - "rev": "dbab3b292c3400d028a2257e3acd2ac0249da774", + "lastModified": 1650980856, + "narHash": "sha256-uiwsfh/K3IABZDYj7JUZNIAPRVqH6g/r8X6QKg8DrZE=", + "owner": "haskell", + "repo": "haskell-language-server", + "rev": "b5a37f7fc360596899cb2945f363030f44156415", "type": "github" }, "original": { - "owner": "input-output-hk", - "repo": "hackage.nix", + "owner": "haskell", + "ref": "1.7.0.0", + "repo": "haskell-language-server", "type": "github" } }, - "hackage-nix_10": { + "haskell-language-server_17": { "flake": false, "locked": { - "lastModified": 1644369434, - "narHash": "sha256-WqU6f1OhSM0UHXFW8Mhhvhz0tcij+NQVtmb6sW4RiFw=", - "owner": "input-output-hk", - "repo": "hackage.nix", - "rev": "644a0d702abf84cdec62f4e620ff1034000e6146", + "lastModified": 1653778781, + "narHash": "sha256-oEVBaYRLjD4gC3vQuT0DCgmCSIeWSwGPVXXSKJDFUK0=", + "owner": "haskell", + "repo": "haskell-language-server", + "rev": "8c47d6ce2a8409a285a3f4c3f0e10c25fb4dd848", "type": "github" }, "original": { - "owner": "input-output-hk", - "repo": "hackage.nix", + "owner": "haskell", + "repo": "haskell-language-server", "type": "github" } }, - "hackage-nix_2": { + "haskell-language-server_18": { "flake": false, "locked": { - "lastModified": 1651108473, - "narHash": "sha256-zHGCnBdwKvrcYanjf3GARTWF8V2pyJl1QNONUNZSoc0=", - "owner": "input-output-hk", - "repo": "hackage.nix", - "rev": "dbab3b292c3400d028a2257e3acd2ac0249da774", + "lastModified": 1650980856, + "narHash": "sha256-uiwsfh/K3IABZDYj7JUZNIAPRVqH6g/r8X6QKg8DrZE=", + "owner": "haskell", + "repo": "haskell-language-server", + "rev": "b5a37f7fc360596899cb2945f363030f44156415", "type": "github" }, "original": { - "owner": "input-output-hk", - "repo": "hackage.nix", + "owner": "haskell", + "ref": "1.7.0.0", + "repo": "haskell-language-server", "type": "github" } }, - "hackage-nix_3": { + "haskell-language-server_19": { "flake": false, "locked": { - "lastModified": 1651108473, - "narHash": "sha256-zHGCnBdwKvrcYanjf3GARTWF8V2pyJl1QNONUNZSoc0=", - "owner": "input-output-hk", - "repo": "hackage.nix", - "rev": "dbab3b292c3400d028a2257e3acd2ac0249da774", + "lastModified": 1653778781, + "narHash": "sha256-oEVBaYRLjD4gC3vQuT0DCgmCSIeWSwGPVXXSKJDFUK0=", + "owner": "haskell", + "repo": "haskell-language-server", + "rev": "8c47d6ce2a8409a285a3f4c3f0e10c25fb4dd848", "type": "github" }, "original": { - "owner": "input-output-hk", - "repo": "hackage.nix", + "owner": "haskell", + "repo": "haskell-language-server", "type": "github" } }, - "hackage-nix_4": { + "haskell-language-server_2": { "flake": false, "locked": { - "lastModified": 1651108473, - "narHash": "sha256-zHGCnBdwKvrcYanjf3GARTWF8V2pyJl1QNONUNZSoc0=", - "owner": "input-output-hk", - "repo": "hackage.nix", - "rev": "dbab3b292c3400d028a2257e3acd2ac0249da774", + "lastModified": 1650980856, + "narHash": "sha256-uiwsfh/K3IABZDYj7JUZNIAPRVqH6g/r8X6QKg8DrZE=", + "owner": "haskell", + "repo": "haskell-language-server", + "rev": "b5a37f7fc360596899cb2945f363030f44156415", "type": "github" }, "original": { - "owner": "input-output-hk", - "repo": "hackage.nix", + "owner": "haskell", + "ref": "1.7.0.0", + "repo": "haskell-language-server", "type": "github" } }, - "hackage-nix_5": { + "haskell-language-server_20": { "flake": false, "locked": { - "lastModified": 1651108473, - "narHash": "sha256-zHGCnBdwKvrcYanjf3GARTWF8V2pyJl1QNONUNZSoc0=", - "owner": "input-output-hk", - "repo": "hackage.nix", - "rev": "dbab3b292c3400d028a2257e3acd2ac0249da774", + "lastModified": 1650980856, + "narHash": "sha256-uiwsfh/K3IABZDYj7JUZNIAPRVqH6g/r8X6QKg8DrZE=", + "owner": "haskell", + "repo": "haskell-language-server", + "rev": "b5a37f7fc360596899cb2945f363030f44156415", "type": "github" }, "original": { - "owner": "input-output-hk", - "repo": "hackage.nix", + "owner": "haskell", + "ref": "1.7.0.0", + "repo": "haskell-language-server", "type": "github" } }, - "hackage-nix_6": { + "haskell-language-server_21": { "flake": false, "locked": { - "lastModified": 1651108473, - "narHash": "sha256-zHGCnBdwKvrcYanjf3GARTWF8V2pyJl1QNONUNZSoc0=", - "owner": "input-output-hk", - "repo": "hackage.nix", - "rev": "dbab3b292c3400d028a2257e3acd2ac0249da774", + "lastModified": 1653778781, + "narHash": "sha256-oEVBaYRLjD4gC3vQuT0DCgmCSIeWSwGPVXXSKJDFUK0=", + "owner": "haskell", + "repo": "haskell-language-server", + "rev": "8c47d6ce2a8409a285a3f4c3f0e10c25fb4dd848", "type": "github" }, "original": { - "owner": "input-output-hk", - "repo": "hackage.nix", + "owner": "haskell", + "repo": "haskell-language-server", "type": "github" } }, - "hackage-nix_7": { + "haskell-language-server_22": { "flake": false, "locked": { - "lastModified": 1651108473, - "narHash": "sha256-zHGCnBdwKvrcYanjf3GARTWF8V2pyJl1QNONUNZSoc0=", - "owner": "input-output-hk", - "repo": "hackage.nix", - "rev": "dbab3b292c3400d028a2257e3acd2ac0249da774", + "lastModified": 1650980856, + "narHash": "sha256-uiwsfh/K3IABZDYj7JUZNIAPRVqH6g/r8X6QKg8DrZE=", + "owner": "haskell", + "repo": "haskell-language-server", + "rev": "b5a37f7fc360596899cb2945f363030f44156415", "type": "github" }, "original": { - "owner": "input-output-hk", - "repo": "hackage.nix", + "owner": "haskell", + "ref": "1.7.0.0", + "repo": "haskell-language-server", "type": "github" } }, - "hackage-nix_8": { + "haskell-language-server_23": { "flake": false, "locked": { - "lastModified": 1651108473, - "narHash": "sha256-zHGCnBdwKvrcYanjf3GARTWF8V2pyJl1QNONUNZSoc0=", - "owner": "input-output-hk", - "repo": "hackage.nix", - "rev": "dbab3b292c3400d028a2257e3acd2ac0249da774", + "lastModified": 1653778781, + "narHash": "sha256-oEVBaYRLjD4gC3vQuT0DCgmCSIeWSwGPVXXSKJDFUK0=", + "owner": "haskell", + "repo": "haskell-language-server", + "rev": "8c47d6ce2a8409a285a3f4c3f0e10c25fb4dd848", "type": "github" }, "original": { - "owner": "input-output-hk", - "repo": "hackage.nix", + "owner": "haskell", + "repo": "haskell-language-server", "type": "github" } }, - "hackage-nix_9": { + "haskell-language-server_24": { "flake": false, "locked": { - "lastModified": 1651108473, - "narHash": "sha256-zHGCnBdwKvrcYanjf3GARTWF8V2pyJl1QNONUNZSoc0=", - "owner": "input-output-hk", - "repo": "hackage.nix", - "rev": "dbab3b292c3400d028a2257e3acd2ac0249da774", + "lastModified": 1650980856, + "narHash": "sha256-uiwsfh/K3IABZDYj7JUZNIAPRVqH6g/r8X6QKg8DrZE=", + "owner": "haskell", + "repo": "haskell-language-server", + "rev": "b5a37f7fc360596899cb2945f363030f44156415", "type": "github" }, "original": { - "owner": "input-output-hk", - "repo": "hackage.nix", + "owner": "haskell", + "ref": "1.7.0.0", + "repo": "haskell-language-server", "type": "github" } }, - "hackage_10": { + "haskell-language-server_25": { "flake": false, "locked": { - "lastModified": 1644887696, - "narHash": "sha256-o4gltv4npUl7+1gEQIcrRqZniwqC9kK8QsPaftlrawc=", - "owner": "input-output-hk", - "repo": "hackage.nix", - "rev": "6ff64aa49b88e75dd6e0bbd2823c2a92c9174fa5", + "lastModified": 1653778781, + "narHash": "sha256-oEVBaYRLjD4gC3vQuT0DCgmCSIeWSwGPVXXSKJDFUK0=", + "owner": "haskell", + "repo": "haskell-language-server", + "rev": "8c47d6ce2a8409a285a3f4c3f0e10c25fb4dd848", "type": "github" }, "original": { - "owner": "input-output-hk", - "repo": "hackage.nix", + "owner": "haskell", + "repo": "haskell-language-server", "type": "github" } }, - "hackage_2": { + "haskell-language-server_26": { "flake": false, "locked": { - "lastModified": 1654046237, - "narHash": "sha256-FpM9zE+Q+WrvCiaZBCg5U1g0bYpiZOCxY8V3R5ydBu8=", - "owner": "input-output-hk", - "repo": "hackage.nix", - "rev": "eeae1790b9c6a880d96e4a7214fdf0a73bdd6fc0", + "lastModified": 1650980856, + "narHash": "sha256-uiwsfh/K3IABZDYj7JUZNIAPRVqH6g/r8X6QKg8DrZE=", + "owner": "haskell", + "repo": "haskell-language-server", + "rev": "b5a37f7fc360596899cb2945f363030f44156415", "type": "github" }, "original": { - "owner": "input-output-hk", - "repo": "hackage.nix", + "owner": "haskell", + "ref": "1.7.0.0", + "repo": "haskell-language-server", "type": "github" } }, - "hackage_3": { + "haskell-language-server_27": { "flake": false, "locked": { - "lastModified": 1654046237, - "narHash": "sha256-FpM9zE+Q+WrvCiaZBCg5U1g0bYpiZOCxY8V3R5ydBu8=", - "owner": "input-output-hk", - "repo": "hackage.nix", - "rev": "eeae1790b9c6a880d96e4a7214fdf0a73bdd6fc0", + "lastModified": 1653778781, + "narHash": "sha256-oEVBaYRLjD4gC3vQuT0DCgmCSIeWSwGPVXXSKJDFUK0=", + "owner": "haskell", + "repo": "haskell-language-server", + "rev": "8c47d6ce2a8409a285a3f4c3f0e10c25fb4dd848", "type": "github" }, "original": { - "owner": "input-output-hk", - "repo": "hackage.nix", + "owner": "haskell", + "repo": "haskell-language-server", "type": "github" } }, - "hackage_4": { + "haskell-language-server_28": { "flake": false, "locked": { - "lastModified": 1654046237, - "narHash": "sha256-FpM9zE+Q+WrvCiaZBCg5U1g0bYpiZOCxY8V3R5ydBu8=", - "owner": "input-output-hk", - "repo": "hackage.nix", - "rev": "eeae1790b9c6a880d96e4a7214fdf0a73bdd6fc0", - "type": "github" - }, - "original": { - "owner": "input-output-hk", - "repo": "hackage.nix", - "type": "github" - } - }, - "hackage_5": { - "flake": false, - "locked": { - "lastModified": 1654046237, - "narHash": "sha256-FpM9zE+Q+WrvCiaZBCg5U1g0bYpiZOCxY8V3R5ydBu8=", - "owner": "input-output-hk", - "repo": "hackage.nix", - "rev": "eeae1790b9c6a880d96e4a7214fdf0a73bdd6fc0", - "type": "github" - }, - "original": { - "owner": "input-output-hk", - "repo": "hackage.nix", - "type": "github" - } - }, - "hackage_6": { - "flake": false, - "locked": { - "lastModified": 1654046237, - "narHash": "sha256-FpM9zE+Q+WrvCiaZBCg5U1g0bYpiZOCxY8V3R5ydBu8=", - "owner": "input-output-hk", - "repo": "hackage.nix", - "rev": "eeae1790b9c6a880d96e4a7214fdf0a73bdd6fc0", - "type": "github" - }, - "original": { - "owner": "input-output-hk", - "repo": "hackage.nix", - "type": "github" - } - }, - "hackage_7": { - "flake": false, - "locked": { - "lastModified": 1654046237, - "narHash": "sha256-FpM9zE+Q+WrvCiaZBCg5U1g0bYpiZOCxY8V3R5ydBu8=", - "owner": "input-output-hk", - "repo": "hackage.nix", - "rev": "eeae1790b9c6a880d96e4a7214fdf0a73bdd6fc0", - "type": "github" - }, - "original": { - "owner": "input-output-hk", - "repo": "hackage.nix", - "type": "github" - } - }, - "hackage_8": { - "flake": false, - "locked": { - "lastModified": 1654046237, - "narHash": "sha256-FpM9zE+Q+WrvCiaZBCg5U1g0bYpiZOCxY8V3R5ydBu8=", - "owner": "input-output-hk", - "repo": "hackage.nix", - "rev": "eeae1790b9c6a880d96e4a7214fdf0a73bdd6fc0", - "type": "github" - }, - "original": { - "owner": "input-output-hk", - "repo": "hackage.nix", - "type": "github" - } - }, - "hackage_9": { - "flake": false, - "locked": { - "lastModified": 1654046237, - "narHash": "sha256-FpM9zE+Q+WrvCiaZBCg5U1g0bYpiZOCxY8V3R5ydBu8=", - "owner": "input-output-hk", - "repo": "hackage.nix", - "rev": "eeae1790b9c6a880d96e4a7214fdf0a73bdd6fc0", + "lastModified": 1650980856, + "narHash": "sha256-uiwsfh/K3IABZDYj7JUZNIAPRVqH6g/r8X6QKg8DrZE=", + "owner": "haskell", + "repo": "haskell-language-server", + "rev": "b5a37f7fc360596899cb2945f363030f44156415", "type": "github" }, "original": { - "owner": "input-output-hk", - "repo": "hackage.nix", + "owner": "haskell", + "ref": "1.7.0.0", + "repo": "haskell-language-server", "type": "github" } }, - "haskell-language-server": { + "haskell-language-server_29": { "flake": false, "locked": { - "lastModified": 1654120290, - "narHash": "sha256-6NuFBnEzJPvWfvbYxXk/WCQDjsEbjCQ1nAelhBDi4yQ=", + "lastModified": 1653778781, + "narHash": "sha256-oEVBaYRLjD4gC3vQuT0DCgmCSIeWSwGPVXXSKJDFUK0=", "owner": "haskell", "repo": "haskell-language-server", - "rev": "140f9040ae88352ca1140a750e7c26485fdfbe17", + "rev": "8c47d6ce2a8409a285a3f4c3f0e10c25fb4dd848", "type": "github" }, "original": { @@ -3771,7 +4038,7 @@ "type": "github" } }, - "haskell-language-server_10": { + "haskell-language-server_3": { "flake": false, "locked": { "lastModified": 1653778781, @@ -3787,7 +4054,7 @@ "type": "github" } }, - "haskell-language-server_11": { + "haskell-language-server_30": { "flake": false, "locked": { "lastModified": 1650980856, @@ -3804,23 +4071,24 @@ "type": "github" } }, - "haskell-language-server_12": { + "haskell-language-server_4": { "flake": false, "locked": { - "lastModified": 1654120290, - "narHash": "sha256-6NuFBnEzJPvWfvbYxXk/WCQDjsEbjCQ1nAelhBDi4yQ=", + "lastModified": 1650980856, + "narHash": "sha256-uiwsfh/K3IABZDYj7JUZNIAPRVqH6g/r8X6QKg8DrZE=", "owner": "haskell", "repo": "haskell-language-server", - "rev": "140f9040ae88352ca1140a750e7c26485fdfbe17", + "rev": "b5a37f7fc360596899cb2945f363030f44156415", "type": "github" }, "original": { "owner": "haskell", + "ref": "1.7.0.0", "repo": "haskell-language-server", "type": "github" } }, - "haskell-language-server_13": { + "haskell-language-server_5": { "flake": false, "locked": { "lastModified": 1653778781, @@ -3836,7 +4104,7 @@ "type": "github" } }, - "haskell-language-server_14": { + "haskell-language-server_6": { "flake": false, "locked": { "lastModified": 1650980856, @@ -3853,23 +4121,7 @@ "type": "github" } }, - "haskell-language-server_15": { - "flake": false, - "locked": { - "lastModified": 1654120290, - "narHash": "sha256-6NuFBnEzJPvWfvbYxXk/WCQDjsEbjCQ1nAelhBDi4yQ=", - "owner": "haskell", - "repo": "haskell-language-server", - "rev": "140f9040ae88352ca1140a750e7c26485fdfbe17", - "type": "github" - }, - "original": { - "owner": "haskell", - "repo": "haskell-language-server", - "type": "github" - } - }, - "haskell-language-server_16": { + "haskell-language-server_7": { "flake": false, "locked": { "lastModified": 1653778781, @@ -3885,7 +4137,7 @@ "type": "github" } }, - "haskell-language-server_17": { + "haskell-language-server_8": { "flake": false, "locked": { "lastModified": 1650980856, @@ -3902,14 +4154,14 @@ "type": "github" } }, - "haskell-language-server_18": { + "haskell-language-server_9": { "flake": false, "locked": { - "lastModified": 1654120290, - "narHash": "sha256-6NuFBnEzJPvWfvbYxXk/WCQDjsEbjCQ1nAelhBDi4yQ=", + "lastModified": 1653778781, + "narHash": "sha256-oEVBaYRLjD4gC3vQuT0DCgmCSIeWSwGPVXXSKJDFUK0=", "owner": "haskell", "repo": "haskell-language-server", - "rev": "140f9040ae88352ca1140a750e7c26485fdfbe17", + "rev": "8c47d6ce2a8409a285a3f4c3f0e10c25fb4dd848", "type": "github" }, "original": { @@ -3918,342 +4170,583 @@ "type": "github" } }, - "haskell-language-server_19": { - "flake": false, + "haskell-nix": { + "inputs": { + "HTTP": "HTTP", + "cabal-32": "cabal-32", + "cabal-34": "cabal-34", + "cabal-36": "cabal-36", + "cardano-shell": "cardano-shell", + "flake-utils": "flake-utils", + "ghc-8.6.5-iohk": "ghc-8.6.5-iohk", + "hackage": "hackage", + "hpc-coveralls": "hpc-coveralls", + "hydra": "hydra", + "nix-tools": "nix-tools", + "nixpkgs": [ + "liqwid-plutarch-extra", + "plutarch", + "haskell-nix", + "nixpkgs-unstable" + ], + "nixpkgs-2003": "nixpkgs-2003", + "nixpkgs-2105": "nixpkgs-2105", + "nixpkgs-2111": "nixpkgs-2111_2", + "nixpkgs-unstable": "nixpkgs-unstable", + "old-ghc-nix": "old-ghc-nix", + "stackage": "stackage" + }, "locked": { - "lastModified": 1654120290, - "narHash": "sha256-6NuFBnEzJPvWfvbYxXk/WCQDjsEbjCQ1nAelhBDi4yQ=", - "owner": "haskell", - "repo": "haskell-language-server", - "rev": "140f9040ae88352ca1140a750e7c26485fdfbe17", + "lastModified": 1654068838, + "narHash": "sha256-GHSufC21DSg8Lz2AzIg3DA9DPxGvLqxGFa/4ADoXRhU=", + "owner": "input-output-hk", + "repo": "haskell.nix", + "rev": "fa2fa131fe15e630c91ab4078d12eb32c41f934b", "type": "github" }, "original": { - "owner": "haskell", - "repo": "haskell-language-server", + "owner": "input-output-hk", + "repo": "haskell.nix", "type": "github" } }, - "haskell-language-server_2": { - "flake": false, + "haskell-nix-extra-hackage": { + "inputs": { + "haskell-nix": [ + "liqwid-plutarch-extra", + "plutarch", + "haskell-nix" + ], + "nixpkgs": [ + "liqwid-plutarch-extra", + "plutarch", + "nixpkgs" + ] + }, "locked": { - "lastModified": 1653778781, - "narHash": "sha256-oEVBaYRLjD4gC3vQuT0DCgmCSIeWSwGPVXXSKJDFUK0=", - "owner": "haskell", - "repo": "haskell-language-server", - "rev": "8c47d6ce2a8409a285a3f4c3f0e10c25fb4dd848", + "lastModified": 1655143375, + "narHash": "sha256-yU+HPLwGPf5IeLj9IBQ1zrPBTYEwvYbuMnADs4T8RLQ=", + "owner": "mlabs-haskell", + "repo": "haskell-nix-extra-hackage", + "rev": "03ee7afdc1ad982e059e3941db80f7a5b30a2757", "type": "github" }, "original": { - "owner": "haskell", - "repo": "haskell-language-server", + "owner": "mlabs-haskell", + "ref": "separate-hackages", + "repo": "haskell-nix-extra-hackage", "type": "github" } }, - "haskell-language-server_20": { - "flake": false, + "haskell-nix-extra-hackage_10": { + "inputs": { + "haskell-nix": [ + "plutarch-safe-money", + "liqwid-plutarch-extra", + "plutarch-context-builder", + "plutarch", + "haskell-nix" + ], + "nixpkgs": [ + "plutarch-safe-money", + "liqwid-plutarch-extra", + "plutarch-context-builder", + "plutarch", + "nixpkgs" + ] + }, "locked": { - "lastModified": 1653778781, - "narHash": "sha256-oEVBaYRLjD4gC3vQuT0DCgmCSIeWSwGPVXXSKJDFUK0=", - "owner": "haskell", - "repo": "haskell-language-server", - "rev": "8c47d6ce2a8409a285a3f4c3f0e10c25fb4dd848", + "lastModified": 1655143375, + "narHash": "sha256-yU+HPLwGPf5IeLj9IBQ1zrPBTYEwvYbuMnADs4T8RLQ=", + "owner": "mlabs-haskell", + "repo": "haskell-nix-extra-hackage", + "rev": "03ee7afdc1ad982e059e3941db80f7a5b30a2757", "type": "github" }, "original": { - "owner": "haskell", - "repo": "haskell-language-server", + "owner": "mlabs-haskell", + "ref": "separate-hackages", + "repo": "haskell-nix-extra-hackage", "type": "github" } }, - "haskell-language-server_21": { - "flake": false, + "haskell-nix-extra-hackage_11": { + "inputs": { + "haskell-nix": [ + "plutarch-safe-money", + "liqwid-plutarch-extra", + "plutarch-numeric", + "plutarch", + "haskell-nix" + ], + "nixpkgs": [ + "plutarch-safe-money", + "liqwid-plutarch-extra", + "plutarch-numeric", + "plutarch", + "nixpkgs" + ] + }, "locked": { - "lastModified": 1650980856, - "narHash": "sha256-uiwsfh/K3IABZDYj7JUZNIAPRVqH6g/r8X6QKg8DrZE=", - "owner": "haskell", - "repo": "haskell-language-server", - "rev": "b5a37f7fc360596899cb2945f363030f44156415", + "lastModified": 1655143375, + "narHash": "sha256-yU+HPLwGPf5IeLj9IBQ1zrPBTYEwvYbuMnADs4T8RLQ=", + "owner": "mlabs-haskell", + "repo": "haskell-nix-extra-hackage", + "rev": "03ee7afdc1ad982e059e3941db80f7a5b30a2757", "type": "github" }, "original": { - "owner": "haskell", - "ref": "1.7.0.0", - "repo": "haskell-language-server", + "owner": "mlabs-haskell", + "ref": "separate-hackages", + "repo": "haskell-nix-extra-hackage", "type": "github" } }, - "haskell-language-server_22": { - "flake": false, - "locked": { - "lastModified": 1654120290, - "narHash": "sha256-6NuFBnEzJPvWfvbYxXk/WCQDjsEbjCQ1nAelhBDi4yQ=", - "owner": "haskell", - "repo": "haskell-language-server", - "rev": "140f9040ae88352ca1140a750e7c26485fdfbe17", + "haskell-nix-extra-hackage_12": { + "inputs": { + "haskell-nix": [ + "plutarch-safe-money", + "liqwid-plutarch-extra", + "plutarch-quickcheck", + "plutarch", + "haskell-nix" + ], + "nixpkgs": [ + "plutarch-safe-money", + "liqwid-plutarch-extra", + "plutarch-quickcheck", + "plutarch", + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1655143375, + "narHash": "sha256-yU+HPLwGPf5IeLj9IBQ1zrPBTYEwvYbuMnADs4T8RLQ=", + "owner": "mlabs-haskell", + "repo": "haskell-nix-extra-hackage", + "rev": "03ee7afdc1ad982e059e3941db80f7a5b30a2757", "type": "github" }, "original": { - "owner": "haskell", - "repo": "haskell-language-server", + "owner": "mlabs-haskell", + "ref": "separate-hackages", + "repo": "haskell-nix-extra-hackage", "type": "github" } }, - "haskell-language-server_23": { - "flake": false, + "haskell-nix-extra-hackage_13": { + "inputs": { + "haskell-nix": [ + "plutarch-safe-money", + "plutarch", + "haskell-nix" + ], + "nixpkgs": [ + "plutarch-safe-money", + "plutarch", + "nixpkgs" + ] + }, "locked": { - "lastModified": 1653778781, - "narHash": "sha256-oEVBaYRLjD4gC3vQuT0DCgmCSIeWSwGPVXXSKJDFUK0=", - "owner": "haskell", - "repo": "haskell-language-server", - "rev": "8c47d6ce2a8409a285a3f4c3f0e10c25fb4dd848", + "lastModified": 1655143375, + "narHash": "sha256-yU+HPLwGPf5IeLj9IBQ1zrPBTYEwvYbuMnADs4T8RLQ=", + "owner": "mlabs-haskell", + "repo": "haskell-nix-extra-hackage", + "rev": "03ee7afdc1ad982e059e3941db80f7a5b30a2757", "type": "github" }, "original": { - "owner": "haskell", - "repo": "haskell-language-server", + "owner": "mlabs-haskell", + "ref": "separate-hackages", + "repo": "haskell-nix-extra-hackage", "type": "github" } }, - "haskell-language-server_24": { - "flake": false, + "haskell-nix-extra-hackage_14": { + "inputs": { + "haskell-nix": [ + "plutarch-safe-money", + "plutarch-numeric", + "plutarch", + "haskell-nix" + ], + "nixpkgs": [ + "plutarch-safe-money", + "plutarch-numeric", + "plutarch", + "nixpkgs" + ] + }, "locked": { - "lastModified": 1650980856, - "narHash": "sha256-uiwsfh/K3IABZDYj7JUZNIAPRVqH6g/r8X6QKg8DrZE=", - "owner": "haskell", - "repo": "haskell-language-server", - "rev": "b5a37f7fc360596899cb2945f363030f44156415", + "lastModified": 1655143375, + "narHash": "sha256-yU+HPLwGPf5IeLj9IBQ1zrPBTYEwvYbuMnADs4T8RLQ=", + "owner": "mlabs-haskell", + "repo": "haskell-nix-extra-hackage", + "rev": "03ee7afdc1ad982e059e3941db80f7a5b30a2757", "type": "github" }, "original": { - "owner": "haskell", - "ref": "1.7.0.0", - "repo": "haskell-language-server", + "owner": "mlabs-haskell", + "ref": "separate-hackages", + "repo": "haskell-nix-extra-hackage", "type": "github" } }, - "haskell-language-server_25": { - "flake": false, + "haskell-nix-extra-hackage_15": { + "inputs": { + "haskell-nix": [ + "plutarch-script-export", + "plutarch", + "haskell-nix" + ], + "nixpkgs": [ + "plutarch-script-export", + "plutarch", + "nixpkgs" + ] + }, "locked": { - "lastModified": 1653778781, - "narHash": "sha256-oEVBaYRLjD4gC3vQuT0DCgmCSIeWSwGPVXXSKJDFUK0=", - "owner": "haskell", - "repo": "haskell-language-server", - "rev": "8c47d6ce2a8409a285a3f4c3f0e10c25fb4dd848", + "lastModified": 1655143375, + "narHash": "sha256-yU+HPLwGPf5IeLj9IBQ1zrPBTYEwvYbuMnADs4T8RLQ=", + "owner": "mlabs-haskell", + "repo": "haskell-nix-extra-hackage", + "rev": "03ee7afdc1ad982e059e3941db80f7a5b30a2757", "type": "github" }, "original": { - "owner": "haskell", - "repo": "haskell-language-server", + "owner": "mlabs-haskell", + "ref": "separate-hackages", + "repo": "haskell-nix-extra-hackage", "type": "github" } }, - "haskell-language-server_26": { - "flake": false, + "haskell-nix-extra-hackage_2": { + "inputs": { + "haskell-nix": [ + "liqwid-plutarch-extra", + "plutarch-context-builder", + "plutarch", + "haskell-nix" + ], + "nixpkgs": [ + "liqwid-plutarch-extra", + "plutarch-context-builder", + "plutarch", + "nixpkgs" + ] + }, "locked": { - "lastModified": 1650980856, - "narHash": "sha256-uiwsfh/K3IABZDYj7JUZNIAPRVqH6g/r8X6QKg8DrZE=", - "owner": "haskell", - "repo": "haskell-language-server", - "rev": "b5a37f7fc360596899cb2945f363030f44156415", + "lastModified": 1655143375, + "narHash": "sha256-yU+HPLwGPf5IeLj9IBQ1zrPBTYEwvYbuMnADs4T8RLQ=", + "owner": "mlabs-haskell", + "repo": "haskell-nix-extra-hackage", + "rev": "03ee7afdc1ad982e059e3941db80f7a5b30a2757", "type": "github" }, "original": { - "owner": "haskell", - "ref": "1.7.0.0", - "repo": "haskell-language-server", + "owner": "mlabs-haskell", + "ref": "separate-hackages", + "repo": "haskell-nix-extra-hackage", "type": "github" } }, - "haskell-language-server_27": { - "flake": false, + "haskell-nix-extra-hackage_3": { + "inputs": { + "haskell-nix": [ + "liqwid-plutarch-extra", + "plutarch-numeric", + "plutarch", + "haskell-nix" + ], + "nixpkgs": [ + "liqwid-plutarch-extra", + "plutarch-numeric", + "plutarch", + "nixpkgs" + ] + }, "locked": { - "lastModified": 1655140576, - "narHash": "sha256-mHJuIk1ElmgPxvEUO2Y3E6T674F2tO5SS/uixf4R2fM=", - "owner": "haskell", - "repo": "haskell-language-server", - "rev": "8a5840a020048c74285f9997b9b02b9b04c658c6", + "lastModified": 1655143375, + "narHash": "sha256-yU+HPLwGPf5IeLj9IBQ1zrPBTYEwvYbuMnADs4T8RLQ=", + "owner": "mlabs-haskell", + "repo": "haskell-nix-extra-hackage", + "rev": "03ee7afdc1ad982e059e3941db80f7a5b30a2757", "type": "github" }, "original": { - "owner": "haskell", - "repo": "haskell-language-server", + "owner": "mlabs-haskell", + "ref": "separate-hackages", + "repo": "haskell-nix-extra-hackage", "type": "github" } }, - "haskell-language-server_28": { - "flake": false, + "haskell-nix-extra-hackage_4": { + "inputs": { + "haskell-nix": [ + "liqwid-plutarch-extra", + "plutarch-quickcheck", + "plutarch", + "haskell-nix" + ], + "nixpkgs": [ + "liqwid-plutarch-extra", + "plutarch-quickcheck", + "plutarch", + "nixpkgs" + ] + }, "locked": { - "lastModified": 1645014262, - "narHash": "sha256-f49So1teiroV+S7sbGTK4AhzUOXpoiQ26/fTjdIKkqc=", - "owner": "haskell", - "repo": "haskell-language-server", - "rev": "96ea854debd92f9a54e2270b9b9a080c0ce6f3d1", + "lastModified": 1655143375, + "narHash": "sha256-yU+HPLwGPf5IeLj9IBQ1zrPBTYEwvYbuMnADs4T8RLQ=", + "owner": "mlabs-haskell", + "repo": "haskell-nix-extra-hackage", + "rev": "03ee7afdc1ad982e059e3941db80f7a5b30a2757", "type": "github" }, "original": { - "owner": "haskell", - "repo": "haskell-language-server", + "owner": "mlabs-haskell", + "ref": "separate-hackages", + "repo": "haskell-nix-extra-hackage", "type": "github" } }, - "haskell-language-server_29": { - "flake": false, + "haskell-nix-extra-hackage_5": { + "inputs": { + "haskell-nix": [ + "plutarch", + "haskell-nix" + ], + "nixpkgs": [ + "plutarch", + "nixpkgs" + ] + }, "locked": { - "lastModified": 1643835246, - "narHash": "sha256-5LQHcQmi3mUGRgJu+X/m3jeM3kdkYjLD+KwgnxBlbeU=", - "owner": "haskell", - "repo": "haskell-language-server", - "rev": "024ddc8b3904f8b8e8fe67ba6b9ebd8a4bd7ce76", + "lastModified": 1655143375, + "narHash": "sha256-yU+HPLwGPf5IeLj9IBQ1zrPBTYEwvYbuMnADs4T8RLQ=", + "owner": "mlabs-haskell", + "repo": "haskell-nix-extra-hackage", + "rev": "03ee7afdc1ad982e059e3941db80f7a5b30a2757", "type": "github" }, "original": { - "owner": "haskell", - "ref": "1.6.1.1", - "repo": "haskell-language-server", + "owner": "mlabs-haskell", + "ref": "separate-hackages", + "repo": "haskell-nix-extra-hackage", "type": "github" } }, - "haskell-language-server_3": { - "flake": false, + "haskell-nix-extra-hackage_6": { + "inputs": { + "haskell-nix": [ + "plutarch-context-builder", + "plutarch", + "haskell-nix" + ], + "nixpkgs": [ + "plutarch-context-builder", + "plutarch", + "nixpkgs" + ] + }, "locked": { - "lastModified": 1650980856, - "narHash": "sha256-uiwsfh/K3IABZDYj7JUZNIAPRVqH6g/r8X6QKg8DrZE=", - "owner": "haskell", - "repo": "haskell-language-server", - "rev": "b5a37f7fc360596899cb2945f363030f44156415", + "lastModified": 1655143375, + "narHash": "sha256-yU+HPLwGPf5IeLj9IBQ1zrPBTYEwvYbuMnADs4T8RLQ=", + "owner": "mlabs-haskell", + "repo": "haskell-nix-extra-hackage", + "rev": "03ee7afdc1ad982e059e3941db80f7a5b30a2757", "type": "github" }, "original": { - "owner": "haskell", - "ref": "1.7.0.0", - "repo": "haskell-language-server", + "owner": "mlabs-haskell", + "ref": "separate-hackages", + "repo": "haskell-nix-extra-hackage", "type": "github" } }, - "haskell-language-server_4": { - "flake": false, + "haskell-nix-extra-hackage_7": { + "inputs": { + "haskell-nix": [ + "plutarch-numeric", + "plutarch", + "haskell-nix" + ], + "nixpkgs": [ + "plutarch-numeric", + "plutarch", + "nixpkgs" + ] + }, "locked": { - "lastModified": 1654120290, - "narHash": "sha256-6NuFBnEzJPvWfvbYxXk/WCQDjsEbjCQ1nAelhBDi4yQ=", - "owner": "haskell", - "repo": "haskell-language-server", - "rev": "140f9040ae88352ca1140a750e7c26485fdfbe17", + "lastModified": 1655143375, + "narHash": "sha256-yU+HPLwGPf5IeLj9IBQ1zrPBTYEwvYbuMnADs4T8RLQ=", + "owner": "mlabs-haskell", + "repo": "haskell-nix-extra-hackage", + "rev": "03ee7afdc1ad982e059e3941db80f7a5b30a2757", "type": "github" }, "original": { - "owner": "haskell", - "repo": "haskell-language-server", + "owner": "mlabs-haskell", + "ref": "separate-hackages", + "repo": "haskell-nix-extra-hackage", "type": "github" } }, - "haskell-language-server_5": { - "flake": false, - "locked": { - "lastModified": 1653778781, - "narHash": "sha256-oEVBaYRLjD4gC3vQuT0DCgmCSIeWSwGPVXXSKJDFUK0=", - "owner": "haskell", - "repo": "haskell-language-server", - "rev": "8c47d6ce2a8409a285a3f4c3f0e10c25fb4dd848", + "haskell-nix-extra-hackage_8": { + "inputs": { + "haskell-nix": [ + "plutarch-quickcheck", + "plutarch", + "haskell-nix" + ], + "nixpkgs": [ + "plutarch-quickcheck", + "plutarch", + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1655143375, + "narHash": "sha256-yU+HPLwGPf5IeLj9IBQ1zrPBTYEwvYbuMnADs4T8RLQ=", + "owner": "mlabs-haskell", + "repo": "haskell-nix-extra-hackage", + "rev": "03ee7afdc1ad982e059e3941db80f7a5b30a2757", "type": "github" }, "original": { - "owner": "haskell", - "repo": "haskell-language-server", + "owner": "mlabs-haskell", + "ref": "separate-hackages", + "repo": "haskell-nix-extra-hackage", "type": "github" } }, - "haskell-language-server_6": { - "flake": false, + "haskell-nix-extra-hackage_9": { + "inputs": { + "haskell-nix": [ + "plutarch-safe-money", + "liqwid-plutarch-extra", + "plutarch", + "haskell-nix" + ], + "nixpkgs": [ + "plutarch-safe-money", + "liqwid-plutarch-extra", + "plutarch", + "nixpkgs" + ] + }, "locked": { - "lastModified": 1650980856, - "narHash": "sha256-uiwsfh/K3IABZDYj7JUZNIAPRVqH6g/r8X6QKg8DrZE=", - "owner": "haskell", - "repo": "haskell-language-server", - "rev": "b5a37f7fc360596899cb2945f363030f44156415", + "lastModified": 1655143375, + "narHash": "sha256-yU+HPLwGPf5IeLj9IBQ1zrPBTYEwvYbuMnADs4T8RLQ=", + "owner": "mlabs-haskell", + "repo": "haskell-nix-extra-hackage", + "rev": "03ee7afdc1ad982e059e3941db80f7a5b30a2757", "type": "github" }, "original": { - "owner": "haskell", - "ref": "1.7.0.0", - "repo": "haskell-language-server", + "owner": "mlabs-haskell", + "ref": "separate-hackages", + "repo": "haskell-nix-extra-hackage", "type": "github" } }, - "haskell-language-server_7": { + "haskell-nix_10": { "flake": false, "locked": { - "lastModified": 1653778781, - "narHash": "sha256-oEVBaYRLjD4gC3vQuT0DCgmCSIeWSwGPVXXSKJDFUK0=", - "owner": "haskell", - "repo": "haskell-language-server", - "rev": "8c47d6ce2a8409a285a3f4c3f0e10c25fb4dd848", + "lastModified": 1651151636, + "narHash": "sha256-WdMP9IMB5kByT0zimDuCYZF/dinRB104H8iDTG/c1Eo=", + "owner": "input-output-hk", + "repo": "haskell.nix", + "rev": "f707aa2e75c0d33473166abc61c0b43ac6e107c0", "type": "github" }, "original": { - "owner": "haskell", - "repo": "haskell-language-server", + "owner": "input-output-hk", + "repo": "haskell.nix", "type": "github" } }, - "haskell-language-server_8": { - "flake": false, + "haskell-nix_11": { + "inputs": { + "HTTP": "HTTP_6", + "cabal-32": "cabal-32_6", + "cabal-34": "cabal-34_6", + "cabal-36": "cabal-36_6", + "cardano-shell": "cardano-shell_6", + "flake-utils": "flake-utils_6", + "ghc-8.6.5-iohk": "ghc-8.6.5-iohk_6", + "hackage": "hackage_6", + "hpc-coveralls": "hpc-coveralls_6", + "hydra": "hydra_6", + "nix-tools": "nix-tools_6", + "nixpkgs": [ + "plutarch-context-builder", + "plutarch", + "haskell-nix", + "nixpkgs-unstable" + ], + "nixpkgs-2003": "nixpkgs-2003_6", + "nixpkgs-2105": "nixpkgs-2105_6", + "nixpkgs-2111": "nixpkgs-2111_12", + "nixpkgs-unstable": "nixpkgs-unstable_6", + "old-ghc-nix": "old-ghc-nix_6", + "stackage": "stackage_6" + }, "locked": { - "lastModified": 1650980856, - "narHash": "sha256-uiwsfh/K3IABZDYj7JUZNIAPRVqH6g/r8X6QKg8DrZE=", - "owner": "haskell", - "repo": "haskell-language-server", - "rev": "b5a37f7fc360596899cb2945f363030f44156415", + "lastModified": 1654068838, + "narHash": "sha256-GHSufC21DSg8Lz2AzIg3DA9DPxGvLqxGFa/4ADoXRhU=", + "owner": "input-output-hk", + "repo": "haskell.nix", + "rev": "fa2fa131fe15e630c91ab4078d12eb32c41f934b", "type": "github" }, "original": { - "owner": "haskell", - "ref": "1.7.0.0", - "repo": "haskell-language-server", + "owner": "input-output-hk", + "repo": "haskell.nix", "type": "github" } }, - "haskell-language-server_9": { + "haskell-nix_12": { "flake": false, "locked": { - "lastModified": 1654120290, - "narHash": "sha256-6NuFBnEzJPvWfvbYxXk/WCQDjsEbjCQ1nAelhBDi4yQ=", - "owner": "haskell", - "repo": "haskell-language-server", - "rev": "140f9040ae88352ca1140a750e7c26485fdfbe17", + "lastModified": 1651151636, + "narHash": "sha256-WdMP9IMB5kByT0zimDuCYZF/dinRB104H8iDTG/c1Eo=", + "owner": "input-output-hk", + "repo": "haskell.nix", + "rev": "f707aa2e75c0d33473166abc61c0b43ac6e107c0", "type": "github" }, "original": { - "owner": "haskell", - "repo": "haskell-language-server", + "owner": "input-output-hk", + "repo": "haskell.nix", "type": "github" } }, - "haskell-nix": { + "haskell-nix_13": { "inputs": { - "HTTP": "HTTP", - "cabal-32": "cabal-32", - "cabal-34": "cabal-34", - "cabal-36": "cabal-36", - "cardano-shell": "cardano-shell", - "flake-utils": "flake-utils_3", - "ghc-8.6.5-iohk": "ghc-8.6.5-iohk", - "hackage": "hackage", - "hpc-coveralls": "hpc-coveralls", - "hydra": "hydra", - "nix-tools": "nix-tools", + "HTTP": "HTTP_7", + "cabal-32": "cabal-32_7", + "cabal-34": "cabal-34_7", + "cabal-36": "cabal-36_7", + "cardano-shell": "cardano-shell_7", + "flake-utils": "flake-utils_7", + "ghc-8.6.5-iohk": "ghc-8.6.5-iohk_7", + "hackage": "hackage_7", + "hpc-coveralls": "hpc-coveralls_7", + "hydra": "hydra_7", + "nix-tools": "nix-tools_7", "nixpkgs": [ - "liqwid-plutarch-extra", + "plutarch-numeric", "plutarch", "haskell-nix", "nixpkgs-unstable" ], - "nixpkgs-2003": "nixpkgs-2003", - "nixpkgs-2105": "nixpkgs-2105", - "nixpkgs-2111": "nixpkgs-2111_2", - "nixpkgs-unstable": "nixpkgs-unstable", - "old-ghc-nix": "old-ghc-nix", - "stackage": "stackage" + "nixpkgs-2003": "nixpkgs-2003_7", + "nixpkgs-2105": "nixpkgs-2105_7", + "nixpkgs-2111": "nixpkgs-2111_14", + "nixpkgs-unstable": "nixpkgs-unstable_7", + "old-ghc-nix": "old-ghc-nix_7", + "stackage": "stackage_7" }, "locked": { "lastModified": 1654068838, @@ -4269,256 +4762,252 @@ "type": "github" } }, - "haskell-nix-extra-hackage": { - "inputs": { - "haskell-nix": [ - "liqwid-plutarch-extra", - "plutarch", - "haskell-nix" - ], - "nixpkgs": [ - "liqwid-plutarch-extra", - "plutarch", - "nixpkgs" - ] - }, + "haskell-nix_14": { + "flake": false, "locked": { - "lastModified": 1653405678, - "narHash": "sha256-fPpPxuCZDF5b/iQgmUg2jspPObsK0mpcchUti/LR8D0=", - "owner": "mlabs-haskell", - "repo": "haskell-nix-extra-hackage", - "rev": "cf4613eb0d883a8c12c86d7cdbdaaf15fdc70128", + "lastModified": 1651151636, + "narHash": "sha256-WdMP9IMB5kByT0zimDuCYZF/dinRB104H8iDTG/c1Eo=", + "owner": "input-output-hk", + "repo": "haskell.nix", + "rev": "f707aa2e75c0d33473166abc61c0b43ac6e107c0", "type": "github" }, "original": { - "owner": "mlabs-haskell", - "repo": "haskell-nix-extra-hackage", + "owner": "input-output-hk", + "repo": "haskell.nix", "type": "github" } }, - "haskell-nix-extra-hackage_2": { + "haskell-nix_15": { "inputs": { - "haskell-nix": [ - "liqwid-plutarch-extra", - "plutarch-quickcheck", - "plutarch", - "haskell-nix" - ], + "HTTP": "HTTP_8", + "cabal-32": "cabal-32_8", + "cabal-34": "cabal-34_8", + "cabal-36": "cabal-36_8", + "cardano-shell": "cardano-shell_8", + "flake-utils": "flake-utils_8", + "ghc-8.6.5-iohk": "ghc-8.6.5-iohk_8", + "hackage": "hackage_8", + "hpc-coveralls": "hpc-coveralls_8", + "hydra": "hydra_8", + "nix-tools": "nix-tools_8", "nixpkgs": [ - "liqwid-plutarch-extra", "plutarch-quickcheck", "plutarch", - "nixpkgs" - ] + "haskell-nix", + "nixpkgs-unstable" + ], + "nixpkgs-2003": "nixpkgs-2003_8", + "nixpkgs-2105": "nixpkgs-2105_8", + "nixpkgs-2111": "nixpkgs-2111_16", + "nixpkgs-unstable": "nixpkgs-unstable_8", + "old-ghc-nix": "old-ghc-nix_8", + "stackage": "stackage_8" }, "locked": { - "lastModified": 1653405678, - "narHash": "sha256-fPpPxuCZDF5b/iQgmUg2jspPObsK0mpcchUti/LR8D0=", - "owner": "mlabs-haskell", - "repo": "haskell-nix-extra-hackage", - "rev": "cf4613eb0d883a8c12c86d7cdbdaaf15fdc70128", + "lastModified": 1654068838, + "narHash": "sha256-GHSufC21DSg8Lz2AzIg3DA9DPxGvLqxGFa/4ADoXRhU=", + "owner": "input-output-hk", + "repo": "haskell.nix", + "rev": "fa2fa131fe15e630c91ab4078d12eb32c41f934b", "type": "github" }, "original": { - "owner": "mlabs-haskell", - "repo": "haskell-nix-extra-hackage", + "owner": "input-output-hk", + "repo": "haskell.nix", "type": "github" } }, - "haskell-nix-extra-hackage_3": { - "inputs": { - "haskell-nix": [ - "plutarch", - "haskell-nix" - ], - "nixpkgs": [ - "plutarch", - "nixpkgs" - ] - }, + "haskell-nix_16": { + "flake": false, "locked": { - "lastModified": 1653405678, - "narHash": "sha256-fPpPxuCZDF5b/iQgmUg2jspPObsK0mpcchUti/LR8D0=", - "owner": "mlabs-haskell", - "repo": "haskell-nix-extra-hackage", - "rev": "cf4613eb0d883a8c12c86d7cdbdaaf15fdc70128", + "lastModified": 1651151636, + "narHash": "sha256-WdMP9IMB5kByT0zimDuCYZF/dinRB104H8iDTG/c1Eo=", + "owner": "input-output-hk", + "repo": "haskell.nix", + "rev": "f707aa2e75c0d33473166abc61c0b43ac6e107c0", "type": "github" }, "original": { - "owner": "mlabs-haskell", - "repo": "haskell-nix-extra-hackage", + "owner": "input-output-hk", + "repo": "haskell.nix", "type": "github" } }, - "haskell-nix-extra-hackage_4": { + "haskell-nix_17": { "inputs": { - "haskell-nix": [ - "plutarch-context-builder", - "plutarch", - "haskell-nix" - ], + "HTTP": "HTTP_9", + "cabal-32": "cabal-32_9", + "cabal-34": "cabal-34_9", + "cabal-36": "cabal-36_9", + "cardano-shell": "cardano-shell_9", + "flake-utils": "flake-utils_9", + "ghc-8.6.5-iohk": "ghc-8.6.5-iohk_9", + "hackage": "hackage_9", + "hpc-coveralls": "hpc-coveralls_9", + "hydra": "hydra_9", + "nix-tools": "nix-tools_9", "nixpkgs": [ - "plutarch-context-builder", + "plutarch-safe-money", + "liqwid-plutarch-extra", "plutarch", - "nixpkgs" - ] + "haskell-nix", + "nixpkgs-unstable" + ], + "nixpkgs-2003": "nixpkgs-2003_9", + "nixpkgs-2105": "nixpkgs-2105_9", + "nixpkgs-2111": "nixpkgs-2111_18", + "nixpkgs-unstable": "nixpkgs-unstable_9", + "old-ghc-nix": "old-ghc-nix_9", + "stackage": "stackage_9" }, "locked": { - "lastModified": 1653405678, - "narHash": "sha256-fPpPxuCZDF5b/iQgmUg2jspPObsK0mpcchUti/LR8D0=", - "owner": "mlabs-haskell", - "repo": "haskell-nix-extra-hackage", - "rev": "cf4613eb0d883a8c12c86d7cdbdaaf15fdc70128", + "lastModified": 1654068838, + "narHash": "sha256-GHSufC21DSg8Lz2AzIg3DA9DPxGvLqxGFa/4ADoXRhU=", + "owner": "input-output-hk", + "repo": "haskell.nix", + "rev": "fa2fa131fe15e630c91ab4078d12eb32c41f934b", "type": "github" }, "original": { - "owner": "mlabs-haskell", - "repo": "haskell-nix-extra-hackage", + "owner": "input-output-hk", + "repo": "haskell.nix", "type": "github" } }, - "haskell-nix-extra-hackage_5": { - "inputs": { - "haskell-nix": [ - "plutarch-numeric", - "plutarch", - "haskell-nix" - ], - "nixpkgs": [ - "plutarch-numeric", - "plutarch", - "nixpkgs" - ] - }, + "haskell-nix_18": { + "flake": false, "locked": { - "lastModified": 1653405678, - "narHash": "sha256-fPpPxuCZDF5b/iQgmUg2jspPObsK0mpcchUti/LR8D0=", - "owner": "mlabs-haskell", - "repo": "haskell-nix-extra-hackage", - "rev": "cf4613eb0d883a8c12c86d7cdbdaaf15fdc70128", + "lastModified": 1651151636, + "narHash": "sha256-WdMP9IMB5kByT0zimDuCYZF/dinRB104H8iDTG/c1Eo=", + "owner": "input-output-hk", + "repo": "haskell.nix", + "rev": "f707aa2e75c0d33473166abc61c0b43ac6e107c0", "type": "github" }, "original": { - "owner": "mlabs-haskell", - "repo": "haskell-nix-extra-hackage", + "owner": "input-output-hk", + "repo": "haskell.nix", "type": "github" } }, - "haskell-nix-extra-hackage_6": { + "haskell-nix_19": { "inputs": { - "haskell-nix": [ - "plutarch-quickcheck", - "plutarch", - "haskell-nix" - ], + "HTTP": "HTTP_10", + "cabal-32": "cabal-32_10", + "cabal-34": "cabal-34_10", + "cabal-36": "cabal-36_10", + "cardano-shell": "cardano-shell_10", + "flake-utils": "flake-utils_10", + "ghc-8.6.5-iohk": "ghc-8.6.5-iohk_10", + "hackage": "hackage_10", + "hpc-coveralls": "hpc-coveralls_10", + "hydra": "hydra_10", + "nix-tools": "nix-tools_10", "nixpkgs": [ - "plutarch-quickcheck", + "plutarch-safe-money", + "liqwid-plutarch-extra", + "plutarch-context-builder", "plutarch", - "nixpkgs" - ] + "haskell-nix", + "nixpkgs-unstable" + ], + "nixpkgs-2003": "nixpkgs-2003_10", + "nixpkgs-2105": "nixpkgs-2105_10", + "nixpkgs-2111": "nixpkgs-2111_20", + "nixpkgs-unstable": "nixpkgs-unstable_10", + "old-ghc-nix": "old-ghc-nix_10", + "stackage": "stackage_10" }, "locked": { - "lastModified": 1653405678, - "narHash": "sha256-fPpPxuCZDF5b/iQgmUg2jspPObsK0mpcchUti/LR8D0=", - "owner": "mlabs-haskell", - "repo": "haskell-nix-extra-hackage", - "rev": "cf4613eb0d883a8c12c86d7cdbdaaf15fdc70128", + "lastModified": 1654068838, + "narHash": "sha256-GHSufC21DSg8Lz2AzIg3DA9DPxGvLqxGFa/4ADoXRhU=", + "owner": "input-output-hk", + "repo": "haskell.nix", + "rev": "fa2fa131fe15e630c91ab4078d12eb32c41f934b", "type": "github" }, "original": { - "owner": "mlabs-haskell", - "repo": "haskell-nix-extra-hackage", + "owner": "input-output-hk", + "repo": "haskell.nix", "type": "github" } }, - "haskell-nix-extra-hackage_7": { - "inputs": { - "haskell-nix": [ - "plutarch-safe-money", - "liqwid-plutarch-extra", - "plutarch", - "haskell-nix" - ], - "nixpkgs": [ - "plutarch-safe-money", - "liqwid-plutarch-extra", - "plutarch", - "nixpkgs" - ] - }, + "haskell-nix_2": { + "flake": false, "locked": { - "lastModified": 1653405678, - "narHash": "sha256-fPpPxuCZDF5b/iQgmUg2jspPObsK0mpcchUti/LR8D0=", - "owner": "mlabs-haskell", - "repo": "haskell-nix-extra-hackage", - "rev": "cf4613eb0d883a8c12c86d7cdbdaaf15fdc70128", + "lastModified": 1651151636, + "narHash": "sha256-WdMP9IMB5kByT0zimDuCYZF/dinRB104H8iDTG/c1Eo=", + "owner": "input-output-hk", + "repo": "haskell.nix", + "rev": "f707aa2e75c0d33473166abc61c0b43ac6e107c0", "type": "github" }, "original": { - "owner": "mlabs-haskell", - "repo": "haskell-nix-extra-hackage", + "owner": "input-output-hk", + "repo": "haskell.nix", "type": "github" } }, - "haskell-nix-extra-hackage_8": { - "inputs": { - "haskell-nix": [ - "plutarch-safe-money", - "liqwid-plutarch-extra", - "plutarch-quickcheck", - "plutarch", - "haskell-nix" - ], - "nixpkgs": [ - "plutarch-safe-money", - "liqwid-plutarch-extra", - "plutarch-quickcheck", - "plutarch", - "nixpkgs" - ] - }, + "haskell-nix_20": { + "flake": false, "locked": { - "lastModified": 1653405678, - "narHash": "sha256-fPpPxuCZDF5b/iQgmUg2jspPObsK0mpcchUti/LR8D0=", - "owner": "mlabs-haskell", - "repo": "haskell-nix-extra-hackage", - "rev": "cf4613eb0d883a8c12c86d7cdbdaaf15fdc70128", + "lastModified": 1651151636, + "narHash": "sha256-WdMP9IMB5kByT0zimDuCYZF/dinRB104H8iDTG/c1Eo=", + "owner": "input-output-hk", + "repo": "haskell.nix", + "rev": "f707aa2e75c0d33473166abc61c0b43ac6e107c0", "type": "github" }, "original": { - "owner": "mlabs-haskell", - "repo": "haskell-nix-extra-hackage", + "owner": "input-output-hk", + "repo": "haskell.nix", "type": "github" } }, - "haskell-nix-extra-hackage_9": { + "haskell-nix_21": { "inputs": { - "haskell-nix": [ - "plutarch-safe-money", - "plutarch", - "haskell-nix" - ], + "HTTP": "HTTP_11", + "cabal-32": "cabal-32_11", + "cabal-34": "cabal-34_11", + "cabal-36": "cabal-36_11", + "cardano-shell": "cardano-shell_11", + "flake-utils": "flake-utils_11", + "ghc-8.6.5-iohk": "ghc-8.6.5-iohk_11", + "hackage": "hackage_11", + "hpc-coveralls": "hpc-coveralls_11", + "hydra": "hydra_11", + "nix-tools": "nix-tools_11", "nixpkgs": [ "plutarch-safe-money", + "liqwid-plutarch-extra", + "plutarch-numeric", "plutarch", - "nixpkgs" - ] + "haskell-nix", + "nixpkgs-unstable" + ], + "nixpkgs-2003": "nixpkgs-2003_11", + "nixpkgs-2105": "nixpkgs-2105_11", + "nixpkgs-2111": "nixpkgs-2111_22", + "nixpkgs-unstable": "nixpkgs-unstable_11", + "old-ghc-nix": "old-ghc-nix_11", + "stackage": "stackage_11" }, "locked": { - "lastModified": 1653405678, - "narHash": "sha256-fPpPxuCZDF5b/iQgmUg2jspPObsK0mpcchUti/LR8D0=", - "owner": "mlabs-haskell", - "repo": "haskell-nix-extra-hackage", - "rev": "cf4613eb0d883a8c12c86d7cdbdaaf15fdc70128", + "lastModified": 1654068838, + "narHash": "sha256-GHSufC21DSg8Lz2AzIg3DA9DPxGvLqxGFa/4ADoXRhU=", + "owner": "input-output-hk", + "repo": "haskell.nix", + "rev": "fa2fa131fe15e630c91ab4078d12eb32c41f934b", "type": "github" }, "original": { - "owner": "mlabs-haskell", - "repo": "haskell-nix-extra-hackage", + "owner": "input-output-hk", + "repo": "haskell.nix", "type": "github" } }, - "haskell-nix_10": { + "haskell-nix_22": { "flake": false, "locked": { "lastModified": 1651151636, @@ -4534,31 +5023,33 @@ "type": "github" } }, - "haskell-nix_11": { + "haskell-nix_23": { "inputs": { - "HTTP": "HTTP_6", - "cabal-32": "cabal-32_6", - "cabal-34": "cabal-34_6", - "cabal-36": "cabal-36_6", - "cardano-shell": "cardano-shell_6", - "flake-utils": "flake-utils_16", - "ghc-8.6.5-iohk": "ghc-8.6.5-iohk_6", - "hackage": "hackage_6", - "hpc-coveralls": "hpc-coveralls_6", - "hydra": "hydra_6", - "nix-tools": "nix-tools_6", + "HTTP": "HTTP_12", + "cabal-32": "cabal-32_12", + "cabal-34": "cabal-34_12", + "cabal-36": "cabal-36_12", + "cardano-shell": "cardano-shell_12", + "flake-utils": "flake-utils_12", + "ghc-8.6.5-iohk": "ghc-8.6.5-iohk_12", + "hackage": "hackage_12", + "hpc-coveralls": "hpc-coveralls_12", + "hydra": "hydra_12", + "nix-tools": "nix-tools_12", "nixpkgs": [ + "plutarch-safe-money", + "liqwid-plutarch-extra", "plutarch-quickcheck", "plutarch", "haskell-nix", "nixpkgs-unstable" ], - "nixpkgs-2003": "nixpkgs-2003_6", - "nixpkgs-2105": "nixpkgs-2105_6", - "nixpkgs-2111": "nixpkgs-2111_12", - "nixpkgs-unstable": "nixpkgs-unstable_6", - "old-ghc-nix": "old-ghc-nix_6", - "stackage": "stackage_6" + "nixpkgs-2003": "nixpkgs-2003_12", + "nixpkgs-2105": "nixpkgs-2105_12", + "nixpkgs-2111": "nixpkgs-2111_24", + "nixpkgs-unstable": "nixpkgs-unstable_12", + "old-ghc-nix": "old-ghc-nix_12", + "stackage": "stackage_12" }, "locked": { "lastModified": 1654068838, @@ -4574,7 +5065,7 @@ "type": "github" } }, - "haskell-nix_12": { + "haskell-nix_24": { "flake": false, "locked": { "lastModified": 1651151636, @@ -4590,32 +5081,31 @@ "type": "github" } }, - "haskell-nix_13": { + "haskell-nix_25": { "inputs": { - "HTTP": "HTTP_7", - "cabal-32": "cabal-32_7", - "cabal-34": "cabal-34_7", - "cabal-36": "cabal-36_7", - "cardano-shell": "cardano-shell_7", - "flake-utils": "flake-utils_19", - "ghc-8.6.5-iohk": "ghc-8.6.5-iohk_7", - "hackage": "hackage_7", - "hpc-coveralls": "hpc-coveralls_7", - "hydra": "hydra_7", - "nix-tools": "nix-tools_7", + "HTTP": "HTTP_13", + "cabal-32": "cabal-32_13", + "cabal-34": "cabal-34_13", + "cabal-36": "cabal-36_13", + "cardano-shell": "cardano-shell_13", + "flake-utils": "flake-utils_13", + "ghc-8.6.5-iohk": "ghc-8.6.5-iohk_13", + "hackage": "hackage_13", + "hpc-coveralls": "hpc-coveralls_13", + "hydra": "hydra_13", + "nix-tools": "nix-tools_13", "nixpkgs": [ "plutarch-safe-money", - "liqwid-plutarch-extra", "plutarch", "haskell-nix", "nixpkgs-unstable" ], - "nixpkgs-2003": "nixpkgs-2003_7", - "nixpkgs-2105": "nixpkgs-2105_7", - "nixpkgs-2111": "nixpkgs-2111_14", - "nixpkgs-unstable": "nixpkgs-unstable_7", - "old-ghc-nix": "old-ghc-nix_7", - "stackage": "stackage_7" + "nixpkgs-2003": "nixpkgs-2003_13", + "nixpkgs-2105": "nixpkgs-2105_13", + "nixpkgs-2111": "nixpkgs-2111_26", + "nixpkgs-unstable": "nixpkgs-unstable_13", + "old-ghc-nix": "old-ghc-nix_13", + "stackage": "stackage_13" }, "locked": { "lastModified": 1654068838, @@ -4631,7 +5121,7 @@ "type": "github" } }, - "haskell-nix_14": { + "haskell-nix_26": { "flake": false, "locked": { "lastModified": 1651151636, @@ -4647,33 +5137,32 @@ "type": "github" } }, - "haskell-nix_15": { + "haskell-nix_27": { "inputs": { - "HTTP": "HTTP_8", - "cabal-32": "cabal-32_8", - "cabal-34": "cabal-34_8", - "cabal-36": "cabal-36_8", - "cardano-shell": "cardano-shell_8", - "flake-utils": "flake-utils_22", - "ghc-8.6.5-iohk": "ghc-8.6.5-iohk_8", - "hackage": "hackage_8", - "hpc-coveralls": "hpc-coveralls_8", - "hydra": "hydra_8", - "nix-tools": "nix-tools_8", + "HTTP": "HTTP_14", + "cabal-32": "cabal-32_14", + "cabal-34": "cabal-34_14", + "cabal-36": "cabal-36_14", + "cardano-shell": "cardano-shell_14", + "flake-utils": "flake-utils_14", + "ghc-8.6.5-iohk": "ghc-8.6.5-iohk_14", + "hackage": "hackage_14", + "hpc-coveralls": "hpc-coveralls_14", + "hydra": "hydra_14", + "nix-tools": "nix-tools_14", "nixpkgs": [ "plutarch-safe-money", - "liqwid-plutarch-extra", - "plutarch-quickcheck", + "plutarch-numeric", "plutarch", "haskell-nix", "nixpkgs-unstable" ], - "nixpkgs-2003": "nixpkgs-2003_8", - "nixpkgs-2105": "nixpkgs-2105_8", - "nixpkgs-2111": "nixpkgs-2111_16", - "nixpkgs-unstable": "nixpkgs-unstable_8", - "old-ghc-nix": "old-ghc-nix_8", - "stackage": "stackage_8" + "nixpkgs-2003": "nixpkgs-2003_14", + "nixpkgs-2105": "nixpkgs-2105_14", + "nixpkgs-2111": "nixpkgs-2111_28", + "nixpkgs-unstable": "nixpkgs-unstable_14", + "old-ghc-nix": "old-ghc-nix_14", + "stackage": "stackage_14" }, "locked": { "lastModified": 1654068838, @@ -4689,7 +5178,7 @@ "type": "github" } }, - "haskell-nix_16": { + "haskell-nix_28": { "flake": false, "locked": { "lastModified": 1651151636, @@ -4705,31 +5194,31 @@ "type": "github" } }, - "haskell-nix_17": { + "haskell-nix_29": { "inputs": { - "HTTP": "HTTP_9", - "cabal-32": "cabal-32_9", - "cabal-34": "cabal-34_9", - "cabal-36": "cabal-36_9", - "cardano-shell": "cardano-shell_9", - "flake-utils": "flake-utils_25", - "ghc-8.6.5-iohk": "ghc-8.6.5-iohk_9", - "hackage": "hackage_9", - "hpc-coveralls": "hpc-coveralls_9", - "hydra": "hydra_9", - "nix-tools": "nix-tools_9", + "HTTP": "HTTP_15", + "cabal-32": "cabal-32_15", + "cabal-34": "cabal-34_15", + "cabal-36": "cabal-36_15", + "cardano-shell": "cardano-shell_15", + "flake-utils": "flake-utils_15", + "ghc-8.6.5-iohk": "ghc-8.6.5-iohk_15", + "hackage": "hackage_15", + "hpc-coveralls": "hpc-coveralls_15", + "hydra": "hydra_15", + "nix-tools": "nix-tools_15", "nixpkgs": [ - "plutarch-safe-money", + "plutarch-script-export", "plutarch", "haskell-nix", "nixpkgs-unstable" ], - "nixpkgs-2003": "nixpkgs-2003_9", - "nixpkgs-2105": "nixpkgs-2105_9", - "nixpkgs-2111": "nixpkgs-2111_18", - "nixpkgs-unstable": "nixpkgs-unstable_9", - "old-ghc-nix": "old-ghc-nix_9", - "stackage": "stackage_9" + "nixpkgs-2003": "nixpkgs-2003_15", + "nixpkgs-2105": "nixpkgs-2105_15", + "nixpkgs-2111": "nixpkgs-2111_30", + "nixpkgs-unstable": "nixpkgs-unstable_15", + "old-ghc-nix": "old-ghc-nix_15", + "stackage": "stackage_15" }, "locked": { "lastModified": 1654068838, @@ -4745,95 +5234,6 @@ "type": "github" } }, - "haskell-nix_18": { - "flake": false, - "locked": { - "lastModified": 1651151636, - "narHash": "sha256-WdMP9IMB5kByT0zimDuCYZF/dinRB104H8iDTG/c1Eo=", - "owner": "input-output-hk", - "repo": "haskell.nix", - "rev": "f707aa2e75c0d33473166abc61c0b43ac6e107c0", - "type": "github" - }, - "original": { - "owner": "input-output-hk", - "repo": "haskell.nix", - "type": "github" - } - }, - "haskell-nix_19": { - "inputs": { - "HTTP": "HTTP_10", - "cabal-32": "cabal-32_10", - "cabal-34": "cabal-34_10", - "cabal-36": "cabal-36_10", - "cardano-shell": "cardano-shell_10", - "flake-utils": "flake-utils_31", - "ghc-8.6.5-iohk": "ghc-8.6.5-iohk_10", - "hackage": "hackage_10", - "hpc-coveralls": "hpc-coveralls_10", - "nix-tools": "nix-tools_10", - "nixpkgs": [ - "plutarch-safe-money", - "plutarch-numeric", - "plutarch", - "haskell-nix", - "nixpkgs-unstable" - ], - "nixpkgs-2003": "nixpkgs-2003_10", - "nixpkgs-2105": "nixpkgs-2105_10", - "nixpkgs-2111": "nixpkgs-2111_20", - "nixpkgs-unstable": "nixpkgs-unstable_10", - "old-ghc-nix": "old-ghc-nix_10", - "stackage": "stackage_10" - }, - "locked": { - "lastModified": 1644944726, - "narHash": "sha256-jJWdP/3Ne1y1akC3m9rSO5ItRoBc4UTdVQZBCuPmmrM=", - "owner": "L-as", - "repo": "haskell.nix", - "rev": "45c583b5580c130487eb5a342679f0bdbc2b23fc", - "type": "github" - }, - "original": { - "owner": "L-as", - "ref": "master", - "repo": "haskell.nix", - "type": "github" - } - }, - "haskell-nix_2": { - "flake": false, - "locked": { - "lastModified": 1651151636, - "narHash": "sha256-WdMP9IMB5kByT0zimDuCYZF/dinRB104H8iDTG/c1Eo=", - "owner": "input-output-hk", - "repo": "haskell.nix", - "rev": "f707aa2e75c0d33473166abc61c0b43ac6e107c0", - "type": "github" - }, - "original": { - "owner": "input-output-hk", - "repo": "haskell.nix", - "type": "github" - } - }, - "haskell-nix_20": { - "flake": false, - "locked": { - "lastModified": 1629380841, - "narHash": "sha256-gWOWCfX7IgVSvMMYN6rBGK6EA0pk6pmYguXzMvGte+Q=", - "owner": "input-output-hk", - "repo": "haskell.nix", - "rev": "7215f083b37741446aa325b20c8ba9f9f76015eb", - "type": "github" - }, - "original": { - "owner": "input-output-hk", - "repo": "haskell.nix", - "type": "github" - } - }, "haskell-nix_3": { "inputs": { "HTTP": "HTTP_2", @@ -4841,7 +5241,7 @@ "cabal-34": "cabal-34_2", "cabal-36": "cabal-36_2", "cardano-shell": "cardano-shell_2", - "flake-utils": "flake-utils_6", + "flake-utils": "flake-utils_2", "ghc-8.6.5-iohk": "ghc-8.6.5-iohk_2", "hackage": "hackage_2", "hpc-coveralls": "hpc-coveralls_2", @@ -4849,7 +5249,7 @@ "nix-tools": "nix-tools_2", "nixpkgs": [ "liqwid-plutarch-extra", - "plutarch-quickcheck", + "plutarch-context-builder", "plutarch", "haskell-nix", "nixpkgs-unstable" @@ -4875,6 +5275,22 @@ "type": "github" } }, + "haskell-nix_30": { + "flake": false, + "locked": { + "lastModified": 1651151636, + "narHash": "sha256-WdMP9IMB5kByT0zimDuCYZF/dinRB104H8iDTG/c1Eo=", + "owner": "input-output-hk", + "repo": "haskell.nix", + "rev": "f707aa2e75c0d33473166abc61c0b43ac6e107c0", + "type": "github" + }, + "original": { + "owner": "input-output-hk", + "repo": "haskell.nix", + "type": "github" + } + }, "haskell-nix_4": { "flake": false, "locked": { @@ -4898,13 +5314,15 @@ "cabal-34": "cabal-34_3", "cabal-36": "cabal-36_3", "cardano-shell": "cardano-shell_3", - "flake-utils": "flake-utils_7", + "flake-utils": "flake-utils_3", "ghc-8.6.5-iohk": "ghc-8.6.5-iohk_3", "hackage": "hackage_3", "hpc-coveralls": "hpc-coveralls_3", "hydra": "hydra_3", "nix-tools": "nix-tools_3", "nixpkgs": [ + "liqwid-plutarch-extra", + "plutarch-numeric", "plutarch", "haskell-nix", "nixpkgs-unstable" @@ -4953,14 +5371,15 @@ "cabal-34": "cabal-34_4", "cabal-36": "cabal-36_4", "cardano-shell": "cardano-shell_4", - "flake-utils": "flake-utils_10", + "flake-utils": "flake-utils_4", "ghc-8.6.5-iohk": "ghc-8.6.5-iohk_4", "hackage": "hackage_4", "hpc-coveralls": "hpc-coveralls_4", "hydra": "hydra_4", "nix-tools": "nix-tools_4", "nixpkgs": [ - "plutarch-context-builder", + "liqwid-plutarch-extra", + "plutarch-quickcheck", "plutarch", "haskell-nix", "nixpkgs-unstable" @@ -5009,14 +5428,13 @@ "cabal-34": "cabal-34_5", "cabal-36": "cabal-36_5", "cardano-shell": "cardano-shell_5", - "flake-utils": "flake-utils_13", + "flake-utils": "flake-utils_5", "ghc-8.6.5-iohk": "ghc-8.6.5-iohk_5", "hackage": "hackage_5", "hpc-coveralls": "hpc-coveralls_5", "hydra": "hydra_5", "nix-tools": "nix-tools_5", "nixpkgs": [ - "plutarch-numeric", "plutarch", "haskell-nix", "nixpkgs-unstable" @@ -5042,162 +5460,99 @@ "type": "github" } }, - "heist": { - "flake": false, - "locked": { - "lastModified": 1653169917, - "narHash": "sha256-i52wi4nNC6ATx8gTtmpLnxQZEhKSM0LbpmSu57d5VqI=", - "owner": "srid", - "repo": "heist", - "rev": "75533cade1a0d9859ff487cbf6f22e98711248d3", - "type": "github" + "hercules-ci-effects": { + "inputs": { + "nixpkgs": "nixpkgs_4" }, - "original": { - "owner": "srid", - "ref": "emanote", - "repo": "heist", - "type": "github" - } - }, - "heist_2": { - "flake": false, "locked": { - "lastModified": 1653169917, - "narHash": "sha256-i52wi4nNC6ATx8gTtmpLnxQZEhKSM0LbpmSu57d5VqI=", - "owner": "srid", - "repo": "heist", - "rev": "75533cade1a0d9859ff487cbf6f22e98711248d3", + "lastModified": 1653841712, + "narHash": "sha256-XBF4i1MuIRAEbFpj3Z3fVaYxzNEsYapyENtw3vG+q1I=", + "owner": "hercules-ci", + "repo": "hercules-ci-effects", + "rev": "e14d2131b7c81acca3904b584ac45fb72da64dd2", "type": "github" }, "original": { - "owner": "srid", - "ref": "emanote", - "repo": "heist", + "owner": "hercules-ci", + "repo": "hercules-ci-effects", "type": "github" } }, - "heist_3": { - "flake": false, - "locked": { - "lastModified": 1653169917, - "narHash": "sha256-i52wi4nNC6ATx8gTtmpLnxQZEhKSM0LbpmSu57d5VqI=", - "owner": "srid", - "repo": "heist", - "rev": "75533cade1a0d9859ff487cbf6f22e98711248d3", - "type": "github" + "hercules-ci-effects_10": { + "inputs": { + "nixpkgs": "nixpkgs_40" }, - "original": { - "owner": "srid", - "ref": "emanote", - "repo": "heist", - "type": "github" - } - }, - "heist_4": { - "flake": false, "locked": { - "lastModified": 1653169917, - "narHash": "sha256-i52wi4nNC6ATx8gTtmpLnxQZEhKSM0LbpmSu57d5VqI=", - "owner": "srid", - "repo": "heist", - "rev": "75533cade1a0d9859ff487cbf6f22e98711248d3", + "lastModified": 1653841712, + "narHash": "sha256-XBF4i1MuIRAEbFpj3Z3fVaYxzNEsYapyENtw3vG+q1I=", + "owner": "hercules-ci", + "repo": "hercules-ci-effects", + "rev": "e14d2131b7c81acca3904b584ac45fb72da64dd2", "type": "github" }, "original": { - "owner": "srid", - "ref": "emanote", - "repo": "heist", + "owner": "hercules-ci", + "repo": "hercules-ci-effects", "type": "github" } }, - "heist_5": { - "flake": false, - "locked": { - "lastModified": 1653169917, - "narHash": "sha256-i52wi4nNC6ATx8gTtmpLnxQZEhKSM0LbpmSu57d5VqI=", - "owner": "srid", - "repo": "heist", - "rev": "75533cade1a0d9859ff487cbf6f22e98711248d3", - "type": "github" + "hercules-ci-effects_11": { + "inputs": { + "nixpkgs": "nixpkgs_44" }, - "original": { - "owner": "srid", - "ref": "emanote", - "repo": "heist", - "type": "github" - } - }, - "heist_6": { - "flake": false, "locked": { - "lastModified": 1653169917, - "narHash": "sha256-i52wi4nNC6ATx8gTtmpLnxQZEhKSM0LbpmSu57d5VqI=", - "owner": "srid", - "repo": "heist", - "rev": "75533cade1a0d9859ff487cbf6f22e98711248d3", + "lastModified": 1653841712, + "narHash": "sha256-XBF4i1MuIRAEbFpj3Z3fVaYxzNEsYapyENtw3vG+q1I=", + "owner": "hercules-ci", + "repo": "hercules-ci-effects", + "rev": "e14d2131b7c81acca3904b584ac45fb72da64dd2", "type": "github" }, "original": { - "owner": "srid", - "ref": "emanote", - "repo": "heist", + "owner": "hercules-ci", + "repo": "hercules-ci-effects", "type": "github" } }, - "heist_7": { - "flake": false, - "locked": { - "lastModified": 1653169917, - "narHash": "sha256-i52wi4nNC6ATx8gTtmpLnxQZEhKSM0LbpmSu57d5VqI=", - "owner": "srid", - "repo": "heist", - "rev": "75533cade1a0d9859ff487cbf6f22e98711248d3", - "type": "github" + "hercules-ci-effects_12": { + "inputs": { + "nixpkgs": "nixpkgs_48" }, - "original": { - "owner": "srid", - "ref": "emanote", - "repo": "heist", - "type": "github" - } - }, - "heist_8": { - "flake": false, "locked": { - "lastModified": 1653169917, - "narHash": "sha256-i52wi4nNC6ATx8gTtmpLnxQZEhKSM0LbpmSu57d5VqI=", - "owner": "srid", - "repo": "heist", - "rev": "75533cade1a0d9859ff487cbf6f22e98711248d3", + "lastModified": 1653841712, + "narHash": "sha256-XBF4i1MuIRAEbFpj3Z3fVaYxzNEsYapyENtw3vG+q1I=", + "owner": "hercules-ci", + "repo": "hercules-ci-effects", + "rev": "e14d2131b7c81acca3904b584ac45fb72da64dd2", "type": "github" }, "original": { - "owner": "srid", - "ref": "emanote", - "repo": "heist", + "owner": "hercules-ci", + "repo": "hercules-ci-effects", "type": "github" } }, - "heist_9": { - "flake": false, + "hercules-ci-effects_13": { + "inputs": { + "nixpkgs": "nixpkgs_51" + }, "locked": { - "lastModified": 1649279862, - "narHash": "sha256-YPD7Qv1ZcXM4uAlsZ2P/2CKen4H2OY3VHHGluYFVulg=", - "owner": "srid", - "repo": "heist", - "rev": "085c7ab88b73079de27c8def27d67f03853fde05", + "lastModified": 1653841712, + "narHash": "sha256-XBF4i1MuIRAEbFpj3Z3fVaYxzNEsYapyENtw3vG+q1I=", + "owner": "hercules-ci", + "repo": "hercules-ci-effects", + "rev": "e14d2131b7c81acca3904b584ac45fb72da64dd2", "type": "github" }, "original": { - "owner": "srid", - "ref": "emanote-release--ghc9", - "repo": "heist", + "owner": "hercules-ci", + "repo": "hercules-ci-effects", "type": "github" } }, - "hercules-ci-effects": { + "hercules-ci-effects_14": { "inputs": { - "nixpkgs": "nixpkgs_4" + "nixpkgs": "nixpkgs_55" }, "locked": { "lastModified": 1653841712, @@ -5213,16 +5568,16 @@ "type": "github" } }, - "hercules-ci-effects_10": { + "hercules-ci-effects_15": { "inputs": { - "nixpkgs": "nixpkgs_48" + "nixpkgs": "nixpkgs_59" }, "locked": { - "lastModified": 1647711660, - "narHash": "sha256-ZoV/oAH8g4NYeTzC7OCZnlM7l0hNBs0nUHf4l1+lmDc=", + "lastModified": 1653841712, + "narHash": "sha256-XBF4i1MuIRAEbFpj3Z3fVaYxzNEsYapyENtw3vG+q1I=", "owner": "hercules-ci", "repo": "hercules-ci-effects", - "rev": "d17e41cfb454d07f5d8d3b667bf45b079d868541", + "rev": "e14d2131b7c81acca3904b584ac45fb72da64dd2", "type": "github" }, "original": { @@ -5233,7 +5588,7 @@ }, "hercules-ci-effects_2": { "inputs": { - "nixpkgs": "nixpkgs_9" + "nixpkgs": "nixpkgs_8" }, "locked": { "lastModified": 1653841712, @@ -5269,7 +5624,7 @@ }, "hercules-ci-effects_4": { "inputs": { - "nixpkgs": "nixpkgs_17" + "nixpkgs": "nixpkgs_16" }, "locked": { "lastModified": 1653841712, @@ -5287,7 +5642,7 @@ }, "hercules-ci-effects_5": { "inputs": { - "nixpkgs": "nixpkgs_22" + "nixpkgs": "nixpkgs_19" }, "locked": { "lastModified": 1653841712, @@ -5305,7 +5660,7 @@ }, "hercules-ci-effects_6": { "inputs": { - "nixpkgs": "nixpkgs_27" + "nixpkgs": "nixpkgs_23" }, "locked": { "lastModified": 1653841712, @@ -5323,7 +5678,7 @@ }, "hercules-ci-effects_7": { "inputs": { - "nixpkgs": "nixpkgs_32" + "nixpkgs": "nixpkgs_27" }, "locked": { "lastModified": 1653841712, @@ -5341,7 +5696,7 @@ }, "hercules-ci-effects_8": { "inputs": { - "nixpkgs": "nixpkgs_37" + "nixpkgs": "nixpkgs_31" }, "locked": { "lastModified": 1653841712, @@ -5359,7 +5714,7 @@ }, "hercules-ci-effects_9": { "inputs": { - "nixpkgs": "nixpkgs_42" + "nixpkgs": "nixpkgs_36" }, "locked": { "lastModified": 1653841712, @@ -5407,7 +5762,7 @@ "type": "github" } }, - "hpc-coveralls_2": { + "hpc-coveralls_11": { "flake": false, "locked": { "lastModified": 1607498076, @@ -5423,7 +5778,7 @@ "type": "github" } }, - "hpc-coveralls_3": { + "hpc-coveralls_12": { "flake": false, "locked": { "lastModified": 1607498076, @@ -5439,7 +5794,7 @@ "type": "github" } }, - "hpc-coveralls_4": { + "hpc-coveralls_13": { "flake": false, "locked": { "lastModified": 1607498076, @@ -5455,7 +5810,7 @@ "type": "github" } }, - "hpc-coveralls_5": { + "hpc-coveralls_14": { "flake": false, "locked": { "lastModified": 1607498076, @@ -5471,7 +5826,7 @@ "type": "github" } }, - "hpc-coveralls_6": { + "hpc-coveralls_15": { "flake": false, "locked": { "lastModified": 1607498076, @@ -5487,7 +5842,7 @@ "type": "github" } }, - "hpc-coveralls_7": { + "hpc-coveralls_2": { "flake": false, "locked": { "lastModified": 1607498076, @@ -5503,7 +5858,7 @@ "type": "github" } }, - "hpc-coveralls_8": { + "hpc-coveralls_3": { "flake": false, "locked": { "lastModified": 1607498076, @@ -5519,7 +5874,7 @@ "type": "github" } }, - "hpc-coveralls_9": { + "hpc-coveralls_4": { "flake": false, "locked": { "lastModified": 1607498076, @@ -5535,69 +5890,83 @@ "type": "github" } }, - "hs-memory": { + "hpc-coveralls_5": { "flake": false, "locked": { - "lastModified": 1636757734, - "narHash": "sha256-DIlt0NpFUx8IUeTcgZNBJWWfyNaKv5ZKYw1K9aLvxBs=", - "owner": "vincenthz", - "repo": "hs-memory", - "rev": "3cf661a8a9a8ac028df77daa88e8d65c55a3347a", + "lastModified": 1607498076, + "narHash": "sha256-8uqsEtivphgZWYeUo5RDUhp6bO9j2vaaProQxHBltQk=", + "owner": "sevanspowell", + "repo": "hpc-coveralls", + "rev": "14df0f7d229f4cd2e79f8eabb1a740097fdfa430", "type": "github" }, "original": { - "owner": "vincenthz", - "repo": "hs-memory", - "rev": "3cf661a8a9a8ac028df77daa88e8d65c55a3347a", + "owner": "sevanspowell", + "repo": "hpc-coveralls", "type": "github" } }, - "hspec": { + "hpc-coveralls_6": { "flake": false, "locked": { - "lastModified": 1649095108, - "narHash": "sha256-cPmt4hvmdh727VT6UAL8yFArmm4FAWeg3K5Qi3XtU4g=", - "owner": "srid", - "repo": "hspec", - "rev": "44f2a143e10c93df237af428457d0e4b74ae270a", + "lastModified": 1607498076, + "narHash": "sha256-8uqsEtivphgZWYeUo5RDUhp6bO9j2vaaProQxHBltQk=", + "owner": "sevanspowell", + "repo": "hpc-coveralls", + "rev": "14df0f7d229f4cd2e79f8eabb1a740097fdfa430", "type": "github" }, "original": { - "owner": "srid", - "ref": "askAncestors", - "repo": "hspec", + "owner": "sevanspowell", + "repo": "hpc-coveralls", "type": "github" } }, - "hspec-golden": { + "hpc-coveralls_7": { "flake": false, "locked": { - "lastModified": 1648755064, - "narHash": "sha256-5a6BksZx00o2iL0Ei/L1Kkou2BsnsIagN+tTmqYyKfs=", - "owner": "stackbuilders", - "repo": "hspec-golden", - "rev": "4b0ad56b2de0254a7b1e0feda917656f78a5bcda", + "lastModified": 1607498076, + "narHash": "sha256-8uqsEtivphgZWYeUo5RDUhp6bO9j2vaaProQxHBltQk=", + "owner": "sevanspowell", + "repo": "hpc-coveralls", + "rev": "14df0f7d229f4cd2e79f8eabb1a740097fdfa430", "type": "github" }, "original": { - "owner": "stackbuilders", - "repo": "hspec-golden", + "owner": "sevanspowell", + "repo": "hpc-coveralls", "type": "github" } }, - "hspec-hedgehog": { + "hpc-coveralls_8": { "flake": false, "locked": { - "lastModified": 1602603478, - "narHash": "sha256-XnS3zjQ7eh3iBOWq+Z/YcwrfWI55hV6k8LsZ8qm/qOc=", - "owner": "parsonsmatt", - "repo": "hspec-hedgehog", - "rev": "eb617d854542510f0129acdea4bf52e50b13042e", + "lastModified": 1607498076, + "narHash": "sha256-8uqsEtivphgZWYeUo5RDUhp6bO9j2vaaProQxHBltQk=", + "owner": "sevanspowell", + "repo": "hpc-coveralls", + "rev": "14df0f7d229f4cd2e79f8eabb1a740097fdfa430", + "type": "github" + }, + "original": { + "owner": "sevanspowell", + "repo": "hpc-coveralls", + "type": "github" + } + }, + "hpc-coveralls_9": { + "flake": false, + "locked": { + "lastModified": 1607498076, + "narHash": "sha256-8uqsEtivphgZWYeUo5RDUhp6bO9j2vaaProQxHBltQk=", + "owner": "sevanspowell", + "repo": "hpc-coveralls", + "rev": "14df0f7d229f4cd2e79f8eabb1a740097fdfa430", "type": "github" }, "original": { - "owner": "parsonsmatt", - "repo": "hspec-hedgehog", + "owner": "sevanspowell", + "repo": "hpc-coveralls", "type": "github" } }, @@ -5626,12 +5995,169 @@ "type": "indirect" } }, + "hydra_10": { + "inputs": { + "nix": "nix_10", + "nixpkgs": [ + "plutarch-safe-money", + "liqwid-plutarch-extra", + "plutarch-context-builder", + "plutarch", + "haskell-nix", + "hydra", + "nix", + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1646878427, + "narHash": "sha256-KtbrofMtN8GlM7D+n90kixr7QpSlVmdN+vK5CA/aRzc=", + "owner": "NixOS", + "repo": "hydra", + "rev": "28b682b85b7efc5cf7974065792a1f22203a5927", + "type": "github" + }, + "original": { + "id": "hydra", + "type": "indirect" + } + }, + "hydra_11": { + "inputs": { + "nix": "nix_11", + "nixpkgs": [ + "plutarch-safe-money", + "liqwid-plutarch-extra", + "plutarch-numeric", + "plutarch", + "haskell-nix", + "hydra", + "nix", + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1646878427, + "narHash": "sha256-KtbrofMtN8GlM7D+n90kixr7QpSlVmdN+vK5CA/aRzc=", + "owner": "NixOS", + "repo": "hydra", + "rev": "28b682b85b7efc5cf7974065792a1f22203a5927", + "type": "github" + }, + "original": { + "id": "hydra", + "type": "indirect" + } + }, + "hydra_12": { + "inputs": { + "nix": "nix_12", + "nixpkgs": [ + "plutarch-safe-money", + "liqwid-plutarch-extra", + "plutarch-quickcheck", + "plutarch", + "haskell-nix", + "hydra", + "nix", + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1646878427, + "narHash": "sha256-KtbrofMtN8GlM7D+n90kixr7QpSlVmdN+vK5CA/aRzc=", + "owner": "NixOS", + "repo": "hydra", + "rev": "28b682b85b7efc5cf7974065792a1f22203a5927", + "type": "github" + }, + "original": { + "id": "hydra", + "type": "indirect" + } + }, + "hydra_13": { + "inputs": { + "nix": "nix_13", + "nixpkgs": [ + "plutarch-safe-money", + "plutarch", + "haskell-nix", + "hydra", + "nix", + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1646878427, + "narHash": "sha256-KtbrofMtN8GlM7D+n90kixr7QpSlVmdN+vK5CA/aRzc=", + "owner": "NixOS", + "repo": "hydra", + "rev": "28b682b85b7efc5cf7974065792a1f22203a5927", + "type": "github" + }, + "original": { + "id": "hydra", + "type": "indirect" + } + }, + "hydra_14": { + "inputs": { + "nix": "nix_14", + "nixpkgs": [ + "plutarch-safe-money", + "plutarch-numeric", + "plutarch", + "haskell-nix", + "hydra", + "nix", + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1646878427, + "narHash": "sha256-KtbrofMtN8GlM7D+n90kixr7QpSlVmdN+vK5CA/aRzc=", + "owner": "NixOS", + "repo": "hydra", + "rev": "28b682b85b7efc5cf7974065792a1f22203a5927", + "type": "github" + }, + "original": { + "id": "hydra", + "type": "indirect" + } + }, + "hydra_15": { + "inputs": { + "nix": "nix_15", + "nixpkgs": [ + "plutarch-script-export", + "plutarch", + "haskell-nix", + "hydra", + "nix", + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1646878427, + "narHash": "sha256-KtbrofMtN8GlM7D+n90kixr7QpSlVmdN+vK5CA/aRzc=", + "owner": "NixOS", + "repo": "hydra", + "rev": "28b682b85b7efc5cf7974065792a1f22203a5927", + "type": "github" + }, + "original": { + "id": "hydra", + "type": "indirect" + } + }, "hydra_2": { "inputs": { "nix": "nix_2", "nixpkgs": [ "liqwid-plutarch-extra", - "plutarch-quickcheck", + "plutarch-context-builder", "plutarch", "haskell-nix", "hydra", @@ -5656,6 +6182,8 @@ "inputs": { "nix": "nix_3", "nixpkgs": [ + "liqwid-plutarch-extra", + "plutarch-numeric", "plutarch", "haskell-nix", "hydra", @@ -5680,7 +6208,8 @@ "inputs": { "nix": "nix_4", "nixpkgs": [ - "plutarch-context-builder", + "liqwid-plutarch-extra", + "plutarch-quickcheck", "plutarch", "haskell-nix", "hydra", @@ -5705,7 +6234,6 @@ "inputs": { "nix": "nix_5", "nixpkgs": [ - "plutarch-numeric", "plutarch", "haskell-nix", "hydra", @@ -5730,7 +6258,7 @@ "inputs": { "nix": "nix_6", "nixpkgs": [ - "plutarch-quickcheck", + "plutarch-context-builder", "plutarch", "haskell-nix", "hydra", @@ -5755,8 +6283,7 @@ "inputs": { "nix": "nix_7", "nixpkgs": [ - "plutarch-safe-money", - "liqwid-plutarch-extra", + "plutarch-numeric", "plutarch", "haskell-nix", "hydra", @@ -5781,8 +6308,6 @@ "inputs": { "nix": "nix_8", "nixpkgs": [ - "plutarch-safe-money", - "liqwid-plutarch-extra", "plutarch-quickcheck", "plutarch", "haskell-nix", @@ -5809,6 +6334,7 @@ "nix": "nix_9", "nixpkgs": [ "plutarch-safe-money", + "liqwid-plutarch-extra", "plutarch", "haskell-nix", "hydra", @@ -5992,11 +6518,11 @@ "iohk-nix_19": { "flake": false, "locked": { - "lastModified": 1643251385, - "narHash": "sha256-Czbd69lg0ARSZfC18V6h+gtPMioWDAEVPbiHgL2x9LM=", + "lastModified": 1653579289, + "narHash": "sha256-wveDdPsgB/3nAGAdFaxrcgLEpdi0aJ5kEVNtI+YqVfo=", "owner": "input-output-hk", "repo": "iohk-nix", - "rev": "9d6ee3dcb3482f791e40ed991ad6fc649b343ad4", + "rev": "edb2d2df2ebe42bbdf03a0711115cf6213c9d366", "type": "github" }, "original": { @@ -6037,7 +6563,7 @@ "type": "github" } }, - "iohk-nix_3": { + "iohk-nix_21": { "flake": false, "locked": { "lastModified": 1653579289, @@ -6053,7 +6579,7 @@ "type": "github" } }, - "iohk-nix_4": { + "iohk-nix_22": { "flake": false, "locked": { "lastModified": 1626953580, @@ -6069,7 +6595,7 @@ "type": "github" } }, - "iohk-nix_5": { + "iohk-nix_23": { "flake": false, "locked": { "lastModified": 1653579289, @@ -6085,7 +6611,7 @@ "type": "github" } }, - "iohk-nix_6": { + "iohk-nix_24": { "flake": false, "locked": { "lastModified": 1626953580, @@ -6101,7 +6627,7 @@ "type": "github" } }, - "iohk-nix_7": { + "iohk-nix_25": { "flake": false, "locked": { "lastModified": 1653579289, @@ -6117,7 +6643,7 @@ "type": "github" } }, - "iohk-nix_8": { + "iohk-nix_26": { "flake": false, "locked": { "lastModified": 1626953580, @@ -6133,7 +6659,7 @@ "type": "github" } }, - "iohk-nix_9": { + "iohk-nix_27": { "flake": false, "locked": { "lastModified": 1653579289, @@ -6149,185 +6675,462 @@ "type": "github" } }, - "ixset-typed": { + "iohk-nix_28": { "flake": false, "locked": { - "lastModified": 1652177108, - "narHash": "sha256-g0N1jiumsxHzfo9SGVR+q9awRvHEehSRaoW89LXCCnY=", - "owner": "well-typed", - "repo": "ixset-typed", - "rev": "244d3b72fd051b8d78f2d4edb6208269f29d85b7", + "lastModified": 1626953580, + "narHash": "sha256-iEI9aTOaZMGsjWzcrctrC0usmiagwKT2v1LSDe9/tMU=", + "owner": "input-output-hk", + "repo": "iohk-nix", + "rev": "cbd497f5844249ef8fe617166337d59f2a6ebe90", "type": "github" }, "original": { - "owner": "well-typed", - "repo": "ixset-typed", + "owner": "input-output-hk", + "repo": "iohk-nix", "type": "github" } }, - "ixset-typed_2": { + "iohk-nix_29": { "flake": false, "locked": { - "lastModified": 1652177108, - "narHash": "sha256-g0N1jiumsxHzfo9SGVR+q9awRvHEehSRaoW89LXCCnY=", - "owner": "well-typed", - "repo": "ixset-typed", - "rev": "244d3b72fd051b8d78f2d4edb6208269f29d85b7", + "lastModified": 1653579289, + "narHash": "sha256-wveDdPsgB/3nAGAdFaxrcgLEpdi0aJ5kEVNtI+YqVfo=", + "owner": "input-output-hk", + "repo": "iohk-nix", + "rev": "edb2d2df2ebe42bbdf03a0711115cf6213c9d366", "type": "github" }, "original": { - "owner": "well-typed", - "repo": "ixset-typed", + "owner": "input-output-hk", + "repo": "iohk-nix", "type": "github" } }, - "ixset-typed_3": { + "iohk-nix_3": { "flake": false, "locked": { - "lastModified": 1652177108, - "narHash": "sha256-g0N1jiumsxHzfo9SGVR+q9awRvHEehSRaoW89LXCCnY=", - "owner": "well-typed", - "repo": "ixset-typed", - "rev": "244d3b72fd051b8d78f2d4edb6208269f29d85b7", + "lastModified": 1653579289, + "narHash": "sha256-wveDdPsgB/3nAGAdFaxrcgLEpdi0aJ5kEVNtI+YqVfo=", + "owner": "input-output-hk", + "repo": "iohk-nix", + "rev": "edb2d2df2ebe42bbdf03a0711115cf6213c9d366", "type": "github" }, "original": { - "owner": "well-typed", - "repo": "ixset-typed", + "owner": "input-output-hk", + "repo": "iohk-nix", "type": "github" } }, - "ixset-typed_4": { + "iohk-nix_30": { "flake": false, "locked": { - "lastModified": 1652177108, - "narHash": "sha256-g0N1jiumsxHzfo9SGVR+q9awRvHEehSRaoW89LXCCnY=", - "owner": "well-typed", - "repo": "ixset-typed", - "rev": "244d3b72fd051b8d78f2d4edb6208269f29d85b7", + "lastModified": 1626953580, + "narHash": "sha256-iEI9aTOaZMGsjWzcrctrC0usmiagwKT2v1LSDe9/tMU=", + "owner": "input-output-hk", + "repo": "iohk-nix", + "rev": "cbd497f5844249ef8fe617166337d59f2a6ebe90", "type": "github" }, "original": { - "owner": "well-typed", - "repo": "ixset-typed", + "owner": "input-output-hk", + "repo": "iohk-nix", "type": "github" } }, - "ixset-typed_5": { + "iohk-nix_4": { "flake": false, "locked": { - "lastModified": 1652177108, - "narHash": "sha256-g0N1jiumsxHzfo9SGVR+q9awRvHEehSRaoW89LXCCnY=", - "owner": "well-typed", - "repo": "ixset-typed", - "rev": "244d3b72fd051b8d78f2d4edb6208269f29d85b7", + "lastModified": 1626953580, + "narHash": "sha256-iEI9aTOaZMGsjWzcrctrC0usmiagwKT2v1LSDe9/tMU=", + "owner": "input-output-hk", + "repo": "iohk-nix", + "rev": "cbd497f5844249ef8fe617166337d59f2a6ebe90", "type": "github" }, "original": { - "owner": "well-typed", - "repo": "ixset-typed", + "owner": "input-output-hk", + "repo": "iohk-nix", "type": "github" } }, - "ixset-typed_6": { + "iohk-nix_5": { "flake": false, "locked": { - "lastModified": 1652177108, - "narHash": "sha256-g0N1jiumsxHzfo9SGVR+q9awRvHEehSRaoW89LXCCnY=", - "owner": "well-typed", - "repo": "ixset-typed", - "rev": "244d3b72fd051b8d78f2d4edb6208269f29d85b7", + "lastModified": 1653579289, + "narHash": "sha256-wveDdPsgB/3nAGAdFaxrcgLEpdi0aJ5kEVNtI+YqVfo=", + "owner": "input-output-hk", + "repo": "iohk-nix", + "rev": "edb2d2df2ebe42bbdf03a0711115cf6213c9d366", "type": "github" }, "original": { - "owner": "well-typed", - "repo": "ixset-typed", + "owner": "input-output-hk", + "repo": "iohk-nix", "type": "github" } }, - "ixset-typed_7": { + "iohk-nix_6": { "flake": false, "locked": { - "lastModified": 1652177108, - "narHash": "sha256-g0N1jiumsxHzfo9SGVR+q9awRvHEehSRaoW89LXCCnY=", - "owner": "well-typed", - "repo": "ixset-typed", - "rev": "244d3b72fd051b8d78f2d4edb6208269f29d85b7", + "lastModified": 1626953580, + "narHash": "sha256-iEI9aTOaZMGsjWzcrctrC0usmiagwKT2v1LSDe9/tMU=", + "owner": "input-output-hk", + "repo": "iohk-nix", + "rev": "cbd497f5844249ef8fe617166337d59f2a6ebe90", "type": "github" }, "original": { - "owner": "well-typed", - "repo": "ixset-typed", + "owner": "input-output-hk", + "repo": "iohk-nix", "type": "github" } }, - "ixset-typed_8": { + "iohk-nix_7": { "flake": false, "locked": { - "lastModified": 1652177108, - "narHash": "sha256-g0N1jiumsxHzfo9SGVR+q9awRvHEehSRaoW89LXCCnY=", - "owner": "well-typed", - "repo": "ixset-typed", - "rev": "244d3b72fd051b8d78f2d4edb6208269f29d85b7", + "lastModified": 1653579289, + "narHash": "sha256-wveDdPsgB/3nAGAdFaxrcgLEpdi0aJ5kEVNtI+YqVfo=", + "owner": "input-output-hk", + "repo": "iohk-nix", + "rev": "edb2d2df2ebe42bbdf03a0711115cf6213c9d366", "type": "github" }, "original": { - "owner": "well-typed", - "repo": "ixset-typed", + "owner": "input-output-hk", + "repo": "iohk-nix", "type": "github" } }, - "ixset-typed_9": { + "iohk-nix_8": { "flake": false, "locked": { - "lastModified": 1639657838, - "narHash": "sha256-pI2dzJfkR10CHDEX6TV2E01pqcGkj7kheROw05MRTR8=", - "owner": "well-typed", - "repo": "ixset-typed", - "rev": "6cf16f77ae173311742623e5f0b308a21b337aa7", - "type": "github" + "lastModified": 1626953580, + "narHash": "sha256-iEI9aTOaZMGsjWzcrctrC0usmiagwKT2v1LSDe9/tMU=", + "owner": "input-output-hk", + "repo": "iohk-nix", + "rev": "cbd497f5844249ef8fe617166337d59f2a6ebe90", + "type": "github" + }, + "original": { + "owner": "input-output-hk", + "repo": "iohk-nix", + "type": "github" + } + }, + "iohk-nix_9": { + "flake": false, + "locked": { + "lastModified": 1653579289, + "narHash": "sha256-wveDdPsgB/3nAGAdFaxrcgLEpdi0aJ5kEVNtI+YqVfo=", + "owner": "input-output-hk", + "repo": "iohk-nix", + "rev": "edb2d2df2ebe42bbdf03a0711115cf6213c9d366", + "type": "github" }, "original": { - "owner": "well-typed", - "repo": "ixset-typed", + "owner": "input-output-hk", + "repo": "iohk-nix", "type": "github" } }, - "lint-utils": { + "liqwid-nix": { "inputs": { - "flake-utils": "flake-utils_27", - "nixpkgs": [ - "plutarch-safe-money", - "plutarch-numeric", - "plutarch", - "emanote", - "ema", - "nixpkgs" - ] + "nixpkgs": "nixpkgs", + "nixpkgs-2205": "nixpkgs-2205" + }, + "locked": { + "lastModified": 1660251224, + "narHash": "sha256-spBrASFpblmQFYuS4GHv9hI3cLRzh6OG5tNikRmUUZA=", + "owner": "Liqwid-Labs", + "repo": "liqwid-nix", + "rev": "6bf26da0cbd1dea4ea275ffb5d05214a7d3e61be", + "type": "github" + }, + "original": { + "owner": "Liqwid-Labs", + "ref": "main", + "repo": "liqwid-nix", + "type": "github" + } + }, + "liqwid-nix_10": { + "inputs": { + "nixpkgs": "nixpkgs_34" + }, + "locked": { + "lastModified": 1659383708, + "narHash": "sha256-eenTO5t4ocK7VzorMUdUyKUoup976cCu5dJcVjebY8E=", + "owner": "Liqwid-Labs", + "repo": "liqwid-nix", + "rev": "c261df76dc31b3dc5dfde7030420e0a6be73f615", + "type": "github" + }, + "original": { + "owner": "Liqwid-Labs", + "repo": "liqwid-nix", + "type": "github" + } + }, + "liqwid-nix_11": { + "inputs": { + "nixpkgs": "nixpkgs_38" + }, + "locked": { + "lastModified": 1659383708, + "narHash": "sha256-eenTO5t4ocK7VzorMUdUyKUoup976cCu5dJcVjebY8E=", + "owner": "Liqwid-Labs", + "repo": "liqwid-nix", + "rev": "c261df76dc31b3dc5dfde7030420e0a6be73f615", + "type": "github" + }, + "original": { + "owner": "Liqwid-Labs", + "repo": "liqwid-nix", + "type": "github" + } + }, + "liqwid-nix_12": { + "inputs": { + "nixpkgs": "nixpkgs_42" + }, + "locked": { + "lastModified": 1659383708, + "narHash": "sha256-eenTO5t4ocK7VzorMUdUyKUoup976cCu5dJcVjebY8E=", + "owner": "Liqwid-Labs", + "repo": "liqwid-nix", + "rev": "c261df76dc31b3dc5dfde7030420e0a6be73f615", + "type": "github" + }, + "original": { + "owner": "Liqwid-Labs", + "repo": "liqwid-nix", + "type": "github" + } + }, + "liqwid-nix_13": { + "inputs": { + "nixpkgs": "nixpkgs_46" + }, + "locked": { + "lastModified": 1659383708, + "narHash": "sha256-eenTO5t4ocK7VzorMUdUyKUoup976cCu5dJcVjebY8E=", + "owner": "Liqwid-Labs", + "repo": "liqwid-nix", + "rev": "c261df76dc31b3dc5dfde7030420e0a6be73f615", + "type": "github" + }, + "original": { + "owner": "Liqwid-Labs", + "repo": "liqwid-nix", + "type": "github" + } + }, + "liqwid-nix_14": { + "inputs": { + "nixpkgs": "nixpkgs_53" + }, + "locked": { + "lastModified": 1659383708, + "narHash": "sha256-eenTO5t4ocK7VzorMUdUyKUoup976cCu5dJcVjebY8E=", + "owner": "Liqwid-Labs", + "repo": "liqwid-nix", + "rev": "c261df76dc31b3dc5dfde7030420e0a6be73f615", + "type": "github" + }, + "original": { + "owner": "Liqwid-Labs", + "repo": "liqwid-nix", + "type": "github" + } + }, + "liqwid-nix_15": { + "inputs": { + "nixpkgs": "nixpkgs_57", + "nixpkgs-2205": "nixpkgs-2205_2" + }, + "locked": { + "lastModified": 1660165784, + "narHash": "sha256-uSwB6jmiP0giQM9NwCkXloabfRnbDSsd1EAKXbTQpq4=", + "owner": "Liqwid-Labs", + "repo": "liqwid-nix", + "rev": "07d35ade0f9a1bab07413d059ccec63982592552", + "type": "github" + }, + "original": { + "owner": "Liqwid-Labs", + "repo": "liqwid-nix", + "type": "github" + } + }, + "liqwid-nix_2": { + "inputs": { + "nixpkgs": "nixpkgs_2" + }, + "locked": { + "lastModified": 1659383708, + "narHash": "sha256-eenTO5t4ocK7VzorMUdUyKUoup976cCu5dJcVjebY8E=", + "owner": "Liqwid-Labs", + "repo": "liqwid-nix", + "rev": "c261df76dc31b3dc5dfde7030420e0a6be73f615", + "type": "github" + }, + "original": { + "owner": "Liqwid-Labs", + "repo": "liqwid-nix", + "type": "github" + } + }, + "liqwid-nix_3": { + "inputs": { + "nixpkgs": "nixpkgs_6" + }, + "locked": { + "lastModified": 1659383708, + "narHash": "sha256-eenTO5t4ocK7VzorMUdUyKUoup976cCu5dJcVjebY8E=", + "owner": "Liqwid-Labs", + "repo": "liqwid-nix", + "rev": "c261df76dc31b3dc5dfde7030420e0a6be73f615", + "type": "github" + }, + "original": { + "owner": "Liqwid-Labs", + "repo": "liqwid-nix", + "type": "github" + } + }, + "liqwid-nix_4": { + "inputs": { + "nixpkgs": "nixpkgs_10" + }, + "locked": { + "lastModified": 1659383708, + "narHash": "sha256-eenTO5t4ocK7VzorMUdUyKUoup976cCu5dJcVjebY8E=", + "owner": "Liqwid-Labs", + "repo": "liqwid-nix", + "rev": "c261df76dc31b3dc5dfde7030420e0a6be73f615", + "type": "github" + }, + "original": { + "owner": "Liqwid-Labs", + "repo": "liqwid-nix", + "type": "github" + } + }, + "liqwid-nix_5": { + "inputs": { + "nixpkgs": "nixpkgs_14" + }, + "locked": { + "lastModified": 1659383708, + "narHash": "sha256-eenTO5t4ocK7VzorMUdUyKUoup976cCu5dJcVjebY8E=", + "owner": "Liqwid-Labs", + "repo": "liqwid-nix", + "rev": "c261df76dc31b3dc5dfde7030420e0a6be73f615", + "type": "github" + }, + "original": { + "owner": "Liqwid-Labs", + "repo": "liqwid-nix", + "type": "github" + } + }, + "liqwid-nix_6": { + "inputs": { + "nixpkgs": "nixpkgs_21" + }, + "locked": { + "lastModified": 1659383708, + "narHash": "sha256-eenTO5t4ocK7VzorMUdUyKUoup976cCu5dJcVjebY8E=", + "owner": "Liqwid-Labs", + "repo": "liqwid-nix", + "rev": "c261df76dc31b3dc5dfde7030420e0a6be73f615", + "type": "github" + }, + "original": { + "owner": "Liqwid-Labs", + "repo": "liqwid-nix", + "type": "github" + } + }, + "liqwid-nix_7": { + "inputs": { + "nixpkgs": "nixpkgs_25" + }, + "locked": { + "lastModified": 1659383708, + "narHash": "sha256-eenTO5t4ocK7VzorMUdUyKUoup976cCu5dJcVjebY8E=", + "owner": "Liqwid-Labs", + "repo": "liqwid-nix", + "rev": "c261df76dc31b3dc5dfde7030420e0a6be73f615", + "type": "github" + }, + "original": { + "owner": "Liqwid-Labs", + "repo": "liqwid-nix", + "type": "github" + } + }, + "liqwid-nix_8": { + "inputs": { + "nixpkgs": "nixpkgs_29" + }, + "locked": { + "lastModified": 1659383708, + "narHash": "sha256-eenTO5t4ocK7VzorMUdUyKUoup976cCu5dJcVjebY8E=", + "owner": "Liqwid-Labs", + "repo": "liqwid-nix", + "rev": "c261df76dc31b3dc5dfde7030420e0a6be73f615", + "type": "github" + }, + "original": { + "owner": "Liqwid-Labs", + "repo": "liqwid-nix", + "type": "github" + } + }, + "liqwid-nix_9": { + "inputs": { + "nixpkgs": "nixpkgs_33" }, "locked": { - "lastModified": 1650427214, - "narHash": "sha256-9m66rRSSM614ocRXNPAArwnrS6zzCQYYhd3nw8g4QUg=", - "ref": "overengineered", - "rev": "5555def5a25c5437834c06cbe79b3945916ec59f", - "revCount": 28, - "type": "git", - "url": "https://gitlab.homotopic.tech/nix/lint-utils.git" + "lastModified": 1659383708, + "narHash": "sha256-eenTO5t4ocK7VzorMUdUyKUoup976cCu5dJcVjebY8E=", + "owner": "Liqwid-Labs", + "repo": "liqwid-nix", + "rev": "c261df76dc31b3dc5dfde7030420e0a6be73f615", + "type": "github" }, "original": { - "ref": "overengineered", - "type": "git", - "url": "https://gitlab.homotopic.tech/nix/lint-utils.git" + "owner": "Liqwid-Labs", + "repo": "liqwid-nix", + "type": "github" } }, "liqwid-plutarch-extra": { "inputs": { - "haskell-language-server": "haskell-language-server", + "haskell-language-server": [ + "liqwid-plutarch-extra", + "plutarch", + "haskell-language-server" + ], "haskell-nix": [ "liqwid-plutarch-extra", "plutarch", "haskell-nix" ], + "haskell-nix-extra-hackage": [ + "liqwid-plutarch-extra", + "plutarch", + "haskell-nix-extra-hackage" + ], + "iohk-nix": [ + "liqwid-plutarch-extra", + "plutarch", + "iohk-nix" + ], + "liqwid-nix": "liqwid-nix_2", "nixpkgs": [ "liqwid-plutarch-extra", "plutarch", @@ -6336,49 +7139,71 @@ "nixpkgs-2111": "nixpkgs-2111", "nixpkgs-latest": "nixpkgs-latest", "plutarch": "plutarch", + "plutarch-context-builder": "plutarch-context-builder", + "plutarch-numeric": "plutarch-numeric", "plutarch-quickcheck": "plutarch-quickcheck" }, "locked": { - "lastModified": 1655824848, - "narHash": "sha256-ZpQ/d+wIO18uE+h6cysPHNpog1f7Qlfy6ul1FSnm2Ek=", + "lastModified": 1660162748, + "narHash": "sha256-TvDWZ3mbfQCKHgNDjRR2Ydjx9cgw48hDpN0t/wy7oCI=", "owner": "Liqwid-Labs", "repo": "liqwid-plutarch-extra", - "rev": "620072d639afd91c84e7347b35df4dfe247546a4", + "rev": "d8be5f8dc91ad00158727fdbccb6db849e9f3559", "type": "github" }, "original": { "owner": "Liqwid-Labs", - "ref": "main", + "ref": "plutus-v1", "repo": "liqwid-plutarch-extra", "type": "github" } }, "liqwid-plutarch-extra_2": { "inputs": { - "haskell-language-server": "haskell-language-server_19", + "haskell-language-server": [ + "plutarch-safe-money", + "liqwid-plutarch-extra", + "plutarch", + "haskell-language-server" + ], "haskell-nix": [ "plutarch-safe-money", "liqwid-plutarch-extra", "plutarch", "haskell-nix" ], + "haskell-nix-extra-hackage": [ + "plutarch-safe-money", + "liqwid-plutarch-extra", + "plutarch", + "haskell-nix-extra-hackage" + ], + "iohk-nix": [ + "plutarch-safe-money", + "liqwid-plutarch-extra", + "plutarch", + "iohk-nix" + ], + "liqwid-nix": "liqwid-nix_10", "nixpkgs": [ "plutarch-safe-money", "liqwid-plutarch-extra", "plutarch", "nixpkgs" ], - "nixpkgs-2111": "nixpkgs-2111_13", - "nixpkgs-latest": "nixpkgs-latest_13", - "plutarch": "plutarch_7", + "nixpkgs-2111": "nixpkgs-2111_17", + "nixpkgs-latest": "nixpkgs-latest_17", + "plutarch": "plutarch_9", + "plutarch-context-builder": "plutarch-context-builder_3", + "plutarch-numeric": "plutarch-numeric_3", "plutarch-quickcheck": "plutarch-quickcheck_3" }, "locked": { - "lastModified": 1655470312, - "narHash": "sha256-O4Dy803SFOS+S1OFEecfCRkjWc8y0iHbO+EVKtBqsGk=", + "lastModified": 1659473759, + "narHash": "sha256-hHGEaISfdUyrQEh5OeBD4IEn0xwCdR1vfk3c+yfxeaw=", "owner": "Liqwid-Labs", "repo": "liqwid-plutarch-extra", - "rev": "fd9b2e6e713c36efef30bcef8d97a069fda7d71a", + "rev": "6ddf927299f8f1681092253f0297df549b8a74b6", "type": "github" }, "original": { @@ -6404,7 +7229,7 @@ "type": "github" } }, - "lowdown-src_2": { + "lowdown-src_10": { "flake": false, "locked": { "lastModified": 1633514407, @@ -6420,7 +7245,7 @@ "type": "github" } }, - "lowdown-src_3": { + "lowdown-src_11": { "flake": false, "locked": { "lastModified": 1633514407, @@ -6436,7 +7261,7 @@ "type": "github" } }, - "lowdown-src_4": { + "lowdown-src_12": { "flake": false, "locked": { "lastModified": 1633514407, @@ -6452,7 +7277,7 @@ "type": "github" } }, - "lowdown-src_5": { + "lowdown-src_13": { "flake": false, "locked": { "lastModified": 1633514407, @@ -6468,7 +7293,7 @@ "type": "github" } }, - "lowdown-src_6": { + "lowdown-src_14": { "flake": false, "locked": { "lastModified": 1633514407, @@ -6484,7 +7309,7 @@ "type": "github" } }, - "lowdown-src_7": { + "lowdown-src_15": { "flake": false, "locked": { "lastModified": 1633514407, @@ -6500,7 +7325,7 @@ "type": "github" } }, - "lowdown-src_8": { + "lowdown-src_2": { "flake": false, "locked": { "lastModified": 1633514407, @@ -6516,7 +7341,7 @@ "type": "github" } }, - "lowdown-src_9": { + "lowdown-src_3": { "flake": false, "locked": { "lastModified": 1633514407, @@ -6532,18 +7357,114 @@ "type": "github" } }, - "nix": { - "inputs": { - "lowdown-src": "lowdown-src", - "nixpkgs": "nixpkgs_3", - "nixpkgs-regression": "nixpkgs-regression" - }, + "lowdown-src_4": { + "flake": false, "locked": { - "lastModified": 1643066034, - "narHash": "sha256-xEPeMcNJVOeZtoN+d+aRwolpW8mFSEQx76HTRdlhPhg=", - "owner": "NixOS", - "repo": "nix", - "rev": "a1cd7e58606a41fcf62bf8637804cf8306f17f62", + "lastModified": 1633514407, + "narHash": "sha256-Dw32tiMjdK9t3ETl5fzGrutQTzh2rufgZV4A/BbxuD4=", + "owner": "kristapsdz", + "repo": "lowdown", + "rev": "d2c2b44ff6c27b936ec27358a2653caaef8f73b8", + "type": "github" + }, + "original": { + "owner": "kristapsdz", + "repo": "lowdown", + "type": "github" + } + }, + "lowdown-src_5": { + "flake": false, + "locked": { + "lastModified": 1633514407, + "narHash": "sha256-Dw32tiMjdK9t3ETl5fzGrutQTzh2rufgZV4A/BbxuD4=", + "owner": "kristapsdz", + "repo": "lowdown", + "rev": "d2c2b44ff6c27b936ec27358a2653caaef8f73b8", + "type": "github" + }, + "original": { + "owner": "kristapsdz", + "repo": "lowdown", + "type": "github" + } + }, + "lowdown-src_6": { + "flake": false, + "locked": { + "lastModified": 1633514407, + "narHash": "sha256-Dw32tiMjdK9t3ETl5fzGrutQTzh2rufgZV4A/BbxuD4=", + "owner": "kristapsdz", + "repo": "lowdown", + "rev": "d2c2b44ff6c27b936ec27358a2653caaef8f73b8", + "type": "github" + }, + "original": { + "owner": "kristapsdz", + "repo": "lowdown", + "type": "github" + } + }, + "lowdown-src_7": { + "flake": false, + "locked": { + "lastModified": 1633514407, + "narHash": "sha256-Dw32tiMjdK9t3ETl5fzGrutQTzh2rufgZV4A/BbxuD4=", + "owner": "kristapsdz", + "repo": "lowdown", + "rev": "d2c2b44ff6c27b936ec27358a2653caaef8f73b8", + "type": "github" + }, + "original": { + "owner": "kristapsdz", + "repo": "lowdown", + "type": "github" + } + }, + "lowdown-src_8": { + "flake": false, + "locked": { + "lastModified": 1633514407, + "narHash": "sha256-Dw32tiMjdK9t3ETl5fzGrutQTzh2rufgZV4A/BbxuD4=", + "owner": "kristapsdz", + "repo": "lowdown", + "rev": "d2c2b44ff6c27b936ec27358a2653caaef8f73b8", + "type": "github" + }, + "original": { + "owner": "kristapsdz", + "repo": "lowdown", + "type": "github" + } + }, + "lowdown-src_9": { + "flake": false, + "locked": { + "lastModified": 1633514407, + "narHash": "sha256-Dw32tiMjdK9t3ETl5fzGrutQTzh2rufgZV4A/BbxuD4=", + "owner": "kristapsdz", + "repo": "lowdown", + "rev": "d2c2b44ff6c27b936ec27358a2653caaef8f73b8", + "type": "github" + }, + "original": { + "owner": "kristapsdz", + "repo": "lowdown", + "type": "github" + } + }, + "nix": { + "inputs": { + "lowdown-src": "lowdown-src", + "nixpkgs": "nixpkgs_3", + "nixpkgs-regression": "nixpkgs-regression" + }, + "locked": { + "lastModified": 1643066034, + "narHash": "sha256-xEPeMcNJVOeZtoN+d+aRwolpW8mFSEQx76HTRdlhPhg=", + "owner": "NixOS", + "repo": "nix", + "rev": "a1cd7e58606a41fcf62bf8637804cf8306f17f62", "type": "github" }, "original": { @@ -6572,11 +7493,91 @@ "nix-tools_10": { "flake": false, "locked": { - "lastModified": 1644395812, - "narHash": "sha256-BVFk/BEsTLq5MMZvdy3ZYHKfaS3dHrsKh4+tb5t5b58=", + "lastModified": 1649424170, + "narHash": "sha256-XgKXWispvv5RCvZzPb+p7e6Hy3LMuRjafKMl7kXzxGw=", + "owner": "input-output-hk", + "repo": "nix-tools", + "rev": "e109c94016e3b6e0db7ed413c793e2d4bdb24aa7", + "type": "github" + }, + "original": { + "owner": "input-output-hk", + "repo": "nix-tools", + "type": "github" + } + }, + "nix-tools_11": { + "flake": false, + "locked": { + "lastModified": 1649424170, + "narHash": "sha256-XgKXWispvv5RCvZzPb+p7e6Hy3LMuRjafKMl7kXzxGw=", + "owner": "input-output-hk", + "repo": "nix-tools", + "rev": "e109c94016e3b6e0db7ed413c793e2d4bdb24aa7", + "type": "github" + }, + "original": { + "owner": "input-output-hk", + "repo": "nix-tools", + "type": "github" + } + }, + "nix-tools_12": { + "flake": false, + "locked": { + "lastModified": 1649424170, + "narHash": "sha256-XgKXWispvv5RCvZzPb+p7e6Hy3LMuRjafKMl7kXzxGw=", + "owner": "input-output-hk", + "repo": "nix-tools", + "rev": "e109c94016e3b6e0db7ed413c793e2d4bdb24aa7", + "type": "github" + }, + "original": { + "owner": "input-output-hk", + "repo": "nix-tools", + "type": "github" + } + }, + "nix-tools_13": { + "flake": false, + "locked": { + "lastModified": 1649424170, + "narHash": "sha256-XgKXWispvv5RCvZzPb+p7e6Hy3LMuRjafKMl7kXzxGw=", + "owner": "input-output-hk", + "repo": "nix-tools", + "rev": "e109c94016e3b6e0db7ed413c793e2d4bdb24aa7", + "type": "github" + }, + "original": { + "owner": "input-output-hk", + "repo": "nix-tools", + "type": "github" + } + }, + "nix-tools_14": { + "flake": false, + "locked": { + "lastModified": 1649424170, + "narHash": "sha256-XgKXWispvv5RCvZzPb+p7e6Hy3LMuRjafKMl7kXzxGw=", + "owner": "input-output-hk", + "repo": "nix-tools", + "rev": "e109c94016e3b6e0db7ed413c793e2d4bdb24aa7", + "type": "github" + }, + "original": { + "owner": "input-output-hk", + "repo": "nix-tools", + "type": "github" + } + }, + "nix-tools_15": { + "flake": false, + "locked": { + "lastModified": 1649424170, + "narHash": "sha256-XgKXWispvv5RCvZzPb+p7e6Hy3LMuRjafKMl7kXzxGw=", "owner": "input-output-hk", "repo": "nix-tools", - "rev": "d847c63b99bbec78bf83be2a61dc9f09b8a9ccc1", + "rev": "e109c94016e3b6e0db7ed413c793e2d4bdb24aa7", "type": "github" }, "original": { @@ -6713,11 +7714,11 @@ "type": "github" } }, - "nix_2": { + "nix_10": { "inputs": { - "lowdown-src": "lowdown-src_2", - "nixpkgs": "nixpkgs_8", - "nixpkgs-regression": "nixpkgs-regression_2" + "lowdown-src": "lowdown-src_10", + "nixpkgs": "nixpkgs_39", + "nixpkgs-regression": "nixpkgs-regression_10" }, "locked": { "lastModified": 1643066034, @@ -6734,11 +7735,11 @@ "type": "github" } }, - "nix_3": { + "nix_11": { "inputs": { - "lowdown-src": "lowdown-src_3", - "nixpkgs": "nixpkgs_11", - "nixpkgs-regression": "nixpkgs-regression_3" + "lowdown-src": "lowdown-src_11", + "nixpkgs": "nixpkgs_43", + "nixpkgs-regression": "nixpkgs-regression_11" }, "locked": { "lastModified": 1643066034, @@ -6755,11 +7756,11 @@ "type": "github" } }, - "nix_4": { + "nix_12": { "inputs": { - "lowdown-src": "lowdown-src_4", - "nixpkgs": "nixpkgs_16", - "nixpkgs-regression": "nixpkgs-regression_4" + "lowdown-src": "lowdown-src_12", + "nixpkgs": "nixpkgs_47", + "nixpkgs-regression": "nixpkgs-regression_12" }, "locked": { "lastModified": 1643066034, @@ -6776,11 +7777,11 @@ "type": "github" } }, - "nix_5": { + "nix_13": { "inputs": { - "lowdown-src": "lowdown-src_5", - "nixpkgs": "nixpkgs_21", - "nixpkgs-regression": "nixpkgs-regression_5" + "lowdown-src": "lowdown-src_13", + "nixpkgs": "nixpkgs_50", + "nixpkgs-regression": "nixpkgs-regression_13" }, "locked": { "lastModified": 1643066034, @@ -6797,11 +7798,11 @@ "type": "github" } }, - "nix_6": { + "nix_14": { "inputs": { - "lowdown-src": "lowdown-src_6", - "nixpkgs": "nixpkgs_26", - "nixpkgs-regression": "nixpkgs-regression_6" + "lowdown-src": "lowdown-src_14", + "nixpkgs": "nixpkgs_54", + "nixpkgs-regression": "nixpkgs-regression_14" }, "locked": { "lastModified": 1643066034, @@ -6818,11 +7819,11 @@ "type": "github" } }, - "nix_7": { + "nix_15": { "inputs": { - "lowdown-src": "lowdown-src_7", - "nixpkgs": "nixpkgs_31", - "nixpkgs-regression": "nixpkgs-regression_7" + "lowdown-src": "lowdown-src_15", + "nixpkgs": "nixpkgs_58", + "nixpkgs-regression": "nixpkgs-regression_15" }, "locked": { "lastModified": 1643066034, @@ -6839,11 +7840,11 @@ "type": "github" } }, - "nix_8": { + "nix_2": { "inputs": { - "lowdown-src": "lowdown-src_8", - "nixpkgs": "nixpkgs_36", - "nixpkgs-regression": "nixpkgs-regression_8" + "lowdown-src": "lowdown-src_2", + "nixpkgs": "nixpkgs_7", + "nixpkgs-regression": "nixpkgs-regression_2" }, "locked": { "lastModified": 1643066034, @@ -6860,11 +7861,11 @@ "type": "github" } }, - "nix_9": { + "nix_3": { "inputs": { - "lowdown-src": "lowdown-src_9", - "nixpkgs": "nixpkgs_41", - "nixpkgs-regression": "nixpkgs-regression_9" + "lowdown-src": "lowdown-src_3", + "nixpkgs": "nixpkgs_11", + "nixpkgs-regression": "nixpkgs-regression_3" }, "locked": { "lastModified": 1643066034, @@ -6881,41 +7882,245 @@ "type": "github" } }, - "nixpkgs": { + "nix_4": { + "inputs": { + "lowdown-src": "lowdown-src_4", + "nixpkgs": "nixpkgs_15", + "nixpkgs-regression": "nixpkgs-regression_4" + }, "locked": { - "lastModified": 1652885393, - "narHash": "sha256-YIgvvlk4iQ1Hi7KD9o5gsojc+ApB+jiH1d5stK8uXiw=", - "owner": "nixos", - "repo": "nixpkgs", - "rev": "48037fd90426e44e4bf03e6479e88a11453b9b66", + "lastModified": 1643066034, + "narHash": "sha256-xEPeMcNJVOeZtoN+d+aRwolpW8mFSEQx76HTRdlhPhg=", + "owner": "NixOS", + "repo": "nix", + "rev": "a1cd7e58606a41fcf62bf8637804cf8306f17f62", "type": "github" }, "original": { - "owner": "nixos", - "ref": "nixos-unstable", - "repo": "nixpkgs", + "owner": "NixOS", + "ref": "2.6.0", + "repo": "nix", "type": "github" } }, - "nixpkgs-2003": { + "nix_5": { + "inputs": { + "lowdown-src": "lowdown-src_5", + "nixpkgs": "nixpkgs_18", + "nixpkgs-regression": "nixpkgs-regression_5" + }, "locked": { - "lastModified": 1620055814, - "narHash": "sha256-8LEHoYSJiL901bTMVatq+rf8y7QtWuZhwwpKE2fyaRY=", + "lastModified": 1643066034, + "narHash": "sha256-xEPeMcNJVOeZtoN+d+aRwolpW8mFSEQx76HTRdlhPhg=", "owner": "NixOS", - "repo": "nixpkgs", - "rev": "1db42b7fe3878f3f5f7a4f2dc210772fd080e205", + "repo": "nix", + "rev": "a1cd7e58606a41fcf62bf8637804cf8306f17f62", "type": "github" }, "original": { "owner": "NixOS", - "ref": "nixpkgs-20.03-darwin", - "repo": "nixpkgs", + "ref": "2.6.0", + "repo": "nix", "type": "github" } }, - "nixpkgs-2003_10": { + "nix_6": { + "inputs": { + "lowdown-src": "lowdown-src_6", + "nixpkgs": "nixpkgs_22", + "nixpkgs-regression": "nixpkgs-regression_6" + }, "locked": { - "lastModified": 1620055814, + "lastModified": 1643066034, + "narHash": "sha256-xEPeMcNJVOeZtoN+d+aRwolpW8mFSEQx76HTRdlhPhg=", + "owner": "NixOS", + "repo": "nix", + "rev": "a1cd7e58606a41fcf62bf8637804cf8306f17f62", + "type": "github" + }, + "original": { + "owner": "NixOS", + "ref": "2.6.0", + "repo": "nix", + "type": "github" + } + }, + "nix_7": { + "inputs": { + "lowdown-src": "lowdown-src_7", + "nixpkgs": "nixpkgs_26", + "nixpkgs-regression": "nixpkgs-regression_7" + }, + "locked": { + "lastModified": 1643066034, + "narHash": "sha256-xEPeMcNJVOeZtoN+d+aRwolpW8mFSEQx76HTRdlhPhg=", + "owner": "NixOS", + "repo": "nix", + "rev": "a1cd7e58606a41fcf62bf8637804cf8306f17f62", + "type": "github" + }, + "original": { + "owner": "NixOS", + "ref": "2.6.0", + "repo": "nix", + "type": "github" + } + }, + "nix_8": { + "inputs": { + "lowdown-src": "lowdown-src_8", + "nixpkgs": "nixpkgs_30", + "nixpkgs-regression": "nixpkgs-regression_8" + }, + "locked": { + "lastModified": 1643066034, + "narHash": "sha256-xEPeMcNJVOeZtoN+d+aRwolpW8mFSEQx76HTRdlhPhg=", + "owner": "NixOS", + "repo": "nix", + "rev": "a1cd7e58606a41fcf62bf8637804cf8306f17f62", + "type": "github" + }, + "original": { + "owner": "NixOS", + "ref": "2.6.0", + "repo": "nix", + "type": "github" + } + }, + "nix_9": { + "inputs": { + "lowdown-src": "lowdown-src_9", + "nixpkgs": "nixpkgs_35", + "nixpkgs-regression": "nixpkgs-regression_9" + }, + "locked": { + "lastModified": 1643066034, + "narHash": "sha256-xEPeMcNJVOeZtoN+d+aRwolpW8mFSEQx76HTRdlhPhg=", + "owner": "NixOS", + "repo": "nix", + "rev": "a1cd7e58606a41fcf62bf8637804cf8306f17f62", + "type": "github" + }, + "original": { + "owner": "NixOS", + "ref": "2.6.0", + "repo": "nix", + "type": "github" + } + }, + "nixpkgs": { + "locked": { + "lastModified": 1657292830, + "narHash": "sha256-ldfVSTveWceDCmW6gf3B4kR6vwmz/XS80y5wsLLHFJU=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "334ec8b503c3981e37a04b817a70e8d026ea9e84", + "type": "github" + }, + "original": { + "id": "nixpkgs", + "type": "indirect" + } + }, + "nixpkgs-2003": { + "locked": { + "lastModified": 1620055814, + "narHash": "sha256-8LEHoYSJiL901bTMVatq+rf8y7QtWuZhwwpKE2fyaRY=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "1db42b7fe3878f3f5f7a4f2dc210772fd080e205", + "type": "github" + }, + "original": { + "owner": "NixOS", + "ref": "nixpkgs-20.03-darwin", + "repo": "nixpkgs", + "type": "github" + } + }, + "nixpkgs-2003_10": { + "locked": { + "lastModified": 1620055814, + "narHash": "sha256-8LEHoYSJiL901bTMVatq+rf8y7QtWuZhwwpKE2fyaRY=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "1db42b7fe3878f3f5f7a4f2dc210772fd080e205", + "type": "github" + }, + "original": { + "owner": "NixOS", + "ref": "nixpkgs-20.03-darwin", + "repo": "nixpkgs", + "type": "github" + } + }, + "nixpkgs-2003_11": { + "locked": { + "lastModified": 1620055814, + "narHash": "sha256-8LEHoYSJiL901bTMVatq+rf8y7QtWuZhwwpKE2fyaRY=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "1db42b7fe3878f3f5f7a4f2dc210772fd080e205", + "type": "github" + }, + "original": { + "owner": "NixOS", + "ref": "nixpkgs-20.03-darwin", + "repo": "nixpkgs", + "type": "github" + } + }, + "nixpkgs-2003_12": { + "locked": { + "lastModified": 1620055814, + "narHash": "sha256-8LEHoYSJiL901bTMVatq+rf8y7QtWuZhwwpKE2fyaRY=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "1db42b7fe3878f3f5f7a4f2dc210772fd080e205", + "type": "github" + }, + "original": { + "owner": "NixOS", + "ref": "nixpkgs-20.03-darwin", + "repo": "nixpkgs", + "type": "github" + } + }, + "nixpkgs-2003_13": { + "locked": { + "lastModified": 1620055814, + "narHash": "sha256-8LEHoYSJiL901bTMVatq+rf8y7QtWuZhwwpKE2fyaRY=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "1db42b7fe3878f3f5f7a4f2dc210772fd080e205", + "type": "github" + }, + "original": { + "owner": "NixOS", + "ref": "nixpkgs-20.03-darwin", + "repo": "nixpkgs", + "type": "github" + } + }, + "nixpkgs-2003_14": { + "locked": { + "lastModified": 1620055814, + "narHash": "sha256-8LEHoYSJiL901bTMVatq+rf8y7QtWuZhwwpKE2fyaRY=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "1db42b7fe3878f3f5f7a4f2dc210772fd080e205", + "type": "github" + }, + "original": { + "owner": "NixOS", + "ref": "nixpkgs-20.03-darwin", + "repo": "nixpkgs", + "type": "github" + } + }, + "nixpkgs-2003_15": { + "locked": { + "lastModified": 1620055814, "narHash": "sha256-8LEHoYSJiL901bTMVatq+rf8y7QtWuZhwwpKE2fyaRY=", "owner": "NixOS", "repo": "nixpkgs", @@ -7075,11 +8280,11 @@ }, "nixpkgs-2105_10": { "locked": { - "lastModified": 1642244250, - "narHash": "sha256-vWpUEqQdVP4srj+/YLJRTN9vjpTs4je0cdWKXPbDItc=", + "lastModified": 1645296114, + "narHash": "sha256-y53N7TyIkXsjMpOG7RhvqJFGDacLs9HlyHeSTBioqYU=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "0fd9ee1aa36ce865ad273f4f07fdc093adeb5c00", + "rev": "530a53dcbc9437363471167a5e4762c5fcfa34a1", "type": "github" }, "original": { @@ -7089,7 +8294,7 @@ "type": "github" } }, - "nixpkgs-2105_2": { + "nixpkgs-2105_11": { "locked": { "lastModified": 1645296114, "narHash": "sha256-y53N7TyIkXsjMpOG7RhvqJFGDacLs9HlyHeSTBioqYU=", @@ -7105,7 +8310,7 @@ "type": "github" } }, - "nixpkgs-2105_3": { + "nixpkgs-2105_12": { "locked": { "lastModified": 1645296114, "narHash": "sha256-y53N7TyIkXsjMpOG7RhvqJFGDacLs9HlyHeSTBioqYU=", @@ -7121,7 +8326,7 @@ "type": "github" } }, - "nixpkgs-2105_4": { + "nixpkgs-2105_13": { "locked": { "lastModified": 1645296114, "narHash": "sha256-y53N7TyIkXsjMpOG7RhvqJFGDacLs9HlyHeSTBioqYU=", @@ -7137,7 +8342,7 @@ "type": "github" } }, - "nixpkgs-2105_5": { + "nixpkgs-2105_14": { "locked": { "lastModified": 1645296114, "narHash": "sha256-y53N7TyIkXsjMpOG7RhvqJFGDacLs9HlyHeSTBioqYU=", @@ -7153,7 +8358,7 @@ "type": "github" } }, - "nixpkgs-2105_6": { + "nixpkgs-2105_15": { "locked": { "lastModified": 1645296114, "narHash": "sha256-y53N7TyIkXsjMpOG7RhvqJFGDacLs9HlyHeSTBioqYU=", @@ -7169,7 +8374,7 @@ "type": "github" } }, - "nixpkgs-2105_7": { + "nixpkgs-2105_2": { "locked": { "lastModified": 1645296114, "narHash": "sha256-y53N7TyIkXsjMpOG7RhvqJFGDacLs9HlyHeSTBioqYU=", @@ -7185,7 +8390,7 @@ "type": "github" } }, - "nixpkgs-2105_8": { + "nixpkgs-2105_3": { "locked": { "lastModified": 1645296114, "narHash": "sha256-y53N7TyIkXsjMpOG7RhvqJFGDacLs9HlyHeSTBioqYU=", @@ -7201,7 +8406,7 @@ "type": "github" } }, - "nixpkgs-2105_9": { + "nixpkgs-2105_4": { "locked": { "lastModified": 1645296114, "narHash": "sha256-y53N7TyIkXsjMpOG7RhvqJFGDacLs9HlyHeSTBioqYU=", @@ -7217,77 +8422,93 @@ "type": "github" } }, - "nixpkgs-2111": { + "nixpkgs-2105_5": { "locked": { - "lastModified": 1654115789, - "narHash": "sha256-k9Qr8dLrmgEn+xIVbneJdQgCYG8FbbqOrTVaExUrLFI=", + "lastModified": 1645296114, + "narHash": "sha256-y53N7TyIkXsjMpOG7RhvqJFGDacLs9HlyHeSTBioqYU=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "bce6d15455f8c15c9ef511368947e7ef789c5316", + "rev": "530a53dcbc9437363471167a5e4762c5fcfa34a1", "type": "github" }, "original": { "owner": "NixOS", - "ref": "nixpkgs-21.11-darwin", + "ref": "nixpkgs-21.05-darwin", "repo": "nixpkgs", "type": "github" } }, - "nixpkgs-2111_10": { + "nixpkgs-2105_6": { "locked": { - "lastModified": 1648744337, - "narHash": "sha256-bYe1dFJAXovjqiaPKrmAbSBEK5KUkgwVaZcTbSoJ7hg=", + "lastModified": 1645296114, + "narHash": "sha256-y53N7TyIkXsjMpOG7RhvqJFGDacLs9HlyHeSTBioqYU=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "0a58eebd8ec65ffdef2ce9562784123a73922052", + "rev": "530a53dcbc9437363471167a5e4762c5fcfa34a1", "type": "github" }, "original": { "owner": "NixOS", - "ref": "nixpkgs-21.11-darwin", + "ref": "nixpkgs-21.05-darwin", "repo": "nixpkgs", "type": "github" } }, - "nixpkgs-2111_11": { + "nixpkgs-2105_7": { "locked": { - "lastModified": 1652364845, - "narHash": "sha256-1pG2GR+z7IrUVGcMoTsH6nJ+ACMvBplo/Pyw4SXJDIE=", + "lastModified": 1645296114, + "narHash": "sha256-y53N7TyIkXsjMpOG7RhvqJFGDacLs9HlyHeSTBioqYU=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "ee80943d4d1160f460e3d719222212dbfbc6a193", + "rev": "530a53dcbc9437363471167a5e4762c5fcfa34a1", "type": "github" }, "original": { "owner": "NixOS", - "ref": "nixpkgs-21.11-darwin", + "ref": "nixpkgs-21.05-darwin", "repo": "nixpkgs", "type": "github" } }, - "nixpkgs-2111_12": { + "nixpkgs-2105_8": { "locked": { - "lastModified": 1648744337, - "narHash": "sha256-bYe1dFJAXovjqiaPKrmAbSBEK5KUkgwVaZcTbSoJ7hg=", + "lastModified": 1645296114, + "narHash": "sha256-y53N7TyIkXsjMpOG7RhvqJFGDacLs9HlyHeSTBioqYU=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "0a58eebd8ec65ffdef2ce9562784123a73922052", + "rev": "530a53dcbc9437363471167a5e4762c5fcfa34a1", "type": "github" }, "original": { "owner": "NixOS", - "ref": "nixpkgs-21.11-darwin", + "ref": "nixpkgs-21.05-darwin", "repo": "nixpkgs", "type": "github" } }, - "nixpkgs-2111_13": { + "nixpkgs-2105_9": { + "locked": { + "lastModified": 1645296114, + "narHash": "sha256-y53N7TyIkXsjMpOG7RhvqJFGDacLs9HlyHeSTBioqYU=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "530a53dcbc9437363471167a5e4762c5fcfa34a1", + "type": "github" + }, + "original": { + "owner": "NixOS", + "ref": "nixpkgs-21.05-darwin", + "repo": "nixpkgs", + "type": "github" + } + }, + "nixpkgs-2111": { "locked": { - "lastModified": 1654115789, - "narHash": "sha256-k9Qr8dLrmgEn+xIVbneJdQgCYG8FbbqOrTVaExUrLFI=", + "lastModified": 1658346836, + "narHash": "sha256-c9BZZbi0tqCQ4j6CMVDlsut3Q3ET1Fezf+qIslCfkhs=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "bce6d15455f8c15c9ef511368947e7ef789c5316", + "rev": "a1fe662eb26ffc2a036b37c4670392ade632c413", "type": "github" }, "original": { @@ -7297,7 +8518,7 @@ "type": "github" } }, - "nixpkgs-2111_14": { + "nixpkgs-2111_10": { "locked": { "lastModified": 1648744337, "narHash": "sha256-bYe1dFJAXovjqiaPKrmAbSBEK5KUkgwVaZcTbSoJ7hg=", @@ -7313,13 +8534,13 @@ "type": "github" } }, - "nixpkgs-2111_15": { + "nixpkgs-2111_11": { "locked": { - "lastModified": 1652364845, - "narHash": "sha256-1pG2GR+z7IrUVGcMoTsH6nJ+ACMvBplo/Pyw4SXJDIE=", + "lastModified": 1659375853, + "narHash": "sha256-aiMfO6U1w1u93vB+5qCHCQDZKgpJ7qs4GJOQvI3CN/4=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "ee80943d4d1160f460e3d719222212dbfbc6a193", + "rev": "511f6a5c3248f9019a41e70c1891484de2bc906c", "type": "github" }, "original": { @@ -7329,7 +8550,7 @@ "type": "github" } }, - "nixpkgs-2111_16": { + "nixpkgs-2111_12": { "locked": { "lastModified": 1648744337, "narHash": "sha256-bYe1dFJAXovjqiaPKrmAbSBEK5KUkgwVaZcTbSoJ7hg=", @@ -7345,13 +8566,13 @@ "type": "github" } }, - "nixpkgs-2111_17": { + "nixpkgs-2111_13": { "locked": { - "lastModified": 1653319070, - "narHash": "sha256-Z3cv967iN6mXgxhq1cjOoPod23XgNttCWHXMnMZUq9E=", + "lastModified": 1658346836, + "narHash": "sha256-c9BZZbi0tqCQ4j6CMVDlsut3Q3ET1Fezf+qIslCfkhs=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "1c813bbdc330b45fe922c642eb610902aecd5673", + "rev": "a1fe662eb26ffc2a036b37c4670392ade632c413", "type": "github" }, "original": { @@ -7361,7 +8582,71 @@ "type": "github" } }, - "nixpkgs-2111_18": { + "nixpkgs-2111_14": { + "locked": { + "lastModified": 1648744337, + "narHash": "sha256-bYe1dFJAXovjqiaPKrmAbSBEK5KUkgwVaZcTbSoJ7hg=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "0a58eebd8ec65ffdef2ce9562784123a73922052", + "type": "github" + }, + "original": { + "owner": "NixOS", + "ref": "nixpkgs-21.11-darwin", + "repo": "nixpkgs", + "type": "github" + } + }, + "nixpkgs-2111_15": { + "locked": { + "lastModified": 1658346836, + "narHash": "sha256-c9BZZbi0tqCQ4j6CMVDlsut3Q3ET1Fezf+qIslCfkhs=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "a1fe662eb26ffc2a036b37c4670392ade632c413", + "type": "github" + }, + "original": { + "owner": "NixOS", + "ref": "nixpkgs-21.11-darwin", + "repo": "nixpkgs", + "type": "github" + } + }, + "nixpkgs-2111_16": { + "locked": { + "lastModified": 1648744337, + "narHash": "sha256-bYe1dFJAXovjqiaPKrmAbSBEK5KUkgwVaZcTbSoJ7hg=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "0a58eebd8ec65ffdef2ce9562784123a73922052", + "type": "github" + }, + "original": { + "owner": "NixOS", + "ref": "nixpkgs-21.11-darwin", + "repo": "nixpkgs", + "type": "github" + } + }, + "nixpkgs-2111_17": { + "locked": { + "lastModified": 1658346836, + "narHash": "sha256-c9BZZbi0tqCQ4j6CMVDlsut3Q3ET1Fezf+qIslCfkhs=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "a1fe662eb26ffc2a036b37c4670392ade632c413", + "type": "github" + }, + "original": { + "owner": "NixOS", + "ref": "nixpkgs-21.11-darwin", + "repo": "nixpkgs", + "type": "github" + } + }, + "nixpkgs-2111_18": { "locked": { "lastModified": 1648744337, "narHash": "sha256-bYe1dFJAXovjqiaPKrmAbSBEK5KUkgwVaZcTbSoJ7hg=", @@ -7379,11 +8664,11 @@ }, "nixpkgs-2111_19": { "locked": { - "lastModified": 1653319070, - "narHash": "sha256-Z3cv967iN6mXgxhq1cjOoPod23XgNttCWHXMnMZUq9E=", + "lastModified": 1658346836, + "narHash": "sha256-c9BZZbi0tqCQ4j6CMVDlsut3Q3ET1Fezf+qIslCfkhs=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "1c813bbdc330b45fe922c642eb610902aecd5673", + "rev": "a1fe662eb26ffc2a036b37c4670392ade632c413", "type": "github" }, "original": { @@ -7411,11 +8696,155 @@ }, "nixpkgs-2111_20": { "locked": { - "lastModified": 1644510859, - "narHash": "sha256-xjpVvL5ecbyi0vxtVl/Fh9bwGlMbw3S06zE5nUzFB8A=", + "lastModified": 1648744337, + "narHash": "sha256-bYe1dFJAXovjqiaPKrmAbSBEK5KUkgwVaZcTbSoJ7hg=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "0a58eebd8ec65ffdef2ce9562784123a73922052", + "type": "github" + }, + "original": { + "owner": "NixOS", + "ref": "nixpkgs-21.11-darwin", + "repo": "nixpkgs", + "type": "github" + } + }, + "nixpkgs-2111_21": { + "locked": { + "lastModified": 1658346836, + "narHash": "sha256-c9BZZbi0tqCQ4j6CMVDlsut3Q3ET1Fezf+qIslCfkhs=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "a1fe662eb26ffc2a036b37c4670392ade632c413", + "type": "github" + }, + "original": { + "owner": "NixOS", + "ref": "nixpkgs-21.11-darwin", + "repo": "nixpkgs", + "type": "github" + } + }, + "nixpkgs-2111_22": { + "locked": { + "lastModified": 1648744337, + "narHash": "sha256-bYe1dFJAXovjqiaPKrmAbSBEK5KUkgwVaZcTbSoJ7hg=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "0a58eebd8ec65ffdef2ce9562784123a73922052", + "type": "github" + }, + "original": { + "owner": "NixOS", + "ref": "nixpkgs-21.11-darwin", + "repo": "nixpkgs", + "type": "github" + } + }, + "nixpkgs-2111_23": { + "locked": { + "lastModified": 1658346836, + "narHash": "sha256-c9BZZbi0tqCQ4j6CMVDlsut3Q3ET1Fezf+qIslCfkhs=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "a1fe662eb26ffc2a036b37c4670392ade632c413", + "type": "github" + }, + "original": { + "owner": "NixOS", + "ref": "nixpkgs-21.11-darwin", + "repo": "nixpkgs", + "type": "github" + } + }, + "nixpkgs-2111_24": { + "locked": { + "lastModified": 1648744337, + "narHash": "sha256-bYe1dFJAXovjqiaPKrmAbSBEK5KUkgwVaZcTbSoJ7hg=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "0a58eebd8ec65ffdef2ce9562784123a73922052", + "type": "github" + }, + "original": { + "owner": "NixOS", + "ref": "nixpkgs-21.11-darwin", + "repo": "nixpkgs", + "type": "github" + } + }, + "nixpkgs-2111_25": { + "locked": { + "lastModified": 1659375853, + "narHash": "sha256-aiMfO6U1w1u93vB+5qCHCQDZKgpJ7qs4GJOQvI3CN/4=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "511f6a5c3248f9019a41e70c1891484de2bc906c", + "type": "github" + }, + "original": { + "owner": "NixOS", + "ref": "nixpkgs-21.11-darwin", + "repo": "nixpkgs", + "type": "github" + } + }, + "nixpkgs-2111_26": { + "locked": { + "lastModified": 1648744337, + "narHash": "sha256-bYe1dFJAXovjqiaPKrmAbSBEK5KUkgwVaZcTbSoJ7hg=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "0a58eebd8ec65ffdef2ce9562784123a73922052", + "type": "github" + }, + "original": { + "owner": "NixOS", + "ref": "nixpkgs-21.11-darwin", + "repo": "nixpkgs", + "type": "github" + } + }, + "nixpkgs-2111_27": { + "locked": { + "lastModified": 1658346836, + "narHash": "sha256-c9BZZbi0tqCQ4j6CMVDlsut3Q3ET1Fezf+qIslCfkhs=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "a1fe662eb26ffc2a036b37c4670392ade632c413", + "type": "github" + }, + "original": { + "owner": "NixOS", + "ref": "nixpkgs-21.11-darwin", + "repo": "nixpkgs", + "type": "github" + } + }, + "nixpkgs-2111_28": { + "locked": { + "lastModified": 1648744337, + "narHash": "sha256-bYe1dFJAXovjqiaPKrmAbSBEK5KUkgwVaZcTbSoJ7hg=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "0a58eebd8ec65ffdef2ce9562784123a73922052", + "type": "github" + }, + "original": { + "owner": "NixOS", + "ref": "nixpkgs-21.11-darwin", + "repo": "nixpkgs", + "type": "github" + } + }, + "nixpkgs-2111_29": { + "locked": { + "lastModified": 1659446231, + "narHash": "sha256-hekabNdTdgR/iLsgce5TGWmfIDZ86qjPhxDg/8TlzhE=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "0d1d5d7e3679fec9d07f2eb804d9f9fdb98378d3", + "rev": "eabc38219184cc3e04a974fe31857d8e0eac098d", "type": "github" }, "original": { @@ -7427,11 +8856,27 @@ }, "nixpkgs-2111_3": { "locked": { - "lastModified": 1652364845, - "narHash": "sha256-1pG2GR+z7IrUVGcMoTsH6nJ+ACMvBplo/Pyw4SXJDIE=", + "lastModified": 1658346836, + "narHash": "sha256-c9BZZbi0tqCQ4j6CMVDlsut3Q3ET1Fezf+qIslCfkhs=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "a1fe662eb26ffc2a036b37c4670392ade632c413", + "type": "github" + }, + "original": { + "owner": "NixOS", + "ref": "nixpkgs-21.11-darwin", + "repo": "nixpkgs", + "type": "github" + } + }, + "nixpkgs-2111_30": { + "locked": { + "lastModified": 1648744337, + "narHash": "sha256-bYe1dFJAXovjqiaPKrmAbSBEK5KUkgwVaZcTbSoJ7hg=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "ee80943d4d1160f460e3d719222212dbfbc6a193", + "rev": "0a58eebd8ec65ffdef2ce9562784123a73922052", "type": "github" }, "original": { @@ -7459,11 +8904,11 @@ }, "nixpkgs-2111_5": { "locked": { - "lastModified": 1655415671, - "narHash": "sha256-WD7HxxW1m8D/fkV1QlCYlZvnE5gQdg7ckq3myI4gPtE=", + "lastModified": 1658346836, + "narHash": "sha256-c9BZZbi0tqCQ4j6CMVDlsut3Q3ET1Fezf+qIslCfkhs=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "f96729212602f15a6a226d2f27f5de70492ad095", + "rev": "a1fe662eb26ffc2a036b37c4670392ade632c413", "type": "github" }, "original": { @@ -7491,11 +8936,11 @@ }, "nixpkgs-2111_7": { "locked": { - "lastModified": 1652298859, - "narHash": "sha256-hcwRboK+NxMWUJh0fQ3VsocDcAHrYJ95FmPEHlddV0Y=", + "lastModified": 1658346836, + "narHash": "sha256-c9BZZbi0tqCQ4j6CMVDlsut3Q3ET1Fezf+qIslCfkhs=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "051448e41537c3463ae776d46115d01afb6c498d", + "rev": "a1fe662eb26ffc2a036b37c4670392ade632c413", "type": "github" }, "original": { @@ -7523,11 +8968,11 @@ }, "nixpkgs-2111_9": { "locked": { - "lastModified": 1653319070, - "narHash": "sha256-Z3cv967iN6mXgxhq1cjOoPod23XgNttCWHXMnMZUq9E=", + "lastModified": 1659446231, + "narHash": "sha256-hekabNdTdgR/iLsgce5TGWmfIDZ86qjPhxDg/8TlzhE=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "1c813bbdc330b45fe922c642eb610902aecd5673", + "rev": "eabc38219184cc3e04a974fe31857d8e0eac098d", "type": "github" }, "original": { @@ -7537,6 +8982,38 @@ "type": "github" } }, + "nixpkgs-2205": { + "locked": { + "lastModified": 1660033036, + "narHash": "sha256-GjwzXmdN5SVTT0RIZ11uDTQxaHLTLt9/AbBeIHNfidQ=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "490f6174c03132bf8f078d0f3a6e5890a47f9b30", + "type": "github" + }, + "original": { + "owner": "NixOS", + "ref": "nixos-22.05", + "repo": "nixpkgs", + "type": "github" + } + }, + "nixpkgs-2205_2": { + "locked": { + "lastModified": 1660033036, + "narHash": "sha256-GjwzXmdN5SVTT0RIZ11uDTQxaHLTLt9/AbBeIHNfidQ=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "490f6174c03132bf8f078d0f3a6e5890a47f9b30", + "type": "github" + }, + "original": { + "owner": "NixOS", + "ref": "nixos-22.05", + "repo": "nixpkgs", + "type": "github" + } + }, "nixpkgs-latest": { "locked": { "lastModified": 1653918805, @@ -7729,7 +9206,7 @@ "type": "github" } }, - "nixpkgs-latest_3": { + "nixpkgs-latest_20": { "locked": { "lastModified": 1653918805, "narHash": "sha256-6ahwAnBNGgqSNSn/6RnsxrlFi+fkA+RyT6o/5S1915o=", @@ -7745,7 +9222,7 @@ "type": "github" } }, - "nixpkgs-latest_4": { + "nixpkgs-latest_21": { "locked": { "lastModified": 1653918805, "narHash": "sha256-6ahwAnBNGgqSNSn/6RnsxrlFi+fkA+RyT6o/5S1915o=", @@ -7761,7 +9238,7 @@ "type": "github" } }, - "nixpkgs-latest_5": { + "nixpkgs-latest_22": { "locked": { "lastModified": 1653918805, "narHash": "sha256-6ahwAnBNGgqSNSn/6RnsxrlFi+fkA+RyT6o/5S1915o=", @@ -7777,7 +9254,7 @@ "type": "github" } }, - "nixpkgs-latest_6": { + "nixpkgs-latest_23": { "locked": { "lastModified": 1653918805, "narHash": "sha256-6ahwAnBNGgqSNSn/6RnsxrlFi+fkA+RyT6o/5S1915o=", @@ -7793,7 +9270,7 @@ "type": "github" } }, - "nixpkgs-latest_7": { + "nixpkgs-latest_24": { "locked": { "lastModified": 1653918805, "narHash": "sha256-6ahwAnBNGgqSNSn/6RnsxrlFi+fkA+RyT6o/5S1915o=", @@ -7809,7 +9286,7 @@ "type": "github" } }, - "nixpkgs-latest_8": { + "nixpkgs-latest_25": { "locked": { "lastModified": 1653918805, "narHash": "sha256-6ahwAnBNGgqSNSn/6RnsxrlFi+fkA+RyT6o/5S1915o=", @@ -7825,7 +9302,7 @@ "type": "github" } }, - "nixpkgs-latest_9": { + "nixpkgs-latest_26": { "locked": { "lastModified": 1653918805, "narHash": "sha256-6ahwAnBNGgqSNSn/6RnsxrlFi+fkA+RyT6o/5S1915o=", @@ -7841,40 +9318,186 @@ "type": "github" } }, - "nixpkgs-regression": { + "nixpkgs-latest_27": { "locked": { - "lastModified": 1643052045, - "narHash": "sha256-uGJ0VXIhWKGXxkeNnq4TvV3CIOkUJ3PAoLZ3HMzNVMw=", + "lastModified": 1653918805, + "narHash": "sha256-6ahwAnBNGgqSNSn/6RnsxrlFi+fkA+RyT6o/5S1915o=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "215d4d0fd80ca5163643b03a33fde804a29cc1e2", + "rev": "a0a69be4b5ee63f1b5e75887a406e9194012b492", "type": "github" }, "original": { - "id": "nixpkgs", - "rev": "215d4d0fd80ca5163643b03a33fde804a29cc1e2", - "type": "indirect" + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "a0a69be4b5ee63f1b5e75887a406e9194012b492", + "type": "github" } }, - "nixpkgs-regression_2": { + "nixpkgs-latest_28": { "locked": { - "lastModified": 1643052045, - "narHash": "sha256-uGJ0VXIhWKGXxkeNnq4TvV3CIOkUJ3PAoLZ3HMzNVMw=", + "lastModified": 1653918805, + "narHash": "sha256-6ahwAnBNGgqSNSn/6RnsxrlFi+fkA+RyT6o/5S1915o=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "215d4d0fd80ca5163643b03a33fde804a29cc1e2", + "rev": "a0a69be4b5ee63f1b5e75887a406e9194012b492", "type": "github" }, "original": { - "id": "nixpkgs", - "rev": "215d4d0fd80ca5163643b03a33fde804a29cc1e2", - "type": "indirect" + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "a0a69be4b5ee63f1b5e75887a406e9194012b492", + "type": "github" } }, - "nixpkgs-regression_3": { + "nixpkgs-latest_29": { "locked": { - "lastModified": 1643052045, - "narHash": "sha256-uGJ0VXIhWKGXxkeNnq4TvV3CIOkUJ3PAoLZ3HMzNVMw=", + "lastModified": 1659622790, + "narHash": "sha256-fYelfx2ScXVprcivGPif+hi9cOZPt3/4wV5rC3AwZDs=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "cf63df0364f67848083ff75bc8ac9b7ca7aa5a01", + "type": "github" + }, + "original": { + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "cf63df0364f67848083ff75bc8ac9b7ca7aa5a01", + "type": "github" + } + }, + "nixpkgs-latest_3": { + "locked": { + "lastModified": 1653918805, + "narHash": "sha256-6ahwAnBNGgqSNSn/6RnsxrlFi+fkA+RyT6o/5S1915o=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "a0a69be4b5ee63f1b5e75887a406e9194012b492", + "type": "github" + }, + "original": { + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "a0a69be4b5ee63f1b5e75887a406e9194012b492", + "type": "github" + } + }, + "nixpkgs-latest_30": { + "locked": { + "lastModified": 1653918805, + "narHash": "sha256-6ahwAnBNGgqSNSn/6RnsxrlFi+fkA+RyT6o/5S1915o=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "a0a69be4b5ee63f1b5e75887a406e9194012b492", + "type": "github" + }, + "original": { + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "a0a69be4b5ee63f1b5e75887a406e9194012b492", + "type": "github" + } + }, + "nixpkgs-latest_4": { + "locked": { + "lastModified": 1653918805, + "narHash": "sha256-6ahwAnBNGgqSNSn/6RnsxrlFi+fkA+RyT6o/5S1915o=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "a0a69be4b5ee63f1b5e75887a406e9194012b492", + "type": "github" + }, + "original": { + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "a0a69be4b5ee63f1b5e75887a406e9194012b492", + "type": "github" + } + }, + "nixpkgs-latest_5": { + "locked": { + "lastModified": 1653918805, + "narHash": "sha256-6ahwAnBNGgqSNSn/6RnsxrlFi+fkA+RyT6o/5S1915o=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "a0a69be4b5ee63f1b5e75887a406e9194012b492", + "type": "github" + }, + "original": { + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "a0a69be4b5ee63f1b5e75887a406e9194012b492", + "type": "github" + } + }, + "nixpkgs-latest_6": { + "locked": { + "lastModified": 1653918805, + "narHash": "sha256-6ahwAnBNGgqSNSn/6RnsxrlFi+fkA+RyT6o/5S1915o=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "a0a69be4b5ee63f1b5e75887a406e9194012b492", + "type": "github" + }, + "original": { + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "a0a69be4b5ee63f1b5e75887a406e9194012b492", + "type": "github" + } + }, + "nixpkgs-latest_7": { + "locked": { + "lastModified": 1653918805, + "narHash": "sha256-6ahwAnBNGgqSNSn/6RnsxrlFi+fkA+RyT6o/5S1915o=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "a0a69be4b5ee63f1b5e75887a406e9194012b492", + "type": "github" + }, + "original": { + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "a0a69be4b5ee63f1b5e75887a406e9194012b492", + "type": "github" + } + }, + "nixpkgs-latest_8": { + "locked": { + "lastModified": 1653918805, + "narHash": "sha256-6ahwAnBNGgqSNSn/6RnsxrlFi+fkA+RyT6o/5S1915o=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "a0a69be4b5ee63f1b5e75887a406e9194012b492", + "type": "github" + }, + "original": { + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "a0a69be4b5ee63f1b5e75887a406e9194012b492", + "type": "github" + } + }, + "nixpkgs-latest_9": { + "locked": { + "lastModified": 1659622790, + "narHash": "sha256-fYelfx2ScXVprcivGPif+hi9cOZPt3/4wV5rC3AwZDs=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "cf63df0364f67848083ff75bc8ac9b7ca7aa5a01", + "type": "github" + }, + "original": { + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "cf63df0364f67848083ff75bc8ac9b7ca7aa5a01", + "type": "github" + } + }, + "nixpkgs-regression": { + "locked": { + "lastModified": 1643052045, + "narHash": "sha256-uGJ0VXIhWKGXxkeNnq4TvV3CIOkUJ3PAoLZ3HMzNVMw=", "owner": "NixOS", "repo": "nixpkgs", "rev": "215d4d0fd80ca5163643b03a33fde804a29cc1e2", @@ -7886,7 +9509,7 @@ "type": "indirect" } }, - "nixpkgs-regression_4": { + "nixpkgs-regression_10": { "locked": { "lastModified": 1643052045, "narHash": "sha256-uGJ0VXIhWKGXxkeNnq4TvV3CIOkUJ3PAoLZ3HMzNVMw=", @@ -7901,7 +9524,7 @@ "type": "indirect" } }, - "nixpkgs-regression_5": { + "nixpkgs-regression_11": { "locked": { "lastModified": 1643052045, "narHash": "sha256-uGJ0VXIhWKGXxkeNnq4TvV3CIOkUJ3PAoLZ3HMzNVMw=", @@ -7916,7 +9539,7 @@ "type": "indirect" } }, - "nixpkgs-regression_6": { + "nixpkgs-regression_12": { "locked": { "lastModified": 1643052045, "narHash": "sha256-uGJ0VXIhWKGXxkeNnq4TvV3CIOkUJ3PAoLZ3HMzNVMw=", @@ -7931,7 +9554,7 @@ "type": "indirect" } }, - "nixpkgs-regression_7": { + "nixpkgs-regression_13": { "locked": { "lastModified": 1643052045, "narHash": "sha256-uGJ0VXIhWKGXxkeNnq4TvV3CIOkUJ3PAoLZ3HMzNVMw=", @@ -7946,7 +9569,7 @@ "type": "indirect" } }, - "nixpkgs-regression_8": { + "nixpkgs-regression_14": { "locked": { "lastModified": 1643052045, "narHash": "sha256-uGJ0VXIhWKGXxkeNnq4TvV3CIOkUJ3PAoLZ3HMzNVMw=", @@ -7961,7 +9584,7 @@ "type": "indirect" } }, - "nixpkgs-regression_9": { + "nixpkgs-regression_15": { "locked": { "lastModified": 1643052045, "narHash": "sha256-uGJ0VXIhWKGXxkeNnq4TvV3CIOkUJ3PAoLZ3HMzNVMw=", @@ -7976,71 +9599,127 @@ "type": "indirect" } }, - "nixpkgs-unstable": { + "nixpkgs-regression_2": { "locked": { - "lastModified": 1648219316, - "narHash": "sha256-Ctij+dOi0ZZIfX5eMhgwugfvB+WZSrvVNAyAuANOsnQ=", + "lastModified": 1643052045, + "narHash": "sha256-uGJ0VXIhWKGXxkeNnq4TvV3CIOkUJ3PAoLZ3HMzNVMw=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "30d3d79b7d3607d56546dd2a6b49e156ba0ec634", + "rev": "215d4d0fd80ca5163643b03a33fde804a29cc1e2", "type": "github" }, "original": { + "id": "nixpkgs", + "rev": "215d4d0fd80ca5163643b03a33fde804a29cc1e2", + "type": "indirect" + } + }, + "nixpkgs-regression_3": { + "locked": { + "lastModified": 1643052045, + "narHash": "sha256-uGJ0VXIhWKGXxkeNnq4TvV3CIOkUJ3PAoLZ3HMzNVMw=", "owner": "NixOS", - "ref": "nixpkgs-unstable", "repo": "nixpkgs", + "rev": "215d4d0fd80ca5163643b03a33fde804a29cc1e2", "type": "github" + }, + "original": { + "id": "nixpkgs", + "rev": "215d4d0fd80ca5163643b03a33fde804a29cc1e2", + "type": "indirect" } }, - "nixpkgs-unstable_10": { + "nixpkgs-regression_4": { "locked": { - "lastModified": 1644486793, - "narHash": "sha256-EeijR4guVHgVv+JpOX3cQO+1XdrkJfGmiJ9XVsVU530=", + "lastModified": 1643052045, + "narHash": "sha256-uGJ0VXIhWKGXxkeNnq4TvV3CIOkUJ3PAoLZ3HMzNVMw=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "1882c6b7368fd284ad01b0a5b5601ef136321292", + "rev": "215d4d0fd80ca5163643b03a33fde804a29cc1e2", "type": "github" }, "original": { + "id": "nixpkgs", + "rev": "215d4d0fd80ca5163643b03a33fde804a29cc1e2", + "type": "indirect" + } + }, + "nixpkgs-regression_5": { + "locked": { + "lastModified": 1643052045, + "narHash": "sha256-uGJ0VXIhWKGXxkeNnq4TvV3CIOkUJ3PAoLZ3HMzNVMw=", "owner": "NixOS", - "ref": "nixpkgs-unstable", "repo": "nixpkgs", + "rev": "215d4d0fd80ca5163643b03a33fde804a29cc1e2", "type": "github" + }, + "original": { + "id": "nixpkgs", + "rev": "215d4d0fd80ca5163643b03a33fde804a29cc1e2", + "type": "indirect" } }, - "nixpkgs-unstable_2": { + "nixpkgs-regression_6": { "locked": { - "lastModified": 1648219316, - "narHash": "sha256-Ctij+dOi0ZZIfX5eMhgwugfvB+WZSrvVNAyAuANOsnQ=", + "lastModified": 1643052045, + "narHash": "sha256-uGJ0VXIhWKGXxkeNnq4TvV3CIOkUJ3PAoLZ3HMzNVMw=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "30d3d79b7d3607d56546dd2a6b49e156ba0ec634", + "rev": "215d4d0fd80ca5163643b03a33fde804a29cc1e2", "type": "github" }, "original": { + "id": "nixpkgs", + "rev": "215d4d0fd80ca5163643b03a33fde804a29cc1e2", + "type": "indirect" + } + }, + "nixpkgs-regression_7": { + "locked": { + "lastModified": 1643052045, + "narHash": "sha256-uGJ0VXIhWKGXxkeNnq4TvV3CIOkUJ3PAoLZ3HMzNVMw=", "owner": "NixOS", - "ref": "nixpkgs-unstable", "repo": "nixpkgs", + "rev": "215d4d0fd80ca5163643b03a33fde804a29cc1e2", "type": "github" + }, + "original": { + "id": "nixpkgs", + "rev": "215d4d0fd80ca5163643b03a33fde804a29cc1e2", + "type": "indirect" } }, - "nixpkgs-unstable_3": { + "nixpkgs-regression_8": { "locked": { - "lastModified": 1648219316, - "narHash": "sha256-Ctij+dOi0ZZIfX5eMhgwugfvB+WZSrvVNAyAuANOsnQ=", + "lastModified": 1643052045, + "narHash": "sha256-uGJ0VXIhWKGXxkeNnq4TvV3CIOkUJ3PAoLZ3HMzNVMw=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "30d3d79b7d3607d56546dd2a6b49e156ba0ec634", + "rev": "215d4d0fd80ca5163643b03a33fde804a29cc1e2", "type": "github" }, "original": { + "id": "nixpkgs", + "rev": "215d4d0fd80ca5163643b03a33fde804a29cc1e2", + "type": "indirect" + } + }, + "nixpkgs-regression_9": { + "locked": { + "lastModified": 1643052045, + "narHash": "sha256-uGJ0VXIhWKGXxkeNnq4TvV3CIOkUJ3PAoLZ3HMzNVMw=", "owner": "NixOS", - "ref": "nixpkgs-unstable", "repo": "nixpkgs", + "rev": "215d4d0fd80ca5163643b03a33fde804a29cc1e2", "type": "github" + }, + "original": { + "id": "nixpkgs", + "rev": "215d4d0fd80ca5163643b03a33fde804a29cc1e2", + "type": "indirect" } }, - "nixpkgs-unstable_4": { + "nixpkgs-unstable": { "locked": { "lastModified": 1648219316, "narHash": "sha256-Ctij+dOi0ZZIfX5eMhgwugfvB+WZSrvVNAyAuANOsnQ=", @@ -8056,7 +9735,7 @@ "type": "github" } }, - "nixpkgs-unstable_5": { + "nixpkgs-unstable_10": { "locked": { "lastModified": 1648219316, "narHash": "sha256-Ctij+dOi0ZZIfX5eMhgwugfvB+WZSrvVNAyAuANOsnQ=", @@ -8072,7 +9751,7 @@ "type": "github" } }, - "nixpkgs-unstable_6": { + "nixpkgs-unstable_11": { "locked": { "lastModified": 1648219316, "narHash": "sha256-Ctij+dOi0ZZIfX5eMhgwugfvB+WZSrvVNAyAuANOsnQ=", @@ -8088,7 +9767,7 @@ "type": "github" } }, - "nixpkgs-unstable_7": { + "nixpkgs-unstable_12": { "locked": { "lastModified": 1648219316, "narHash": "sha256-Ctij+dOi0ZZIfX5eMhgwugfvB+WZSrvVNAyAuANOsnQ=", @@ -8104,7 +9783,7 @@ "type": "github" } }, - "nixpkgs-unstable_8": { + "nixpkgs-unstable_13": { "locked": { "lastModified": 1648219316, "narHash": "sha256-Ctij+dOi0ZZIfX5eMhgwugfvB+WZSrvVNAyAuANOsnQ=", @@ -8120,7 +9799,7 @@ "type": "github" } }, - "nixpkgs-unstable_9": { + "nixpkgs-unstable_14": { "locked": { "lastModified": 1648219316, "narHash": "sha256-Ctij+dOi0ZZIfX5eMhgwugfvB+WZSrvVNAyAuANOsnQ=", @@ -8136,14 +9815,13 @@ "type": "github" } }, - "nixpkgs_10": { - "flake": false, + "nixpkgs-unstable_15": { "locked": { - "lastModified": 1645493675, - "narHash": "sha256-9xundbZQbhFodsQRh6QMN1GeSXfo3y/5NL0CZcJULz0=", + "lastModified": 1648219316, + "narHash": "sha256-Ctij+dOi0ZZIfX5eMhgwugfvB+WZSrvVNAyAuANOsnQ=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "74b10859829153d5c5d50f7c77b86763759e8654", + "rev": "30d3d79b7d3607d56546dd2a6b49e156ba0ec634", "type": "github" }, "original": { @@ -8153,45 +9831,45 @@ "type": "github" } }, - "nixpkgs_11": { + "nixpkgs-unstable_2": { "locked": { - "lastModified": 1632864508, - "narHash": "sha256-d127FIvGR41XbVRDPVvozUPQ/uRHbHwvfyKHwEt5xFM=", + "lastModified": 1648219316, + "narHash": "sha256-Ctij+dOi0ZZIfX5eMhgwugfvB+WZSrvVNAyAuANOsnQ=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "82891b5e2c2359d7e58d08849e4c89511ab94234", + "rev": "30d3d79b7d3607d56546dd2a6b49e156ba0ec634", "type": "github" }, "original": { - "id": "nixpkgs", - "ref": "nixos-21.05-small", - "type": "indirect" + "owner": "NixOS", + "ref": "nixpkgs-unstable", + "repo": "nixpkgs", + "type": "github" } }, - "nixpkgs_12": { + "nixpkgs-unstable_3": { "locked": { - "lastModified": 1647297614, - "narHash": "sha256-ulGq3W5XsrBMU/u5k9d4oPy65pQTkunR4HKKtTq0RwY=", + "lastModified": 1648219316, + "narHash": "sha256-Ctij+dOi0ZZIfX5eMhgwugfvB+WZSrvVNAyAuANOsnQ=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "73ad5f9e147c0d2a2061f1d4bd91e05078dc0b58", + "rev": "30d3d79b7d3607d56546dd2a6b49e156ba0ec634", "type": "github" }, "original": { "owner": "NixOS", - "ref": "nixos-unstable", + "ref": "nixpkgs-unstable", "repo": "nixpkgs", "type": "github" } }, - "nixpkgs_13": { - "flake": false, + "nixpkgs-unstable_4": { "locked": { - "lastModified": 1645493675, - "narHash": "sha256-9xundbZQbhFodsQRh6QMN1GeSXfo3y/5NL0CZcJULz0=", + "lastModified": 1648219316, + "narHash": "sha256-Ctij+dOi0ZZIfX5eMhgwugfvB+WZSrvVNAyAuANOsnQ=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "74b10859829153d5c5d50f7c77b86763759e8654", + "rev": "30d3d79b7d3607d56546dd2a6b49e156ba0ec634", "type": "github" }, "original": { @@ -8201,75 +9879,61 @@ "type": "github" } }, - "nixpkgs_14": { + "nixpkgs-unstable_5": { "locked": { - "lastModified": 1652885393, - "narHash": "sha256-YIgvvlk4iQ1Hi7KD9o5gsojc+ApB+jiH1d5stK8uXiw=", - "owner": "nixos", + "lastModified": 1648219316, + "narHash": "sha256-Ctij+dOi0ZZIfX5eMhgwugfvB+WZSrvVNAyAuANOsnQ=", + "owner": "NixOS", "repo": "nixpkgs", - "rev": "48037fd90426e44e4bf03e6479e88a11453b9b66", + "rev": "30d3d79b7d3607d56546dd2a6b49e156ba0ec634", "type": "github" }, "original": { - "owner": "nixos", - "ref": "nixos-unstable", + "owner": "NixOS", + "ref": "nixpkgs-unstable", "repo": "nixpkgs", "type": "github" } }, - "nixpkgs_15": { + "nixpkgs-unstable_6": { "locked": { - "lastModified": 1653117584, - "narHash": "sha256-5uUrHeHBIaySBTrRExcCoW8fBBYVSDjDYDU5A6iOl+k=", + "lastModified": 1648219316, + "narHash": "sha256-Ctij+dOi0ZZIfX5eMhgwugfvB+WZSrvVNAyAuANOsnQ=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "f4dfed73ee886b115a99e5b85fdfbeb683290d83", + "rev": "30d3d79b7d3607d56546dd2a6b49e156ba0ec634", "type": "github" }, "original": { - "id": "nixpkgs", - "type": "indirect" - } - }, - "nixpkgs_16": { - "locked": { - "lastModified": 1632864508, - "narHash": "sha256-d127FIvGR41XbVRDPVvozUPQ/uRHbHwvfyKHwEt5xFM=", "owner": "NixOS", + "ref": "nixpkgs-unstable", "repo": "nixpkgs", - "rev": "82891b5e2c2359d7e58d08849e4c89511ab94234", "type": "github" - }, - "original": { - "id": "nixpkgs", - "ref": "nixos-21.05-small", - "type": "indirect" } }, - "nixpkgs_17": { + "nixpkgs-unstable_7": { "locked": { - "lastModified": 1647297614, - "narHash": "sha256-ulGq3W5XsrBMU/u5k9d4oPy65pQTkunR4HKKtTq0RwY=", + "lastModified": 1648219316, + "narHash": "sha256-Ctij+dOi0ZZIfX5eMhgwugfvB+WZSrvVNAyAuANOsnQ=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "73ad5f9e147c0d2a2061f1d4bd91e05078dc0b58", + "rev": "30d3d79b7d3607d56546dd2a6b49e156ba0ec634", "type": "github" }, "original": { "owner": "NixOS", - "ref": "nixos-unstable", + "ref": "nixpkgs-unstable", "repo": "nixpkgs", "type": "github" } }, - "nixpkgs_18": { - "flake": false, + "nixpkgs-unstable_8": { "locked": { - "lastModified": 1645493675, - "narHash": "sha256-9xundbZQbhFodsQRh6QMN1GeSXfo3y/5NL0CZcJULz0=", + "lastModified": 1648219316, + "narHash": "sha256-Ctij+dOi0ZZIfX5eMhgwugfvB+WZSrvVNAyAuANOsnQ=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "74b10859829153d5c5d50f7c77b86763759e8654", + "rev": "30d3d79b7d3607d56546dd2a6b49e156ba0ec634", "type": "github" }, "original": { @@ -8279,43 +9943,29 @@ "type": "github" } }, - "nixpkgs_19": { + "nixpkgs-unstable_9": { "locked": { - "lastModified": 1652885393, - "narHash": "sha256-YIgvvlk4iQ1Hi7KD9o5gsojc+ApB+jiH1d5stK8uXiw=", - "owner": "nixos", + "lastModified": 1648219316, + "narHash": "sha256-Ctij+dOi0ZZIfX5eMhgwugfvB+WZSrvVNAyAuANOsnQ=", + "owner": "NixOS", "repo": "nixpkgs", - "rev": "48037fd90426e44e4bf03e6479e88a11453b9b66", + "rev": "30d3d79b7d3607d56546dd2a6b49e156ba0ec634", "type": "github" }, "original": { - "owner": "nixos", - "ref": "nixos-unstable", - "repo": "nixpkgs", - "type": "github" - } - }, - "nixpkgs_2": { - "locked": { - "lastModified": 1653117584, - "narHash": "sha256-5uUrHeHBIaySBTrRExcCoW8fBBYVSDjDYDU5A6iOl+k=", "owner": "NixOS", + "ref": "nixpkgs-unstable", "repo": "nixpkgs", - "rev": "f4dfed73ee886b115a99e5b85fdfbeb683290d83", "type": "github" - }, - "original": { - "id": "nixpkgs", - "type": "indirect" } }, - "nixpkgs_20": { + "nixpkgs_10": { "locked": { - "lastModified": 1653117584, - "narHash": "sha256-5uUrHeHBIaySBTrRExcCoW8fBBYVSDjDYDU5A6iOl+k=", + "lastModified": 1657292830, + "narHash": "sha256-ldfVSTveWceDCmW6gf3B4kR6vwmz/XS80y5wsLLHFJU=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "f4dfed73ee886b115a99e5b85fdfbeb683290d83", + "rev": "334ec8b503c3981e37a04b817a70e8d026ea9e84", "type": "github" }, "original": { @@ -8323,7 +9973,7 @@ "type": "indirect" } }, - "nixpkgs_21": { + "nixpkgs_11": { "locked": { "lastModified": 1632864508, "narHash": "sha256-d127FIvGR41XbVRDPVvozUPQ/uRHbHwvfyKHwEt5xFM=", @@ -8338,7 +9988,7 @@ "type": "indirect" } }, - "nixpkgs_22": { + "nixpkgs_12": { "locked": { "lastModified": 1647297614, "narHash": "sha256-ulGq3W5XsrBMU/u5k9d4oPy65pQTkunR4HKKtTq0RwY=", @@ -8354,7 +10004,7 @@ "type": "github" } }, - "nixpkgs_23": { + "nixpkgs_13": { "flake": false, "locked": { "lastModified": 1645493675, @@ -8371,29 +10021,13 @@ "type": "github" } }, - "nixpkgs_24": { - "locked": { - "lastModified": 1652885393, - "narHash": "sha256-YIgvvlk4iQ1Hi7KD9o5gsojc+ApB+jiH1d5stK8uXiw=", - "owner": "nixos", - "repo": "nixpkgs", - "rev": "48037fd90426e44e4bf03e6479e88a11453b9b66", - "type": "github" - }, - "original": { - "owner": "nixos", - "ref": "nixos-unstable", - "repo": "nixpkgs", - "type": "github" - } - }, - "nixpkgs_25": { + "nixpkgs_14": { "locked": { - "lastModified": 1653117584, - "narHash": "sha256-5uUrHeHBIaySBTrRExcCoW8fBBYVSDjDYDU5A6iOl+k=", + "lastModified": 1657292830, + "narHash": "sha256-ldfVSTveWceDCmW6gf3B4kR6vwmz/XS80y5wsLLHFJU=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "f4dfed73ee886b115a99e5b85fdfbeb683290d83", + "rev": "334ec8b503c3981e37a04b817a70e8d026ea9e84", "type": "github" }, "original": { @@ -8401,7 +10035,7 @@ "type": "indirect" } }, - "nixpkgs_26": { + "nixpkgs_15": { "locked": { "lastModified": 1632864508, "narHash": "sha256-d127FIvGR41XbVRDPVvozUPQ/uRHbHwvfyKHwEt5xFM=", @@ -8416,7 +10050,7 @@ "type": "indirect" } }, - "nixpkgs_27": { + "nixpkgs_16": { "locked": { "lastModified": 1647297614, "narHash": "sha256-ulGq3W5XsrBMU/u5k9d4oPy65pQTkunR4HKKtTq0RwY=", @@ -8432,7 +10066,7 @@ "type": "github" } }, - "nixpkgs_28": { + "nixpkgs_17": { "flake": false, "locked": { "lastModified": 1645493675, @@ -8449,44 +10083,75 @@ "type": "github" } }, - "nixpkgs_29": { + "nixpkgs_18": { + "locked": { + "lastModified": 1632864508, + "narHash": "sha256-d127FIvGR41XbVRDPVvozUPQ/uRHbHwvfyKHwEt5xFM=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "82891b5e2c2359d7e58d08849e4c89511ab94234", + "type": "github" + }, + "original": { + "id": "nixpkgs", + "ref": "nixos-21.05-small", + "type": "indirect" + } + }, + "nixpkgs_19": { "locked": { - "lastModified": 1652885393, - "narHash": "sha256-YIgvvlk4iQ1Hi7KD9o5gsojc+ApB+jiH1d5stK8uXiw=", - "owner": "nixos", + "lastModified": 1647297614, + "narHash": "sha256-ulGq3W5XsrBMU/u5k9d4oPy65pQTkunR4HKKtTq0RwY=", + "owner": "NixOS", "repo": "nixpkgs", - "rev": "48037fd90426e44e4bf03e6479e88a11453b9b66", + "rev": "73ad5f9e147c0d2a2061f1d4bd91e05078dc0b58", "type": "github" }, "original": { - "owner": "nixos", + "owner": "NixOS", "ref": "nixos-unstable", "repo": "nixpkgs", "type": "github" } }, - "nixpkgs_3": { + "nixpkgs_2": { "locked": { - "lastModified": 1632864508, - "narHash": "sha256-d127FIvGR41XbVRDPVvozUPQ/uRHbHwvfyKHwEt5xFM=", + "lastModified": 1657292830, + "narHash": "sha256-ldfVSTveWceDCmW6gf3B4kR6vwmz/XS80y5wsLLHFJU=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "82891b5e2c2359d7e58d08849e4c89511ab94234", + "rev": "334ec8b503c3981e37a04b817a70e8d026ea9e84", "type": "github" }, "original": { "id": "nixpkgs", - "ref": "nixos-21.05-small", "type": "indirect" } }, - "nixpkgs_30": { + "nixpkgs_20": { + "flake": false, + "locked": { + "lastModified": 1645493675, + "narHash": "sha256-9xundbZQbhFodsQRh6QMN1GeSXfo3y/5NL0CZcJULz0=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "74b10859829153d5c5d50f7c77b86763759e8654", + "type": "github" + }, + "original": { + "owner": "NixOS", + "ref": "nixpkgs-unstable", + "repo": "nixpkgs", + "type": "github" + } + }, + "nixpkgs_21": { "locked": { - "lastModified": 1653117584, - "narHash": "sha256-5uUrHeHBIaySBTrRExcCoW8fBBYVSDjDYDU5A6iOl+k=", + "lastModified": 1657292830, + "narHash": "sha256-ldfVSTveWceDCmW6gf3B4kR6vwmz/XS80y5wsLLHFJU=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "f4dfed73ee886b115a99e5b85fdfbeb683290d83", + "rev": "334ec8b503c3981e37a04b817a70e8d026ea9e84", "type": "github" }, "original": { @@ -8494,7 +10159,7 @@ "type": "indirect" } }, - "nixpkgs_31": { + "nixpkgs_22": { "locked": { "lastModified": 1632864508, "narHash": "sha256-d127FIvGR41XbVRDPVvozUPQ/uRHbHwvfyKHwEt5xFM=", @@ -8509,7 +10174,7 @@ "type": "indirect" } }, - "nixpkgs_32": { + "nixpkgs_23": { "locked": { "lastModified": 1647297614, "narHash": "sha256-ulGq3W5XsrBMU/u5k9d4oPy65pQTkunR4HKKtTq0RwY=", @@ -8525,7 +10190,7 @@ "type": "github" } }, - "nixpkgs_33": { + "nixpkgs_24": { "flake": false, "locked": { "lastModified": 1645493675, @@ -8542,29 +10207,13 @@ "type": "github" } }, - "nixpkgs_34": { - "locked": { - "lastModified": 1652885393, - "narHash": "sha256-YIgvvlk4iQ1Hi7KD9o5gsojc+ApB+jiH1d5stK8uXiw=", - "owner": "nixos", - "repo": "nixpkgs", - "rev": "48037fd90426e44e4bf03e6479e88a11453b9b66", - "type": "github" - }, - "original": { - "owner": "nixos", - "ref": "nixos-unstable", - "repo": "nixpkgs", - "type": "github" - } - }, - "nixpkgs_35": { + "nixpkgs_25": { "locked": { - "lastModified": 1653117584, - "narHash": "sha256-5uUrHeHBIaySBTrRExcCoW8fBBYVSDjDYDU5A6iOl+k=", + "lastModified": 1657292830, + "narHash": "sha256-ldfVSTveWceDCmW6gf3B4kR6vwmz/XS80y5wsLLHFJU=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "f4dfed73ee886b115a99e5b85fdfbeb683290d83", + "rev": "334ec8b503c3981e37a04b817a70e8d026ea9e84", "type": "github" }, "original": { @@ -8572,7 +10221,7 @@ "type": "indirect" } }, - "nixpkgs_36": { + "nixpkgs_26": { "locked": { "lastModified": 1632864508, "narHash": "sha256-d127FIvGR41XbVRDPVvozUPQ/uRHbHwvfyKHwEt5xFM=", @@ -8587,7 +10236,7 @@ "type": "indirect" } }, - "nixpkgs_37": { + "nixpkgs_27": { "locked": { "lastModified": 1647297614, "narHash": "sha256-ulGq3W5XsrBMU/u5k9d4oPy65pQTkunR4HKKtTq0RwY=", @@ -8603,7 +10252,7 @@ "type": "github" } }, - "nixpkgs_38": { + "nixpkgs_28": { "flake": false, "locked": { "lastModified": 1645493675, @@ -8620,53 +10269,36 @@ "type": "github" } }, - "nixpkgs_39": { - "locked": { - "lastModified": 1652885393, - "narHash": "sha256-YIgvvlk4iQ1Hi7KD9o5gsojc+ApB+jiH1d5stK8uXiw=", - "owner": "nixos", - "repo": "nixpkgs", - "rev": "48037fd90426e44e4bf03e6479e88a11453b9b66", - "type": "github" - }, - "original": { - "owner": "nixos", - "ref": "nixos-unstable", - "repo": "nixpkgs", - "type": "github" - } - }, - "nixpkgs_4": { + "nixpkgs_29": { "locked": { - "lastModified": 1647297614, - "narHash": "sha256-ulGq3W5XsrBMU/u5k9d4oPy65pQTkunR4HKKtTq0RwY=", + "lastModified": 1657292830, + "narHash": "sha256-ldfVSTveWceDCmW6gf3B4kR6vwmz/XS80y5wsLLHFJU=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "73ad5f9e147c0d2a2061f1d4bd91e05078dc0b58", + "rev": "334ec8b503c3981e37a04b817a70e8d026ea9e84", "type": "github" }, "original": { - "owner": "NixOS", - "ref": "nixos-unstable", - "repo": "nixpkgs", - "type": "github" + "id": "nixpkgs", + "type": "indirect" } }, - "nixpkgs_40": { + "nixpkgs_3": { "locked": { - "lastModified": 1653117584, - "narHash": "sha256-5uUrHeHBIaySBTrRExcCoW8fBBYVSDjDYDU5A6iOl+k=", + "lastModified": 1632864508, + "narHash": "sha256-d127FIvGR41XbVRDPVvozUPQ/uRHbHwvfyKHwEt5xFM=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "f4dfed73ee886b115a99e5b85fdfbeb683290d83", + "rev": "82891b5e2c2359d7e58d08849e4c89511ab94234", "type": "github" }, "original": { "id": "nixpkgs", + "ref": "nixos-21.05-small", "type": "indirect" } }, - "nixpkgs_41": { + "nixpkgs_30": { "locked": { "lastModified": 1632864508, "narHash": "sha256-d127FIvGR41XbVRDPVvozUPQ/uRHbHwvfyKHwEt5xFM=", @@ -8681,7 +10313,7 @@ "type": "indirect" } }, - "nixpkgs_42": { + "nixpkgs_31": { "locked": { "lastModified": 1647297614, "narHash": "sha256-ulGq3W5XsrBMU/u5k9d4oPy65pQTkunR4HKKtTq0RwY=", @@ -8697,7 +10329,7 @@ "type": "github" } }, - "nixpkgs_43": { + "nixpkgs_32": { "flake": false, "locked": { "lastModified": 1645493675, @@ -8714,61 +10346,89 @@ "type": "github" } }, - "nixpkgs_44": { + "nixpkgs_33": { "locked": { - "lastModified": 1650882267, - "narHash": "sha256-BFKiz8srATQIBuFEN2HgS2EHisK29EjZ/HV34wSr2lU=", - "owner": "nixos", + "lastModified": 1657292830, + "narHash": "sha256-ldfVSTveWceDCmW6gf3B4kR6vwmz/XS80y5wsLLHFJU=", + "owner": "NixOS", "repo": "nixpkgs", - "rev": "2ea2f7b6d0cb7ce0712f2aa80303cda08deb0de2", + "rev": "334ec8b503c3981e37a04b817a70e8d026ea9e84", "type": "github" }, "original": { - "owner": "nixos", - "repo": "nixpkgs", - "rev": "2ea2f7b6d0cb7ce0712f2aa80303cda08deb0de2", - "type": "github" + "id": "nixpkgs", + "type": "indirect" } }, - "nixpkgs_45": { + "nixpkgs_34": { "locked": { - "lastModified": 1647350163, - "narHash": "sha256-OcMI+PFEHTONthXuEQNddt16Ml7qGvanL3x8QOl2Aao=", - "owner": "nixos", + "lastModified": 1657292830, + "narHash": "sha256-ldfVSTveWceDCmW6gf3B4kR6vwmz/XS80y5wsLLHFJU=", + "owner": "NixOS", "repo": "nixpkgs", - "rev": "3eb07eeafb52bcbf02ce800f032f18d666a9498d", + "rev": "334ec8b503c3981e37a04b817a70e8d026ea9e84", "type": "github" }, "original": { - "owner": "nixos", - "repo": "nixpkgs", - "rev": "3eb07eeafb52bcbf02ce800f032f18d666a9498d", - "type": "github" + "id": "nixpkgs", + "type": "indirect" } }, - "nixpkgs_46": { + "nixpkgs_35": { "locked": { - "lastModified": 1649456639, - "narHash": "sha256-rZCjaEAZgOtT9kYTBigksof64SqKAXOuoHhlzHvfl0E=", - "owner": "nixos", + "lastModified": 1632864508, + "narHash": "sha256-d127FIvGR41XbVRDPVvozUPQ/uRHbHwvfyKHwEt5xFM=", + "owner": "NixOS", "repo": "nixpkgs", - "rev": "c48167590e3258daac6ab12a41bc2b7341e9b2ec", + "rev": "82891b5e2c2359d7e58d08849e4c89511ab94234", "type": "github" }, "original": { - "owner": "nixos", - "repo": "nixpkgs", - "rev": "c48167590e3258daac6ab12a41bc2b7341e9b2ec", - "type": "github" + "id": "nixpkgs", + "ref": "nixos-21.05-small", + "type": "indirect" } }, - "nixpkgs_47": { + "nixpkgs_36": { "locked": { - "lastModified": 1648219316, - "narHash": "sha256-Ctij+dOi0ZZIfX5eMhgwugfvB+WZSrvVNAyAuANOsnQ=", + "lastModified": 1647297614, + "narHash": "sha256-ulGq3W5XsrBMU/u5k9d4oPy65pQTkunR4HKKtTq0RwY=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "30d3d79b7d3607d56546dd2a6b49e156ba0ec634", + "rev": "73ad5f9e147c0d2a2061f1d4bd91e05078dc0b58", + "type": "github" + }, + "original": { + "owner": "NixOS", + "ref": "nixos-unstable", + "repo": "nixpkgs", + "type": "github" + } + }, + "nixpkgs_37": { + "flake": false, + "locked": { + "lastModified": 1645493675, + "narHash": "sha256-9xundbZQbhFodsQRh6QMN1GeSXfo3y/5NL0CZcJULz0=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "74b10859829153d5c5d50f7c77b86763759e8654", + "type": "github" + }, + "original": { + "owner": "NixOS", + "ref": "nixpkgs-unstable", + "repo": "nixpkgs", + "type": "github" + } + }, + "nixpkgs_38": { + "locked": { + "lastModified": 1657292830, + "narHash": "sha256-ldfVSTveWceDCmW6gf3B4kR6vwmz/XS80y5wsLLHFJU=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "334ec8b503c3981e37a04b817a70e8d026ea9e84", "type": "github" }, "original": { @@ -8776,7 +10436,22 @@ "type": "indirect" } }, - "nixpkgs_48": { + "nixpkgs_39": { + "locked": { + "lastModified": 1632864508, + "narHash": "sha256-d127FIvGR41XbVRDPVvozUPQ/uRHbHwvfyKHwEt5xFM=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "82891b5e2c2359d7e58d08849e4c89511ab94234", + "type": "github" + }, + "original": { + "id": "nixpkgs", + "ref": "nixos-21.05-small", + "type": "indirect" + } + }, + "nixpkgs_4": { "locked": { "lastModified": 1647297614, "narHash": "sha256-ulGq3W5XsrBMU/u5k9d4oPy65pQTkunR4HKKtTq0RwY=", @@ -8792,24 +10467,23 @@ "type": "github" } }, - "nixpkgs_49": { - "flake": false, + "nixpkgs_40": { "locked": { - "lastModified": 1628785280, - "narHash": "sha256-2B5eMrEr6O8ff2aQNeVxTB+9WrGE80OB4+oM6T7fOcc=", + "lastModified": 1647297614, + "narHash": "sha256-ulGq3W5XsrBMU/u5k9d4oPy65pQTkunR4HKKtTq0RwY=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "6525bbc06a39f26750ad8ee0d40000ddfdc24acb", + "rev": "73ad5f9e147c0d2a2061f1d4bd91e05078dc0b58", "type": "github" }, "original": { "owner": "NixOS", - "ref": "nixpkgs-unstable", + "ref": "nixos-unstable", "repo": "nixpkgs", "type": "github" } }, - "nixpkgs_5": { + "nixpkgs_41": { "flake": false, "locked": { "lastModified": 1645493675, @@ -8826,29 +10500,13 @@ "type": "github" } }, - "nixpkgs_6": { - "locked": { - "lastModified": 1652885393, - "narHash": "sha256-YIgvvlk4iQ1Hi7KD9o5gsojc+ApB+jiH1d5stK8uXiw=", - "owner": "nixos", - "repo": "nixpkgs", - "rev": "48037fd90426e44e4bf03e6479e88a11453b9b66", - "type": "github" - }, - "original": { - "owner": "nixos", - "ref": "nixos-unstable", - "repo": "nixpkgs", - "type": "github" - } - }, - "nixpkgs_7": { + "nixpkgs_42": { "locked": { - "lastModified": 1653117584, - "narHash": "sha256-5uUrHeHBIaySBTrRExcCoW8fBBYVSDjDYDU5A6iOl+k=", + "lastModified": 1657292830, + "narHash": "sha256-ldfVSTveWceDCmW6gf3B4kR6vwmz/XS80y5wsLLHFJU=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "f4dfed73ee886b115a99e5b85fdfbeb683290d83", + "rev": "334ec8b503c3981e37a04b817a70e8d026ea9e84", "type": "github" }, "original": { @@ -8856,7 +10514,7 @@ "type": "indirect" } }, - "nixpkgs_8": { + "nixpkgs_43": { "locked": { "lastModified": 1632864508, "narHash": "sha256-d127FIvGR41XbVRDPVvozUPQ/uRHbHwvfyKHwEt5xFM=", @@ -8871,7 +10529,7 @@ "type": "indirect" } }, - "nixpkgs_9": { + "nixpkgs_44": { "locked": { "lastModified": 1647297614, "narHash": "sha256-ulGq3W5XsrBMU/u5k9d4oPy65pQTkunR4HKKtTq0RwY=", @@ -8887,663 +10545,1519 @@ "type": "github" } }, - "old-ghc-nix": { + "nixpkgs_45": { "flake": false, "locked": { - "lastModified": 1631092763, - "narHash": "sha256-sIKgO+z7tj4lw3u6oBZxqIhDrzSkvpHtv0Kki+lh9Fg=", - "owner": "angerman", - "repo": "old-ghc-nix", - "rev": "af48a7a7353e418119b6dfe3cd1463a657f342b8", + "lastModified": 1645493675, + "narHash": "sha256-9xundbZQbhFodsQRh6QMN1GeSXfo3y/5NL0CZcJULz0=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "74b10859829153d5c5d50f7c77b86763759e8654", "type": "github" }, "original": { - "owner": "angerman", - "ref": "master", - "repo": "old-ghc-nix", + "owner": "NixOS", + "ref": "nixpkgs-unstable", + "repo": "nixpkgs", "type": "github" } }, - "old-ghc-nix_10": { - "flake": false, + "nixpkgs_46": { "locked": { - "lastModified": 1631092763, - "narHash": "sha256-sIKgO+z7tj4lw3u6oBZxqIhDrzSkvpHtv0Kki+lh9Fg=", - "owner": "angerman", - "repo": "old-ghc-nix", - "rev": "af48a7a7353e418119b6dfe3cd1463a657f342b8", + "lastModified": 1657292830, + "narHash": "sha256-ldfVSTveWceDCmW6gf3B4kR6vwmz/XS80y5wsLLHFJU=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "334ec8b503c3981e37a04b817a70e8d026ea9e84", "type": "github" }, "original": { - "owner": "angerman", - "ref": "master", - "repo": "old-ghc-nix", - "type": "github" + "id": "nixpkgs", + "type": "indirect" } }, - "old-ghc-nix_2": { - "flake": false, + "nixpkgs_47": { "locked": { - "lastModified": 1631092763, - "narHash": "sha256-sIKgO+z7tj4lw3u6oBZxqIhDrzSkvpHtv0Kki+lh9Fg=", - "owner": "angerman", - "repo": "old-ghc-nix", - "rev": "af48a7a7353e418119b6dfe3cd1463a657f342b8", + "lastModified": 1632864508, + "narHash": "sha256-d127FIvGR41XbVRDPVvozUPQ/uRHbHwvfyKHwEt5xFM=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "82891b5e2c2359d7e58d08849e4c89511ab94234", "type": "github" }, "original": { - "owner": "angerman", - "ref": "master", - "repo": "old-ghc-nix", - "type": "github" + "id": "nixpkgs", + "ref": "nixos-21.05-small", + "type": "indirect" } }, - "old-ghc-nix_3": { - "flake": false, + "nixpkgs_48": { "locked": { - "lastModified": 1631092763, - "narHash": "sha256-sIKgO+z7tj4lw3u6oBZxqIhDrzSkvpHtv0Kki+lh9Fg=", - "owner": "angerman", - "repo": "old-ghc-nix", - "rev": "af48a7a7353e418119b6dfe3cd1463a657f342b8", + "lastModified": 1647297614, + "narHash": "sha256-ulGq3W5XsrBMU/u5k9d4oPy65pQTkunR4HKKtTq0RwY=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "73ad5f9e147c0d2a2061f1d4bd91e05078dc0b58", "type": "github" }, "original": { - "owner": "angerman", - "ref": "master", - "repo": "old-ghc-nix", + "owner": "NixOS", + "ref": "nixos-unstable", + "repo": "nixpkgs", "type": "github" } }, - "old-ghc-nix_4": { + "nixpkgs_49": { "flake": false, "locked": { - "lastModified": 1631092763, - "narHash": "sha256-sIKgO+z7tj4lw3u6oBZxqIhDrzSkvpHtv0Kki+lh9Fg=", - "owner": "angerman", - "repo": "old-ghc-nix", - "rev": "af48a7a7353e418119b6dfe3cd1463a657f342b8", + "lastModified": 1645493675, + "narHash": "sha256-9xundbZQbhFodsQRh6QMN1GeSXfo3y/5NL0CZcJULz0=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "74b10859829153d5c5d50f7c77b86763759e8654", "type": "github" }, "original": { - "owner": "angerman", - "ref": "master", - "repo": "old-ghc-nix", + "owner": "NixOS", + "ref": "nixpkgs-unstable", + "repo": "nixpkgs", "type": "github" } }, - "old-ghc-nix_5": { + "nixpkgs_5": { "flake": false, "locked": { - "lastModified": 1631092763, - "narHash": "sha256-sIKgO+z7tj4lw3u6oBZxqIhDrzSkvpHtv0Kki+lh9Fg=", - "owner": "angerman", - "repo": "old-ghc-nix", - "rev": "af48a7a7353e418119b6dfe3cd1463a657f342b8", + "lastModified": 1645493675, + "narHash": "sha256-9xundbZQbhFodsQRh6QMN1GeSXfo3y/5NL0CZcJULz0=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "74b10859829153d5c5d50f7c77b86763759e8654", "type": "github" }, "original": { - "owner": "angerman", - "ref": "master", - "repo": "old-ghc-nix", + "owner": "NixOS", + "ref": "nixpkgs-unstable", + "repo": "nixpkgs", "type": "github" } }, - "old-ghc-nix_6": { - "flake": false, + "nixpkgs_50": { "locked": { - "lastModified": 1631092763, - "narHash": "sha256-sIKgO+z7tj4lw3u6oBZxqIhDrzSkvpHtv0Kki+lh9Fg=", - "owner": "angerman", - "repo": "old-ghc-nix", - "rev": "af48a7a7353e418119b6dfe3cd1463a657f342b8", + "lastModified": 1632864508, + "narHash": "sha256-d127FIvGR41XbVRDPVvozUPQ/uRHbHwvfyKHwEt5xFM=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "82891b5e2c2359d7e58d08849e4c89511ab94234", "type": "github" }, "original": { - "owner": "angerman", - "ref": "master", - "repo": "old-ghc-nix", - "type": "github" + "id": "nixpkgs", + "ref": "nixos-21.05-small", + "type": "indirect" } }, - "old-ghc-nix_7": { - "flake": false, + "nixpkgs_51": { "locked": { - "lastModified": 1631092763, - "narHash": "sha256-sIKgO+z7tj4lw3u6oBZxqIhDrzSkvpHtv0Kki+lh9Fg=", - "owner": "angerman", - "repo": "old-ghc-nix", - "rev": "af48a7a7353e418119b6dfe3cd1463a657f342b8", + "lastModified": 1647297614, + "narHash": "sha256-ulGq3W5XsrBMU/u5k9d4oPy65pQTkunR4HKKtTq0RwY=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "73ad5f9e147c0d2a2061f1d4bd91e05078dc0b58", "type": "github" }, "original": { - "owner": "angerman", - "ref": "master", - "repo": "old-ghc-nix", + "owner": "NixOS", + "ref": "nixos-unstable", + "repo": "nixpkgs", "type": "github" } }, - "old-ghc-nix_8": { + "nixpkgs_52": { "flake": false, "locked": { - "lastModified": 1631092763, - "narHash": "sha256-sIKgO+z7tj4lw3u6oBZxqIhDrzSkvpHtv0Kki+lh9Fg=", - "owner": "angerman", - "repo": "old-ghc-nix", - "rev": "af48a7a7353e418119b6dfe3cd1463a657f342b8", + "lastModified": 1645493675, + "narHash": "sha256-9xundbZQbhFodsQRh6QMN1GeSXfo3y/5NL0CZcJULz0=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "74b10859829153d5c5d50f7c77b86763759e8654", "type": "github" }, "original": { - "owner": "angerman", - "ref": "master", - "repo": "old-ghc-nix", + "owner": "NixOS", + "ref": "nixpkgs-unstable", + "repo": "nixpkgs", "type": "github" } }, - "old-ghc-nix_9": { - "flake": false, + "nixpkgs_53": { "locked": { - "lastModified": 1631092763, - "narHash": "sha256-sIKgO+z7tj4lw3u6oBZxqIhDrzSkvpHtv0Kki+lh9Fg=", - "owner": "angerman", - "repo": "old-ghc-nix", - "rev": "af48a7a7353e418119b6dfe3cd1463a657f342b8", + "lastModified": 1657292830, + "narHash": "sha256-ldfVSTveWceDCmW6gf3B4kR6vwmz/XS80y5wsLLHFJU=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "334ec8b503c3981e37a04b817a70e8d026ea9e84", "type": "github" }, "original": { - "owner": "angerman", - "ref": "master", - "repo": "old-ghc-nix", - "type": "github" + "id": "nixpkgs", + "type": "indirect" + } + }, + "nixpkgs_54": { + "locked": { + "lastModified": 1632864508, + "narHash": "sha256-d127FIvGR41XbVRDPVvozUPQ/uRHbHwvfyKHwEt5xFM=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "82891b5e2c2359d7e58d08849e4c89511ab94234", + "type": "github" + }, + "original": { + "id": "nixpkgs", + "ref": "nixos-21.05-small", + "type": "indirect" + } + }, + "nixpkgs_55": { + "locked": { + "lastModified": 1647297614, + "narHash": "sha256-ulGq3W5XsrBMU/u5k9d4oPy65pQTkunR4HKKtTq0RwY=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "73ad5f9e147c0d2a2061f1d4bd91e05078dc0b58", + "type": "github" + }, + "original": { + "owner": "NixOS", + "ref": "nixos-unstable", + "repo": "nixpkgs", + "type": "github" + } + }, + "nixpkgs_56": { + "flake": false, + "locked": { + "lastModified": 1645493675, + "narHash": "sha256-9xundbZQbhFodsQRh6QMN1GeSXfo3y/5NL0CZcJULz0=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "74b10859829153d5c5d50f7c77b86763759e8654", + "type": "github" + }, + "original": { + "owner": "NixOS", + "ref": "nixpkgs-unstable", + "repo": "nixpkgs", + "type": "github" + } + }, + "nixpkgs_57": { + "locked": { + "lastModified": 1657292830, + "narHash": "sha256-ldfVSTveWceDCmW6gf3B4kR6vwmz/XS80y5wsLLHFJU=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "334ec8b503c3981e37a04b817a70e8d026ea9e84", + "type": "github" + }, + "original": { + "id": "nixpkgs", + "type": "indirect" + } + }, + "nixpkgs_58": { + "locked": { + "lastModified": 1632864508, + "narHash": "sha256-d127FIvGR41XbVRDPVvozUPQ/uRHbHwvfyKHwEt5xFM=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "82891b5e2c2359d7e58d08849e4c89511ab94234", + "type": "github" + }, + "original": { + "id": "nixpkgs", + "ref": "nixos-21.05-small", + "type": "indirect" + } + }, + "nixpkgs_59": { + "locked": { + "lastModified": 1647297614, + "narHash": "sha256-ulGq3W5XsrBMU/u5k9d4oPy65pQTkunR4HKKtTq0RwY=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "73ad5f9e147c0d2a2061f1d4bd91e05078dc0b58", + "type": "github" + }, + "original": { + "owner": "NixOS", + "ref": "nixos-unstable", + "repo": "nixpkgs", + "type": "github" + } + }, + "nixpkgs_6": { + "locked": { + "lastModified": 1657292830, + "narHash": "sha256-ldfVSTveWceDCmW6gf3B4kR6vwmz/XS80y5wsLLHFJU=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "334ec8b503c3981e37a04b817a70e8d026ea9e84", + "type": "github" + }, + "original": { + "id": "nixpkgs", + "type": "indirect" + } + }, + "nixpkgs_60": { + "flake": false, + "locked": { + "lastModified": 1645493675, + "narHash": "sha256-9xundbZQbhFodsQRh6QMN1GeSXfo3y/5NL0CZcJULz0=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "74b10859829153d5c5d50f7c77b86763759e8654", + "type": "github" + }, + "original": { + "owner": "NixOS", + "ref": "nixpkgs-unstable", + "repo": "nixpkgs", + "type": "github" + } + }, + "nixpkgs_7": { + "locked": { + "lastModified": 1632864508, + "narHash": "sha256-d127FIvGR41XbVRDPVvozUPQ/uRHbHwvfyKHwEt5xFM=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "82891b5e2c2359d7e58d08849e4c89511ab94234", + "type": "github" + }, + "original": { + "id": "nixpkgs", + "ref": "nixos-21.05-small", + "type": "indirect" } }, - "pandoc-link-context": { + "nixpkgs_8": { + "locked": { + "lastModified": 1647297614, + "narHash": "sha256-ulGq3W5XsrBMU/u5k9d4oPy65pQTkunR4HKKtTq0RwY=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "73ad5f9e147c0d2a2061f1d4bd91e05078dc0b58", + "type": "github" + }, + "original": { + "owner": "NixOS", + "ref": "nixos-unstable", + "repo": "nixpkgs", + "type": "github" + } + }, + "nixpkgs_9": { + "flake": false, + "locked": { + "lastModified": 1645493675, + "narHash": "sha256-9xundbZQbhFodsQRh6QMN1GeSXfo3y/5NL0CZcJULz0=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "74b10859829153d5c5d50f7c77b86763759e8654", + "type": "github" + }, + "original": { + "owner": "NixOS", + "ref": "nixpkgs-unstable", + "repo": "nixpkgs", + "type": "github" + } + }, + "old-ghc-nix": { + "flake": false, + "locked": { + "lastModified": 1631092763, + "narHash": "sha256-sIKgO+z7tj4lw3u6oBZxqIhDrzSkvpHtv0Kki+lh9Fg=", + "owner": "angerman", + "repo": "old-ghc-nix", + "rev": "af48a7a7353e418119b6dfe3cd1463a657f342b8", + "type": "github" + }, + "original": { + "owner": "angerman", + "ref": "master", + "repo": "old-ghc-nix", + "type": "github" + } + }, + "old-ghc-nix_10": { + "flake": false, + "locked": { + "lastModified": 1631092763, + "narHash": "sha256-sIKgO+z7tj4lw3u6oBZxqIhDrzSkvpHtv0Kki+lh9Fg=", + "owner": "angerman", + "repo": "old-ghc-nix", + "rev": "af48a7a7353e418119b6dfe3cd1463a657f342b8", + "type": "github" + }, + "original": { + "owner": "angerman", + "ref": "master", + "repo": "old-ghc-nix", + "type": "github" + } + }, + "old-ghc-nix_11": { "flake": false, "locked": { - "lastModified": 1653170888, - "narHash": "sha256-bA/Oj2pt3H2b4lqWqVBYo3Qhvhd01r4vM39+vLuPMtA=", - "owner": "srid", - "repo": "pandoc-link-context", - "rev": "c3a3de34b291b2bfec04387af65e0cc0822373c5", + "lastModified": 1631092763, + "narHash": "sha256-sIKgO+z7tj4lw3u6oBZxqIhDrzSkvpHtv0Kki+lh9Fg=", + "owner": "angerman", + "repo": "old-ghc-nix", + "rev": "af48a7a7353e418119b6dfe3cd1463a657f342b8", "type": "github" }, "original": { - "owner": "srid", + "owner": "angerman", "ref": "master", - "repo": "pandoc-link-context", + "repo": "old-ghc-nix", "type": "github" } }, - "pandoc-link-context_2": { + "old-ghc-nix_12": { "flake": false, "locked": { - "lastModified": 1653170888, - "narHash": "sha256-bA/Oj2pt3H2b4lqWqVBYo3Qhvhd01r4vM39+vLuPMtA=", - "owner": "srid", - "repo": "pandoc-link-context", - "rev": "c3a3de34b291b2bfec04387af65e0cc0822373c5", + "lastModified": 1631092763, + "narHash": "sha256-sIKgO+z7tj4lw3u6oBZxqIhDrzSkvpHtv0Kki+lh9Fg=", + "owner": "angerman", + "repo": "old-ghc-nix", + "rev": "af48a7a7353e418119b6dfe3cd1463a657f342b8", "type": "github" }, "original": { - "owner": "srid", + "owner": "angerman", "ref": "master", - "repo": "pandoc-link-context", + "repo": "old-ghc-nix", "type": "github" } }, - "pandoc-link-context_3": { + "old-ghc-nix_13": { "flake": false, "locked": { - "lastModified": 1653170888, - "narHash": "sha256-bA/Oj2pt3H2b4lqWqVBYo3Qhvhd01r4vM39+vLuPMtA=", - "owner": "srid", - "repo": "pandoc-link-context", - "rev": "c3a3de34b291b2bfec04387af65e0cc0822373c5", + "lastModified": 1631092763, + "narHash": "sha256-sIKgO+z7tj4lw3u6oBZxqIhDrzSkvpHtv0Kki+lh9Fg=", + "owner": "angerman", + "repo": "old-ghc-nix", + "rev": "af48a7a7353e418119b6dfe3cd1463a657f342b8", "type": "github" }, "original": { - "owner": "srid", + "owner": "angerman", "ref": "master", - "repo": "pandoc-link-context", + "repo": "old-ghc-nix", "type": "github" } }, - "pandoc-link-context_4": { + "old-ghc-nix_14": { "flake": false, "locked": { - "lastModified": 1653170888, - "narHash": "sha256-bA/Oj2pt3H2b4lqWqVBYo3Qhvhd01r4vM39+vLuPMtA=", - "owner": "srid", - "repo": "pandoc-link-context", - "rev": "c3a3de34b291b2bfec04387af65e0cc0822373c5", + "lastModified": 1631092763, + "narHash": "sha256-sIKgO+z7tj4lw3u6oBZxqIhDrzSkvpHtv0Kki+lh9Fg=", + "owner": "angerman", + "repo": "old-ghc-nix", + "rev": "af48a7a7353e418119b6dfe3cd1463a657f342b8", "type": "github" }, "original": { - "owner": "srid", + "owner": "angerman", "ref": "master", - "repo": "pandoc-link-context", + "repo": "old-ghc-nix", "type": "github" } }, - "pandoc-link-context_5": { + "old-ghc-nix_15": { "flake": false, "locked": { - "lastModified": 1653170888, - "narHash": "sha256-bA/Oj2pt3H2b4lqWqVBYo3Qhvhd01r4vM39+vLuPMtA=", - "owner": "srid", - "repo": "pandoc-link-context", - "rev": "c3a3de34b291b2bfec04387af65e0cc0822373c5", + "lastModified": 1631092763, + "narHash": "sha256-sIKgO+z7tj4lw3u6oBZxqIhDrzSkvpHtv0Kki+lh9Fg=", + "owner": "angerman", + "repo": "old-ghc-nix", + "rev": "af48a7a7353e418119b6dfe3cd1463a657f342b8", "type": "github" }, "original": { - "owner": "srid", + "owner": "angerman", "ref": "master", - "repo": "pandoc-link-context", + "repo": "old-ghc-nix", "type": "github" } }, - "pandoc-link-context_6": { + "old-ghc-nix_2": { "flake": false, "locked": { - "lastModified": 1653170888, - "narHash": "sha256-bA/Oj2pt3H2b4lqWqVBYo3Qhvhd01r4vM39+vLuPMtA=", - "owner": "srid", - "repo": "pandoc-link-context", - "rev": "c3a3de34b291b2bfec04387af65e0cc0822373c5", + "lastModified": 1631092763, + "narHash": "sha256-sIKgO+z7tj4lw3u6oBZxqIhDrzSkvpHtv0Kki+lh9Fg=", + "owner": "angerman", + "repo": "old-ghc-nix", + "rev": "af48a7a7353e418119b6dfe3cd1463a657f342b8", "type": "github" }, "original": { - "owner": "srid", + "owner": "angerman", "ref": "master", - "repo": "pandoc-link-context", + "repo": "old-ghc-nix", "type": "github" } }, - "pandoc-link-context_7": { + "old-ghc-nix_3": { "flake": false, "locked": { - "lastModified": 1653170888, - "narHash": "sha256-bA/Oj2pt3H2b4lqWqVBYo3Qhvhd01r4vM39+vLuPMtA=", - "owner": "srid", - "repo": "pandoc-link-context", - "rev": "c3a3de34b291b2bfec04387af65e0cc0822373c5", + "lastModified": 1631092763, + "narHash": "sha256-sIKgO+z7tj4lw3u6oBZxqIhDrzSkvpHtv0Kki+lh9Fg=", + "owner": "angerman", + "repo": "old-ghc-nix", + "rev": "af48a7a7353e418119b6dfe3cd1463a657f342b8", "type": "github" }, "original": { - "owner": "srid", + "owner": "angerman", "ref": "master", - "repo": "pandoc-link-context", + "repo": "old-ghc-nix", "type": "github" } }, - "pandoc-link-context_8": { + "old-ghc-nix_4": { "flake": false, "locked": { - "lastModified": 1653170888, - "narHash": "sha256-bA/Oj2pt3H2b4lqWqVBYo3Qhvhd01r4vM39+vLuPMtA=", - "owner": "srid", - "repo": "pandoc-link-context", - "rev": "c3a3de34b291b2bfec04387af65e0cc0822373c5", + "lastModified": 1631092763, + "narHash": "sha256-sIKgO+z7tj4lw3u6oBZxqIhDrzSkvpHtv0Kki+lh9Fg=", + "owner": "angerman", + "repo": "old-ghc-nix", + "rev": "af48a7a7353e418119b6dfe3cd1463a657f342b8", "type": "github" }, "original": { - "owner": "srid", + "owner": "angerman", "ref": "master", - "repo": "pandoc-link-context", + "repo": "old-ghc-nix", "type": "github" } }, - "pandoc-link-context_9": { + "old-ghc-nix_5": { "flake": false, "locked": { - "lastModified": 1650932770, - "narHash": "sha256-/WzE4O23B1OcL3WF8Saz5TRQj0tGH7FtbgRLRson2Mc=", - "owner": "srid", - "repo": "pandoc-link-context", - "rev": "85bd204339aafd309b8a3dd99ebffa6a50776cb6", + "lastModified": 1631092763, + "narHash": "sha256-sIKgO+z7tj4lw3u6oBZxqIhDrzSkvpHtv0Kki+lh9Fg=", + "owner": "angerman", + "repo": "old-ghc-nix", + "rev": "af48a7a7353e418119b6dfe3cd1463a657f342b8", + "type": "github" + }, + "original": { + "owner": "angerman", + "ref": "master", + "repo": "old-ghc-nix", + "type": "github" + } + }, + "old-ghc-nix_6": { + "flake": false, + "locked": { + "lastModified": 1631092763, + "narHash": "sha256-sIKgO+z7tj4lw3u6oBZxqIhDrzSkvpHtv0Kki+lh9Fg=", + "owner": "angerman", + "repo": "old-ghc-nix", + "rev": "af48a7a7353e418119b6dfe3cd1463a657f342b8", + "type": "github" + }, + "original": { + "owner": "angerman", + "ref": "master", + "repo": "old-ghc-nix", + "type": "github" + } + }, + "old-ghc-nix_7": { + "flake": false, + "locked": { + "lastModified": 1631092763, + "narHash": "sha256-sIKgO+z7tj4lw3u6oBZxqIhDrzSkvpHtv0Kki+lh9Fg=", + "owner": "angerman", + "repo": "old-ghc-nix", + "rev": "af48a7a7353e418119b6dfe3cd1463a657f342b8", + "type": "github" + }, + "original": { + "owner": "angerman", + "ref": "master", + "repo": "old-ghc-nix", + "type": "github" + } + }, + "old-ghc-nix_8": { + "flake": false, + "locked": { + "lastModified": 1631092763, + "narHash": "sha256-sIKgO+z7tj4lw3u6oBZxqIhDrzSkvpHtv0Kki+lh9Fg=", + "owner": "angerman", + "repo": "old-ghc-nix", + "rev": "af48a7a7353e418119b6dfe3cd1463a657f342b8", + "type": "github" + }, + "original": { + "owner": "angerman", + "ref": "master", + "repo": "old-ghc-nix", + "type": "github" + } + }, + "old-ghc-nix_9": { + "flake": false, + "locked": { + "lastModified": 1631092763, + "narHash": "sha256-sIKgO+z7tj4lw3u6oBZxqIhDrzSkvpHtv0Kki+lh9Fg=", + "owner": "angerman", + "repo": "old-ghc-nix", + "rev": "af48a7a7353e418119b6dfe3cd1463a657f342b8", + "type": "github" + }, + "original": { + "owner": "angerman", + "ref": "master", + "repo": "old-ghc-nix", + "type": "github" + } + }, + "plutarch": { + "inputs": { + "cardano-base": "cardano-base", + "cardano-crypto": "cardano-crypto", + "cardano-prelude": "cardano-prelude", + "emanote": [ + "liqwid-plutarch-extra", + "plutarch", + "haskell-nix", + "nixpkgs-unstable" + ], + "flat": "flat", + "haskell-language-server": "haskell-language-server", + "haskell-nix": "haskell-nix", + "haskell-nix-extra-hackage": "haskell-nix-extra-hackage", + "hercules-ci-effects": "hercules-ci-effects", + "iohk-nix": "iohk-nix", + "nixpkgs": [ + "liqwid-plutarch-extra", + "plutarch", + "haskell-nix", + "nixpkgs-unstable" + ], + "nixpkgs-latest": "nixpkgs-latest_2", + "plutus": "plutus", + "protolude": "protolude", + "secp256k1-haskell": "secp256k1-haskell" + }, + "locked": { + "lastModified": 1659381657, + "narHash": "sha256-W0EWY0DV2idbIeqtJnShVHQ83exME8TK2GYQGbVpz8A=", + "owner": "Plutonomicon", + "repo": "plutarch-plutus", + "rev": "45b7c77a9ee9bd6c7dc25ddebcc3d12c58c4c3a2", + "type": "github" + }, + "original": { + "owner": "Plutonomicon", + "ref": "staging", + "repo": "plutarch-plutus", + "type": "github" + } + }, + "plutarch-context-builder": { + "inputs": { + "haskell-language-server": [ + "liqwid-plutarch-extra", + "plutarch-context-builder", + "plutarch", + "haskell-language-server" + ], + "haskell-nix": [ + "liqwid-plutarch-extra", + "plutarch-context-builder", + "plutarch", + "haskell-nix" + ], + "haskell-nix-extra-hackage": [ + "liqwid-plutarch-extra", + "plutarch-context-builder", + "plutarch", + "haskell-nix-extra-hackage" + ], + "iohk-nix": [ + "liqwid-plutarch-extra", + "plutarch-context-builder", + "plutarch", + "iohk-nix" + ], + "liqwid-nix": "liqwid-nix_3", + "nixpkgs": [ + "liqwid-plutarch-extra", + "plutarch-context-builder", + "plutarch", + "nixpkgs" + ], + "nixpkgs-2111": "nixpkgs-2111_3", + "nixpkgs-latest": "nixpkgs-latest_3", + "plutarch": "plutarch_2" + }, + "locked": { + "lastModified": 1659452596, + "narHash": "sha256-j0StZAogDVbpjzBXsWzlAO4JPp2pafMnG5ndgMyeuwU=", + "owner": "Liqwid-Labs", + "repo": "plutarch-context-builder", + "rev": "7dfa384bbf5427412ba78ef48ddd86ca251fdb18", + "type": "github" + }, + "original": { + "owner": "Liqwid-Labs", + "ref": "staging", + "repo": "plutarch-context-builder", + "type": "github" + } + }, + "plutarch-context-builder_2": { + "inputs": { + "haskell-language-server": [ + "plutarch-context-builder", + "plutarch", + "haskell-language-server" + ], + "haskell-nix": [ + "plutarch-context-builder", + "plutarch", + "haskell-nix" + ], + "haskell-nix-extra-hackage": [ + "plutarch-context-builder", + "plutarch", + "haskell-nix-extra-hackage" + ], + "iohk-nix": [ + "plutarch-context-builder", + "plutarch", + "iohk-nix" + ], + "liqwid-nix": "liqwid-nix_6", + "nixpkgs": [ + "plutarch-context-builder", + "plutarch", + "nixpkgs" + ], + "nixpkgs-2111": "nixpkgs-2111_11", + "nixpkgs-latest": "nixpkgs-latest_11", + "plutarch": "plutarch_6" + }, + "locked": { + "lastModified": 1659452596, + "narHash": "sha256-j0StZAogDVbpjzBXsWzlAO4JPp2pafMnG5ndgMyeuwU=", + "owner": "Liqwid-Labs", + "repo": "plutarch-context-builder", + "rev": "7dfa384bbf5427412ba78ef48ddd86ca251fdb18", + "type": "github" + }, + "original": { + "owner": "Liqwid-Labs", + "ref": "plutus-v1", + "repo": "plutarch-context-builder", + "type": "github" + } + }, + "plutarch-context-builder_3": { + "inputs": { + "haskell-language-server": [ + "plutarch-safe-money", + "liqwid-plutarch-extra", + "plutarch-context-builder", + "plutarch", + "haskell-language-server" + ], + "haskell-nix": [ + "plutarch-safe-money", + "liqwid-plutarch-extra", + "plutarch-context-builder", + "plutarch", + "haskell-nix" + ], + "haskell-nix-extra-hackage": [ + "plutarch-safe-money", + "liqwid-plutarch-extra", + "plutarch-context-builder", + "plutarch", + "haskell-nix-extra-hackage" + ], + "iohk-nix": [ + "plutarch-safe-money", + "liqwid-plutarch-extra", + "plutarch-context-builder", + "plutarch", + "iohk-nix" + ], + "liqwid-nix": "liqwid-nix_11", + "nixpkgs": [ + "plutarch-safe-money", + "liqwid-plutarch-extra", + "plutarch-context-builder", + "plutarch", + "nixpkgs" + ], + "nixpkgs-2111": "nixpkgs-2111_19", + "nixpkgs-latest": "nixpkgs-latest_19", + "plutarch": "plutarch_10" + }, + "locked": { + "lastModified": 1659452596, + "narHash": "sha256-j0StZAogDVbpjzBXsWzlAO4JPp2pafMnG5ndgMyeuwU=", + "owner": "Liqwid-Labs", + "repo": "plutarch-context-builder", + "rev": "7dfa384bbf5427412ba78ef48ddd86ca251fdb18", + "type": "github" + }, + "original": { + "owner": "Liqwid-Labs", + "ref": "staging", + "repo": "plutarch-context-builder", + "type": "github" + } + }, + "plutarch-numeric": { + "inputs": { + "haskell-language-server": [ + "liqwid-plutarch-extra", + "plutarch-numeric", + "plutarch", + "haskell-language-server" + ], + "haskell-nix": [ + "liqwid-plutarch-extra", + "plutarch-numeric", + "plutarch", + "haskell-nix" + ], + "haskell-nix-extra-hackage": [ + "liqwid-plutarch-extra", + "plutarch-numeric", + "plutarch", + "haskell-nix-extra-hackage" + ], + "iohk-nix": [ + "liqwid-plutarch-extra", + "plutarch-numeric", + "plutarch", + "iohk-nix" + ], + "liqwid-nix": "liqwid-nix_4", + "nixpkgs": [ + "liqwid-plutarch-extra", + "plutarch-numeric", + "plutarch", + "nixpkgs" + ], + "nixpkgs-2111": "nixpkgs-2111_5", + "nixpkgs-latest": "nixpkgs-latest_5", + "plutarch": "plutarch_3" + }, + "locked": { + "lastModified": 1659450964, + "narHash": "sha256-jkxeMZ5ZjEl94MG5jWC+ogeh8m5sCpR7FX2Srtedvc4=", + "owner": "liqwid-labs", + "repo": "plutarch-numeric", + "rev": "65a1a5dec3836cf4e3c793bf780a4ee84b0a9331", + "type": "github" + }, + "original": { + "owner": "liqwid-labs", + "ref": "main", + "repo": "plutarch-numeric", + "type": "github" + } + }, + "plutarch-numeric_2": { + "inputs": { + "haskell-language-server": [ + "plutarch-numeric", + "plutarch", + "haskell-language-server" + ], + "haskell-nix": [ + "plutarch-numeric", + "plutarch", + "haskell-nix" + ], + "haskell-nix-extra-hackage": [ + "plutarch-numeric", + "plutarch", + "haskell-nix-extra-hackage" + ], + "iohk-nix": [ + "plutarch-numeric", + "plutarch", + "iohk-nix" + ], + "liqwid-nix": "liqwid-nix_7", + "nixpkgs": [ + "plutarch-numeric", + "plutarch", + "nixpkgs" + ], + "nixpkgs-2111": "nixpkgs-2111_13", + "nixpkgs-latest": "nixpkgs-latest_13", + "plutarch": "plutarch_7" + }, + "locked": { + "lastModified": 1659450964, + "narHash": "sha256-jkxeMZ5ZjEl94MG5jWC+ogeh8m5sCpR7FX2Srtedvc4=", + "owner": "Liqwid-Labs", + "repo": "plutarch-numeric", + "rev": "65a1a5dec3836cf4e3c793bf780a4ee84b0a9331", + "type": "github" + }, + "original": { + "owner": "Liqwid-Labs", + "ref": "main", + "repo": "plutarch-numeric", + "type": "github" + } + }, + "plutarch-numeric_3": { + "inputs": { + "haskell-language-server": [ + "plutarch-safe-money", + "liqwid-plutarch-extra", + "plutarch-numeric", + "plutarch", + "haskell-language-server" + ], + "haskell-nix": [ + "plutarch-safe-money", + "liqwid-plutarch-extra", + "plutarch-numeric", + "plutarch", + "haskell-nix" + ], + "haskell-nix-extra-hackage": [ + "plutarch-safe-money", + "liqwid-plutarch-extra", + "plutarch-numeric", + "plutarch", + "haskell-nix-extra-hackage" + ], + "iohk-nix": [ + "plutarch-safe-money", + "liqwid-plutarch-extra", + "plutarch-numeric", + "plutarch", + "iohk-nix" + ], + "liqwid-nix": "liqwid-nix_12", + "nixpkgs": [ + "plutarch-safe-money", + "liqwid-plutarch-extra", + "plutarch-numeric", + "plutarch", + "nixpkgs" + ], + "nixpkgs-2111": "nixpkgs-2111_21", + "nixpkgs-latest": "nixpkgs-latest_21", + "plutarch": "plutarch_11" + }, + "locked": { + "lastModified": 1659450964, + "narHash": "sha256-jkxeMZ5ZjEl94MG5jWC+ogeh8m5sCpR7FX2Srtedvc4=", + "owner": "liqwid-labs", + "repo": "plutarch-numeric", + "rev": "65a1a5dec3836cf4e3c793bf780a4ee84b0a9331", + "type": "github" + }, + "original": { + "owner": "liqwid-labs", + "ref": "main", + "repo": "plutarch-numeric", + "type": "github" + } + }, + "plutarch-numeric_4": { + "inputs": { + "haskell-language-server": [ + "plutarch-safe-money", + "plutarch-numeric", + "plutarch", + "haskell-language-server" + ], + "haskell-nix": [ + "plutarch-safe-money", + "plutarch-numeric", + "plutarch", + "haskell-nix" + ], + "haskell-nix-extra-hackage": [ + "plutarch-safe-money", + "plutarch-numeric", + "plutarch", + "haskell-nix-extra-hackage" + ], + "iohk-nix": [ + "plutarch-safe-money", + "plutarch-numeric", + "plutarch", + "iohk-nix" + ], + "liqwid-nix": "liqwid-nix_14", + "nixpkgs": [ + "plutarch-safe-money", + "plutarch-numeric", + "plutarch", + "nixpkgs" + ], + "nixpkgs-2111": "nixpkgs-2111_27", + "nixpkgs-latest": "nixpkgs-latest_27", + "plutarch": "plutarch_14" + }, + "locked": { + "lastModified": 1659450964, + "narHash": "sha256-jkxeMZ5ZjEl94MG5jWC+ogeh8m5sCpR7FX2Srtedvc4=", + "owner": "Liqwid-Labs", + "repo": "plutarch-numeric", + "rev": "65a1a5dec3836cf4e3c793bf780a4ee84b0a9331", "type": "github" }, "original": { - "owner": "srid", - "ref": "master", - "repo": "pandoc-link-context", + "owner": "Liqwid-Labs", + "ref": "main", + "repo": "plutarch-numeric", "type": "github" } }, - "pathtree": { + "plutarch-quickcheck": { "inputs": { - "flake-compat": "flake-compat_18", - "flake-utils": "flake-utils_28", - "nixpkgs": "nixpkgs_45" + "haskell-language-server": [ + "liqwid-plutarch-extra", + "plutarch-quickcheck", + "plutarch", + "haskell-language-server" + ], + "haskell-nix": [ + "liqwid-plutarch-extra", + "plutarch-quickcheck", + "plutarch", + "haskell-nix" + ], + "haskell-nix-extra-hackage": [ + "liqwid-plutarch-extra", + "plutarch-quickcheck", + "plutarch", + "haskell-nix-extra-hackage" + ], + "iohk-nix": [ + "liqwid-plutarch-extra", + "plutarch-quickcheck", + "plutarch", + "iohk-nix" + ], + "liqwid-nix": "liqwid-nix_5", + "nixpkgs": [ + "liqwid-plutarch-extra", + "plutarch-quickcheck", + "plutarch", + "nixpkgs" + ], + "nixpkgs-2111": "nixpkgs-2111_7", + "nixpkgs-latest": "nixpkgs-latest_7", + "plutarch": "plutarch_4" }, "locked": { - "lastModified": 1649011952, - "narHash": "sha256-RuNIoPXx0xy5TZ81JH33V8EqXWX5erv8gepM0Aaeat8=", - "owner": "srid", - "repo": "pathtree", - "rev": "d60f22b356f79663aca3f5fde9f23bb4a1412963", + "lastModified": 1659450065, + "narHash": "sha256-x6B9sjrZaTite4TSLLyOWfmG3JJbOZuGUNMDZ1f4qhk=", + "owner": "liqwid-labs", + "repo": "plutarch-quickcheck", + "rev": "2c5b77f1a622ce68d80a09b286eb0ac85527ff26", "type": "github" }, "original": { - "owner": "srid", - "repo": "pathtree", + "owner": "liqwid-labs", + "ref": "staging", + "repo": "plutarch-quickcheck", "type": "github" } }, - "plutarch": { + "plutarch-quickcheck_2": { "inputs": { - "cardano-base": "cardano-base", - "cardano-crypto": "cardano-crypto", - "cardano-prelude": "cardano-prelude", - "emanote": "emanote", - "flat": "flat", - "haskell-language-server": "haskell-language-server_2", - "haskell-nix": "haskell-nix", - "haskell-nix-extra-hackage": "haskell-nix-extra-hackage", - "hercules-ci-effects": "hercules-ci-effects", - "iohk-nix": "iohk-nix", + "haskell-language-server": [ + "plutarch-quickcheck", + "plutarch", + "haskell-language-server" + ], + "haskell-nix": [ + "plutarch-quickcheck", + "plutarch", + "haskell-nix" + ], + "haskell-nix-extra-hackage": [ + "plutarch-quickcheck", + "plutarch", + "haskell-nix-extra-hackage" + ], + "iohk-nix": [ + "plutarch-quickcheck", + "plutarch", + "iohk-nix" + ], + "liqwid-nix": "liqwid-nix_8", "nixpkgs": [ - "liqwid-plutarch-extra", + "plutarch-quickcheck", "plutarch", - "haskell-nix", - "nixpkgs-unstable" + "nixpkgs" ], - "nixpkgs-latest": "nixpkgs-latest_2", - "plutus": "plutus", - "protolude": "protolude", - "secp256k1-haskell": "secp256k1-haskell" + "nixpkgs-2111": "nixpkgs-2111_15", + "nixpkgs-latest": "nixpkgs-latest_15", + "plutarch": "plutarch_8" }, "locked": { - "lastModified": 1654108284, - "narHash": "sha256-VD0zX4pFrJJaaUO7uJgioZGg1moe1Fy8nAb5j2mV/Qc=", - "owner": "Liqwid-Labs", - "repo": "plutarch", - "rev": "e7ef565645146e26e75ec29fe97122a74e52c6b7", + "lastModified": 1659450065, + "narHash": "sha256-x6B9sjrZaTite4TSLLyOWfmG3JJbOZuGUNMDZ1f4qhk=", + "owner": "liqwid-labs", + "repo": "plutarch-quickcheck", + "rev": "2c5b77f1a622ce68d80a09b286eb0ac85527ff26", "type": "github" }, "original": { - "owner": "Liqwid-Labs", + "owner": "liqwid-labs", "ref": "staging", - "repo": "plutarch", + "repo": "plutarch-quickcheck", "type": "github" } }, - "plutarch-context-builder": { + "plutarch-quickcheck_3": { "inputs": { - "haskell-language-server": "haskell-language-server_9", + "haskell-language-server": [ + "plutarch-safe-money", + "liqwid-plutarch-extra", + "plutarch-quickcheck", + "plutarch", + "haskell-language-server" + ], "haskell-nix": [ - "plutarch-context-builder", + "plutarch-safe-money", + "liqwid-plutarch-extra", + "plutarch-quickcheck", "plutarch", "haskell-nix" ], + "haskell-nix-extra-hackage": [ + "plutarch-safe-money", + "liqwid-plutarch-extra", + "plutarch-quickcheck", + "plutarch", + "haskell-nix-extra-hackage" + ], + "iohk-nix": [ + "plutarch-safe-money", + "liqwid-plutarch-extra", + "plutarch-quickcheck", + "plutarch", + "iohk-nix" + ], + "liqwid-nix": "liqwid-nix_13", "nixpkgs": [ - "plutarch-context-builder", + "plutarch-safe-money", + "liqwid-plutarch-extra", + "plutarch-quickcheck", "plutarch", "nixpkgs" ], - "nixpkgs-2111": "nixpkgs-2111_7", - "nixpkgs-latest": "nixpkgs-latest_7", - "plutarch": "plutarch_4" + "nixpkgs-2111": "nixpkgs-2111_23", + "nixpkgs-latest": "nixpkgs-latest_23", + "plutarch": "plutarch_12" }, "locked": { - "lastModified": 1655751255, - "narHash": "sha256-3Uk1v/V+qm/KBBwBPqzr4X7KiH9DyJ9vhNH2Pw08PkE=", - "owner": "Liqwid-Labs", - "repo": "plutarch-context-builder", - "rev": "9e6c81a2e1762a5f8e38cb88b83e2996447e3003", + "lastModified": 1659450065, + "narHash": "sha256-x6B9sjrZaTite4TSLLyOWfmG3JJbOZuGUNMDZ1f4qhk=", + "owner": "liqwid-labs", + "repo": "plutarch-quickcheck", + "rev": "2c5b77f1a622ce68d80a09b286eb0ac85527ff26", "type": "github" }, "original": { - "owner": "Liqwid-Labs", + "owner": "liqwid-labs", "ref": "staging", - "repo": "plutarch-context-builder", + "repo": "plutarch-quickcheck", "type": "github" } }, - "plutarch-numeric": { + "plutarch-safe-money": { "inputs": { - "haskell-language-server": "haskell-language-server_12", + "haskell-language-server": [ + "plutarch-safe-money", + "plutarch", + "haskell-language-server" + ], "haskell-nix": [ - "plutarch-numeric", + "plutarch-safe-money", "plutarch", "haskell-nix" ], + "haskell-nix-extra-hackage": [ + "plutarch-safe-money", + "plutarch", + "haskell-nix-extra-hackage" + ], + "iohk-nix": [ + "plutarch-safe-money", + "plutarch", + "iohk-nix" + ], + "liqwid-nix": "liqwid-nix_9", + "liqwid-plutarch-extra": "liqwid-plutarch-extra_2", "nixpkgs": [ - "plutarch-numeric", + "plutarch-safe-money", "plutarch", "nixpkgs" ], - "nixpkgs-2111": "nixpkgs-2111_9", - "nixpkgs-latest": "nixpkgs-latest_9", - "plutarch": "plutarch_5" + "nixpkgs-2111": "nixpkgs-2111_25", + "nixpkgs-latest": "nixpkgs-latest_25", + "plutarch": "plutarch_13", + "plutarch-numeric": "plutarch-numeric_4" }, "locked": { - "lastModified": 1655733533, - "narHash": "sha256-HRSJUEQYYwr0HvYn6GwLmyYY7TXwZcYPAW0U8t6nmok=", + "lastModified": 1659604619, + "narHash": "sha256-pqjjb/J773z2cE7bBsszxj2QnefewJlIIe1NbDeKrLw=", "owner": "Liqwid-Labs", - "repo": "plutarch-numeric", - "rev": "ce2d39dc366d9453b0f5df328bbb78f11e3b2ed6", + "repo": "plutarch-safe-money", + "rev": "6e4f2112a36b2937fc2f3f7143abb4f4c42e7428", "type": "github" }, "original": { "owner": "Liqwid-Labs", "ref": "main", - "repo": "plutarch-numeric", + "repo": "plutarch-safe-money", "type": "github" } }, - "plutarch-numeric_2": { + "plutarch-script-export": { "inputs": { - "haskell-language-server": "haskell-language-server_27", + "haskell-language-server": [ + "plutarch-script-export", + "plutarch", + "haskell-language-server" + ], "haskell-nix": [ - "plutarch-safe-money", - "plutarch-numeric", + "plutarch-script-export", "plutarch", "haskell-nix" ], + "haskell-nix-extra-hackage": [ + "plutarch-script-export", + "plutarch", + "haskell-nix-extra-hackage" + ], + "iohk-nix": [ + "plutarch-script-export", + "plutarch", + "iohk-nix" + ], + "liqwid-nix": "liqwid-nix_15", "nixpkgs": [ - "plutarch-safe-money", - "plutarch-numeric", + "plutarch-script-export", "plutarch", "nixpkgs" ], - "nixpkgs-2111": "nixpkgs-2111_19", - "nixpkgs-latest": "nixpkgs-latest_19", - "plutarch": "plutarch_10" + "nixpkgs-2111": "nixpkgs-2111_29", + "nixpkgs-latest": "nixpkgs-latest_29", + "plutarch": "plutarch_15" }, "locked": { - "lastModified": 1654950823, - "narHash": "sha256-fq6Iyk1ygNs4sTS55jLjx0hWFAFQNKXBGrVHuzRXFls=", + "lastModified": 1660213721, + "narHash": "sha256-YkDefu3XK1FelMFCgf3jOkzc3ugCS1DXUgr9rZoukPw=", "owner": "Liqwid-Labs", - "repo": "plutarch-numeric", - "rev": "11fdf47fdcbf19d51ed587b0b67618152098f442", + "repo": "plutarch-script-export", + "rev": "4d8f6af19d727c46fc8d746b1f6d3e356196610f", "type": "github" }, "original": { "owner": "Liqwid-Labs", "ref": "main", - "repo": "plutarch-numeric", + "repo": "plutarch-script-export", "type": "github" } }, - "plutarch-quickcheck": { + "plutarch_10": { "inputs": { - "haskell-language-server": "haskell-language-server_4", - "haskell-nix": [ + "cardano-base": "cardano-base_10", + "cardano-crypto": "cardano-crypto_10", + "cardano-prelude": "cardano-prelude_10", + "emanote": [ + "plutarch-safe-money", "liqwid-plutarch-extra", - "plutarch-quickcheck", + "plutarch-context-builder", "plutarch", - "haskell-nix" + "haskell-nix", + "nixpkgs-unstable" ], + "flat": "flat_10", + "haskell-language-server": "haskell-language-server_19", + "haskell-nix": "haskell-nix_19", + "haskell-nix-extra-hackage": "haskell-nix-extra-hackage_10", + "hercules-ci-effects": "hercules-ci-effects_10", + "iohk-nix": "iohk-nix_19", "nixpkgs": [ + "plutarch-safe-money", "liqwid-plutarch-extra", - "plutarch-quickcheck", + "plutarch-context-builder", "plutarch", - "nixpkgs" + "haskell-nix", + "nixpkgs-unstable" ], - "nixpkgs-2111": "nixpkgs-2111_3", - "nixpkgs-latest": "nixpkgs-latest_3", - "plutarch": "plutarch_2" + "nixpkgs-latest": "nixpkgs-latest_20", + "plutus": "plutus_10", + "protolude": "protolude_10", + "secp256k1-haskell": "secp256k1-haskell_10" }, "locked": { - "lastModified": 1655113586, - "narHash": "sha256-hv9tzB3IGvga6/SBDnk16S3Sfp03tvtkWd8COW0It30=", - "owner": "liqwid-labs", - "repo": "plutarch-quickcheck", - "rev": "a560e12b4809c0f292c96e81189e1b2cf2e7f7eb", + "lastModified": 1659381657, + "narHash": "sha256-W0EWY0DV2idbIeqtJnShVHQ83exME8TK2GYQGbVpz8A=", + "owner": "Plutonomicon", + "repo": "plutarch-plutus", + "rev": "45b7c77a9ee9bd6c7dc25ddebcc3d12c58c4c3a2", "type": "github" }, "original": { - "owner": "liqwid-labs", - "repo": "plutarch-quickcheck", - "rev": "a560e12b4809c0f292c96e81189e1b2cf2e7f7eb", + "owner": "Plutonomicon", + "ref": "staging", + "repo": "plutarch-plutus", "type": "github" } }, - "plutarch-quickcheck_2": { + "plutarch_11": { "inputs": { - "haskell-language-server": "haskell-language-server_15", - "haskell-nix": [ - "plutarch-quickcheck", + "cardano-base": "cardano-base_11", + "cardano-crypto": "cardano-crypto_11", + "cardano-prelude": "cardano-prelude_11", + "emanote": [ + "plutarch-safe-money", + "liqwid-plutarch-extra", + "plutarch-numeric", "plutarch", - "haskell-nix" + "haskell-nix", + "nixpkgs-unstable" ], + "flat": "flat_11", + "haskell-language-server": "haskell-language-server_21", + "haskell-nix": "haskell-nix_21", + "haskell-nix-extra-hackage": "haskell-nix-extra-hackage_11", + "hercules-ci-effects": "hercules-ci-effects_11", + "iohk-nix": "iohk-nix_21", "nixpkgs": [ - "plutarch-quickcheck", + "plutarch-safe-money", + "liqwid-plutarch-extra", + "plutarch-numeric", "plutarch", - "nixpkgs" + "haskell-nix", + "nixpkgs-unstable" ], - "nixpkgs-2111": "nixpkgs-2111_11", - "nixpkgs-latest": "nixpkgs-latest_11", - "plutarch": "plutarch_6" + "nixpkgs-latest": "nixpkgs-latest_22", + "plutus": "plutus_11", + "protolude": "protolude_11", + "secp256k1-haskell": "secp256k1-haskell_11" }, "locked": { - "lastModified": 1655307888, - "narHash": "sha256-hv9tzB3IGvga6/SBDnk16S3Sfp03tvtkWd8COW0It30=", - "owner": "liqwid-labs", - "repo": "plutarch-quickcheck", - "rev": "541c57675eefc2ecd0fb6c6477d0b7fb8900b5fc", + "lastModified": 1659381657, + "narHash": "sha256-W0EWY0DV2idbIeqtJnShVHQ83exME8TK2GYQGbVpz8A=", + "owner": "Plutonomicon", + "repo": "plutarch-plutus", + "rev": "45b7c77a9ee9bd6c7dc25ddebcc3d12c58c4c3a2", "type": "github" }, "original": { - "owner": "liqwid-labs", + "owner": "Plutonomicon", "ref": "staging", - "repo": "plutarch-quickcheck", + "repo": "plutarch-plutus", "type": "github" } }, - "plutarch-quickcheck_3": { + "plutarch_12": { "inputs": { - "haskell-language-server": "haskell-language-server_22", - "haskell-nix": [ + "cardano-base": "cardano-base_12", + "cardano-crypto": "cardano-crypto_12", + "cardano-prelude": "cardano-prelude_12", + "emanote": [ "plutarch-safe-money", "liqwid-plutarch-extra", "plutarch-quickcheck", "plutarch", - "haskell-nix" + "haskell-nix", + "nixpkgs-unstable" ], + "flat": "flat_12", + "haskell-language-server": "haskell-language-server_23", + "haskell-nix": "haskell-nix_23", + "haskell-nix-extra-hackage": "haskell-nix-extra-hackage_12", + "hercules-ci-effects": "hercules-ci-effects_12", + "iohk-nix": "iohk-nix_23", "nixpkgs": [ "plutarch-safe-money", "liqwid-plutarch-extra", "plutarch-quickcheck", "plutarch", - "nixpkgs" + "haskell-nix", + "nixpkgs-unstable" + ], + "nixpkgs-latest": "nixpkgs-latest_24", + "plutus": "plutus_12", + "protolude": "protolude_12", + "secp256k1-haskell": "secp256k1-haskell_12" + }, + "locked": { + "lastModified": 1659381657, + "narHash": "sha256-W0EWY0DV2idbIeqtJnShVHQ83exME8TK2GYQGbVpz8A=", + "owner": "Plutonomicon", + "repo": "plutarch-plutus", + "rev": "45b7c77a9ee9bd6c7dc25ddebcc3d12c58c4c3a2", + "type": "github" + }, + "original": { + "owner": "Plutonomicon", + "ref": "staging", + "repo": "plutarch-plutus", + "type": "github" + } + }, + "plutarch_13": { + "inputs": { + "cardano-base": "cardano-base_13", + "cardano-crypto": "cardano-crypto_13", + "cardano-prelude": "cardano-prelude_13", + "emanote": [ + "plutarch-safe-money", + "plutarch", + "haskell-nix", + "nixpkgs-unstable" + ], + "flat": "flat_13", + "haskell-language-server": "haskell-language-server_25", + "haskell-nix": "haskell-nix_25", + "haskell-nix-extra-hackage": "haskell-nix-extra-hackage_13", + "hercules-ci-effects": "hercules-ci-effects_13", + "iohk-nix": "iohk-nix_25", + "nixpkgs": [ + "plutarch-safe-money", + "plutarch", + "haskell-nix", + "nixpkgs-unstable" ], - "nixpkgs-2111": "nixpkgs-2111_15", - "nixpkgs-latest": "nixpkgs-latest_15", - "plutarch": "plutarch_8" + "nixpkgs-latest": "nixpkgs-latest_26", + "plutus": "plutus_13", + "protolude": "protolude_13", + "secp256k1-haskell": "secp256k1-haskell_13" }, "locked": { - "lastModified": 1655113586, - "narHash": "sha256-hv9tzB3IGvga6/SBDnk16S3Sfp03tvtkWd8COW0It30=", - "owner": "liqwid-labs", - "repo": "plutarch-quickcheck", - "rev": "a560e12b4809c0f292c96e81189e1b2cf2e7f7eb", + "lastModified": 1659381657, + "narHash": "sha256-W0EWY0DV2idbIeqtJnShVHQ83exME8TK2GYQGbVpz8A=", + "owner": "Plutonomicon", + "repo": "plutarch-plutus", + "rev": "45b7c77a9ee9bd6c7dc25ddebcc3d12c58c4c3a2", "type": "github" }, "original": { - "owner": "liqwid-labs", - "repo": "plutarch-quickcheck", - "rev": "a560e12b4809c0f292c96e81189e1b2cf2e7f7eb", + "owner": "Plutonomicon", + "ref": "staging", + "repo": "plutarch-plutus", "type": "github" } }, - "plutarch-safe-money": { + "plutarch_14": { "inputs": { - "haskell-language-server": "haskell-language-server_18", - "haskell-nix": [ + "cardano-base": "cardano-base_14", + "cardano-crypto": "cardano-crypto_14", + "cardano-prelude": "cardano-prelude_14", + "emanote": [ "plutarch-safe-money", + "plutarch-numeric", "plutarch", - "haskell-nix" + "haskell-nix", + "nixpkgs-unstable" ], - "liqwid-plutarch-extra": "liqwid-plutarch-extra_2", + "flat": "flat_14", + "haskell-language-server": "haskell-language-server_27", + "haskell-nix": "haskell-nix_27", + "haskell-nix-extra-hackage": "haskell-nix-extra-hackage_14", + "hercules-ci-effects": "hercules-ci-effects_14", + "iohk-nix": "iohk-nix_27", "nixpkgs": [ "plutarch-safe-money", + "plutarch-numeric", "plutarch", - "nixpkgs" + "haskell-nix", + "nixpkgs-unstable" ], - "nixpkgs-2111": "nixpkgs-2111_17", - "nixpkgs-latest": "nixpkgs-latest_17", - "plutarch": "plutarch_9", - "plutarch-numeric": "plutarch-numeric_2" + "nixpkgs-latest": "nixpkgs-latest_28", + "plutus": "plutus_14", + "protolude": "protolude_14", + "secp256k1-haskell": "secp256k1-haskell_14" }, "locked": { - "lastModified": 1655471113, - "narHash": "sha256-6z17r2rs2M+Gv7MJep6+zP2bq6G5Id4XDhInpU5RulM=", - "owner": "Liqwid-Labs", - "repo": "plutarch-safe-money", - "rev": "9f968b80189c7e4b335527cd5b103dc26952f667", + "lastModified": 1659381657, + "narHash": "sha256-W0EWY0DV2idbIeqtJnShVHQ83exME8TK2GYQGbVpz8A=", + "owner": "Plutonomicon", + "repo": "plutarch-plutus", + "rev": "45b7c77a9ee9bd6c7dc25ddebcc3d12c58c4c3a2", "type": "github" }, "original": { - "owner": "Liqwid-Labs", - "repo": "plutarch-safe-money", - "rev": "9f968b80189c7e4b335527cd5b103dc26952f667", + "owner": "Plutonomicon", + "ref": "staging", + "repo": "plutarch-plutus", "type": "github" } }, - "plutarch_10": { + "plutarch_15": { "inputs": { - "Shrinker": "Shrinker", - "cardano-base": "cardano-base_10", - "cardano-crypto": "cardano-crypto_10", - "cardano-prelude": "cardano-prelude_10", - "cryptonite": "cryptonite", - "emanote": "emanote_9", - "flat": "flat_10", - "foundation": "foundation", - "haskell-language-server": "haskell-language-server_28", - "haskell-nix": "haskell-nix_19", - "hercules-ci-effects": "hercules-ci-effects_10", - "hs-memory": "hs-memory", - "hspec": "hspec", - "hspec-golden": "hspec-golden", - "hspec-hedgehog": "hspec-hedgehog", - "iohk-nix": "iohk-nix_19", + "cardano-base": "cardano-base_15", + "cardano-crypto": "cardano-crypto_15", + "cardano-prelude": "cardano-prelude_15", + "emanote": [ + "plutarch-script-export", + "plutarch", + "haskell-nix", + "nixpkgs-unstable" + ], + "flat": "flat_15", + "haskell-language-server": "haskell-language-server_29", + "haskell-nix": "haskell-nix_29", + "haskell-nix-extra-hackage": "haskell-nix-extra-hackage_15", + "hercules-ci-effects": "hercules-ci-effects_15", + "iohk-nix": "iohk-nix_29", "nixpkgs": [ - "plutarch-safe-money", - "plutarch-numeric", + "plutarch-script-export", "plutarch", "haskell-nix", "nixpkgs-unstable" ], - "plutus": "plutus_10", - "protolude": "protolude_10", - "sized-functors": "sized-functors", - "th-extras": "th-extras" + "nixpkgs-latest": "nixpkgs-latest_30", + "plutus": "plutus_15", + "protolude": "protolude_15", + "secp256k1-haskell": "secp256k1-haskell_15" }, "locked": { - "lastModified": 1652353304, - "narHash": "sha256-DeSwiDyJeI9had5OCxLiGtYeDl07Vic0cR8RETBLY9k=", - "owner": "Liqwid-Labs", - "repo": "plutarch", - "rev": "ae2059f11f24d47bedeaa18749d01711cddab0bc", + "lastModified": 1659381657, + "narHash": "sha256-W0EWY0DV2idbIeqtJnShVHQ83exME8TK2GYQGbVpz8A=", + "owner": "Plutonomicon", + "repo": "plutarch-plutus", + "rev": "45b7c77a9ee9bd6c7dc25ddebcc3d12c58c4c3a2", "type": "github" }, "original": { - "owner": "Liqwid-Labs", + "owner": "Plutonomicon", "ref": "staging", - "repo": "plutarch", + "repo": "plutarch-plutus", "type": "github" } }, @@ -9552,16 +12066,22 @@ "cardano-base": "cardano-base_2", "cardano-crypto": "cardano-crypto_2", "cardano-prelude": "cardano-prelude_2", - "emanote": "emanote_2", + "emanote": [ + "liqwid-plutarch-extra", + "plutarch-context-builder", + "plutarch", + "haskell-nix", + "nixpkgs-unstable" + ], "flat": "flat_2", - "haskell-language-server": "haskell-language-server_5", + "haskell-language-server": "haskell-language-server_3", "haskell-nix": "haskell-nix_3", "haskell-nix-extra-hackage": "haskell-nix-extra-hackage_2", "hercules-ci-effects": "hercules-ci-effects_2", "iohk-nix": "iohk-nix_3", "nixpkgs": [ "liqwid-plutarch-extra", - "plutarch-quickcheck", + "plutarch-context-builder", "plutarch", "haskell-nix", "nixpkgs-unstable" @@ -9572,17 +12092,17 @@ "secp256k1-haskell": "secp256k1-haskell_2" }, "locked": { - "lastModified": 1654108284, - "narHash": "sha256-VD0zX4pFrJJaaUO7uJgioZGg1moe1Fy8nAb5j2mV/Qc=", - "owner": "Liqwid-Labs", - "repo": "plutarch", - "rev": "e7ef565645146e26e75ec29fe97122a74e52c6b7", + "lastModified": 1659381657, + "narHash": "sha256-W0EWY0DV2idbIeqtJnShVHQ83exME8TK2GYQGbVpz8A=", + "owner": "Plutonomicon", + "repo": "plutarch-plutus", + "rev": "45b7c77a9ee9bd6c7dc25ddebcc3d12c58c4c3a2", "type": "github" }, "original": { - "owner": "Liqwid-Labs", + "owner": "Plutonomicon", "ref": "staging", - "repo": "plutarch", + "repo": "plutarch-plutus", "type": "github" } }, @@ -9592,17 +12112,21 @@ "cardano-crypto": "cardano-crypto_3", "cardano-prelude": "cardano-prelude_3", "emanote": [ + "liqwid-plutarch-extra", + "plutarch-numeric", "plutarch", "haskell-nix", "nixpkgs-unstable" ], "flat": "flat_3", - "haskell-language-server": "haskell-language-server_7", + "haskell-language-server": "haskell-language-server_5", "haskell-nix": "haskell-nix_5", "haskell-nix-extra-hackage": "haskell-nix-extra-hackage_3", "hercules-ci-effects": "hercules-ci-effects_3", "iohk-nix": "iohk-nix_5", "nixpkgs": [ + "liqwid-plutarch-extra", + "plutarch-numeric", "plutarch", "haskell-nix", "nixpkgs-unstable" @@ -9613,17 +12137,17 @@ "secp256k1-haskell": "secp256k1-haskell_3" }, "locked": { - "lastModified": 1654108284, - "narHash": "sha256-VD0zX4pFrJJaaUO7uJgioZGg1moe1Fy8nAb5j2mV/Qc=", - "owner": "liqwid-labs", - "repo": "plutarch", - "rev": "e7ef565645146e26e75ec29fe97122a74e52c6b7", + "lastModified": 1659381657, + "narHash": "sha256-W0EWY0DV2idbIeqtJnShVHQ83exME8TK2GYQGbVpz8A=", + "owner": "Plutonomicon", + "repo": "plutarch-plutus", + "rev": "45b7c77a9ee9bd6c7dc25ddebcc3d12c58c4c3a2", "type": "github" }, "original": { - "owner": "liqwid-labs", - "repo": "plutarch", - "rev": "e7ef565645146e26e75ec29fe97122a74e52c6b7", + "owner": "Plutonomicon", + "ref": "staging", + "repo": "plutarch-plutus", "type": "github" } }, @@ -9632,15 +12156,22 @@ "cardano-base": "cardano-base_4", "cardano-crypto": "cardano-crypto_4", "cardano-prelude": "cardano-prelude_4", - "emanote": "emanote_3", + "emanote": [ + "liqwid-plutarch-extra", + "plutarch-quickcheck", + "plutarch", + "haskell-nix", + "nixpkgs-unstable" + ], "flat": "flat_4", - "haskell-language-server": "haskell-language-server_10", + "haskell-language-server": "haskell-language-server_7", "haskell-nix": "haskell-nix_7", "haskell-nix-extra-hackage": "haskell-nix-extra-hackage_4", "hercules-ci-effects": "hercules-ci-effects_4", "iohk-nix": "iohk-nix_7", "nixpkgs": [ - "plutarch-context-builder", + "liqwid-plutarch-extra", + "plutarch-quickcheck", "plutarch", "haskell-nix", "nixpkgs-unstable" @@ -9651,17 +12182,17 @@ "secp256k1-haskell": "secp256k1-haskell_4" }, "locked": { - "lastModified": 1654108284, - "narHash": "sha256-VD0zX4pFrJJaaUO7uJgioZGg1moe1Fy8nAb5j2mV/Qc=", - "owner": "Liqwid-Labs", - "repo": "plutarch", - "rev": "e7ef565645146e26e75ec29fe97122a74e52c6b7", + "lastModified": 1659381657, + "narHash": "sha256-W0EWY0DV2idbIeqtJnShVHQ83exME8TK2GYQGbVpz8A=", + "owner": "Plutonomicon", + "repo": "plutarch-plutus", + "rev": "45b7c77a9ee9bd6c7dc25ddebcc3d12c58c4c3a2", "type": "github" }, "original": { - "owner": "Liqwid-Labs", + "owner": "Plutonomicon", "ref": "staging", - "repo": "plutarch", + "repo": "plutarch-plutus", "type": "github" } }, @@ -9670,15 +12201,18 @@ "cardano-base": "cardano-base_5", "cardano-crypto": "cardano-crypto_5", "cardano-prelude": "cardano-prelude_5", - "emanote": "emanote_4", + "emanote": [ + "plutarch", + "haskell-nix", + "nixpkgs-unstable" + ], "flat": "flat_5", - "haskell-language-server": "haskell-language-server_13", + "haskell-language-server": "haskell-language-server_9", "haskell-nix": "haskell-nix_9", "haskell-nix-extra-hackage": "haskell-nix-extra-hackage_5", "hercules-ci-effects": "hercules-ci-effects_5", "iohk-nix": "iohk-nix_9", "nixpkgs": [ - "plutarch-numeric", "plutarch", "haskell-nix", "nixpkgs-unstable" @@ -9689,17 +12223,17 @@ "secp256k1-haskell": "secp256k1-haskell_5" }, "locked": { - "lastModified": 1654108284, - "narHash": "sha256-VD0zX4pFrJJaaUO7uJgioZGg1moe1Fy8nAb5j2mV/Qc=", - "owner": "Liqwid-Labs", - "repo": "plutarch", - "rev": "e7ef565645146e26e75ec29fe97122a74e52c6b7", + "lastModified": 1659381657, + "narHash": "sha256-W0EWY0DV2idbIeqtJnShVHQ83exME8TK2GYQGbVpz8A=", + "owner": "Plutonomicon", + "repo": "plutarch-plutus", + "rev": "45b7c77a9ee9bd6c7dc25ddebcc3d12c58c4c3a2", "type": "github" }, "original": { - "owner": "Liqwid-Labs", + "owner": "Plutonomicon", "ref": "staging", - "repo": "plutarch", + "repo": "plutarch-plutus", "type": "github" } }, @@ -9708,15 +12242,20 @@ "cardano-base": "cardano-base_6", "cardano-crypto": "cardano-crypto_6", "cardano-prelude": "cardano-prelude_6", - "emanote": "emanote_5", + "emanote": [ + "plutarch-context-builder", + "plutarch", + "haskell-nix", + "nixpkgs-unstable" + ], "flat": "flat_6", - "haskell-language-server": "haskell-language-server_16", + "haskell-language-server": "haskell-language-server_11", "haskell-nix": "haskell-nix_11", "haskell-nix-extra-hackage": "haskell-nix-extra-hackage_6", "hercules-ci-effects": "hercules-ci-effects_6", "iohk-nix": "iohk-nix_11", "nixpkgs": [ - "plutarch-quickcheck", + "plutarch-context-builder", "plutarch", "haskell-nix", "nixpkgs-unstable" @@ -9727,17 +12266,17 @@ "secp256k1-haskell": "secp256k1-haskell_6" }, "locked": { - "lastModified": 1654108284, - "narHash": "sha256-VD0zX4pFrJJaaUO7uJgioZGg1moe1Fy8nAb5j2mV/Qc=", - "owner": "Liqwid-Labs", - "repo": "plutarch", - "rev": "e7ef565645146e26e75ec29fe97122a74e52c6b7", + "lastModified": 1659381657, + "narHash": "sha256-W0EWY0DV2idbIeqtJnShVHQ83exME8TK2GYQGbVpz8A=", + "owner": "Plutonomicon", + "repo": "plutarch-plutus", + "rev": "45b7c77a9ee9bd6c7dc25ddebcc3d12c58c4c3a2", "type": "github" }, "original": { - "owner": "Liqwid-Labs", + "owner": "Plutonomicon", "ref": "staging", - "repo": "plutarch", + "repo": "plutarch-plutus", "type": "github" } }, @@ -9746,16 +12285,20 @@ "cardano-base": "cardano-base_7", "cardano-crypto": "cardano-crypto_7", "cardano-prelude": "cardano-prelude_7", - "emanote": "emanote_6", + "emanote": [ + "plutarch-numeric", + "plutarch", + "haskell-nix", + "nixpkgs-unstable" + ], "flat": "flat_7", - "haskell-language-server": "haskell-language-server_20", + "haskell-language-server": "haskell-language-server_13", "haskell-nix": "haskell-nix_13", "haskell-nix-extra-hackage": "haskell-nix-extra-hackage_7", "hercules-ci-effects": "hercules-ci-effects_7", "iohk-nix": "iohk-nix_13", "nixpkgs": [ - "plutarch-safe-money", - "liqwid-plutarch-extra", + "plutarch-numeric", "plutarch", "haskell-nix", "nixpkgs-unstable" @@ -9766,17 +12309,17 @@ "secp256k1-haskell": "secp256k1-haskell_7" }, "locked": { - "lastModified": 1654108284, - "narHash": "sha256-VD0zX4pFrJJaaUO7uJgioZGg1moe1Fy8nAb5j2mV/Qc=", - "owner": "Liqwid-Labs", - "repo": "plutarch", - "rev": "e7ef565645146e26e75ec29fe97122a74e52c6b7", + "lastModified": 1659381657, + "narHash": "sha256-W0EWY0DV2idbIeqtJnShVHQ83exME8TK2GYQGbVpz8A=", + "owner": "Plutonomicon", + "repo": "plutarch-plutus", + "rev": "45b7c77a9ee9bd6c7dc25ddebcc3d12c58c4c3a2", "type": "github" }, "original": { - "owner": "Liqwid-Labs", + "owner": "Plutonomicon", "ref": "staging", - "repo": "plutarch", + "repo": "plutarch-plutus", "type": "github" } }, @@ -9785,16 +12328,19 @@ "cardano-base": "cardano-base_8", "cardano-crypto": "cardano-crypto_8", "cardano-prelude": "cardano-prelude_8", - "emanote": "emanote_7", + "emanote": [ + "plutarch-quickcheck", + "plutarch", + "haskell-nix", + "nixpkgs-unstable" + ], "flat": "flat_8", - "haskell-language-server": "haskell-language-server_23", + "haskell-language-server": "haskell-language-server_15", "haskell-nix": "haskell-nix_15", "haskell-nix-extra-hackage": "haskell-nix-extra-hackage_8", "hercules-ci-effects": "hercules-ci-effects_8", "iohk-nix": "iohk-nix_15", "nixpkgs": [ - "plutarch-safe-money", - "liqwid-plutarch-extra", "plutarch-quickcheck", "plutarch", "haskell-nix", @@ -9806,17 +12352,17 @@ "secp256k1-haskell": "secp256k1-haskell_8" }, "locked": { - "lastModified": 1654108284, - "narHash": "sha256-VD0zX4pFrJJaaUO7uJgioZGg1moe1Fy8nAb5j2mV/Qc=", - "owner": "Liqwid-Labs", - "repo": "plutarch", - "rev": "e7ef565645146e26e75ec29fe97122a74e52c6b7", + "lastModified": 1659381657, + "narHash": "sha256-W0EWY0DV2idbIeqtJnShVHQ83exME8TK2GYQGbVpz8A=", + "owner": "Plutonomicon", + "repo": "plutarch-plutus", + "rev": "45b7c77a9ee9bd6c7dc25ddebcc3d12c58c4c3a2", "type": "github" }, "original": { - "owner": "Liqwid-Labs", + "owner": "Plutonomicon", "ref": "staging", - "repo": "plutarch", + "repo": "plutarch-plutus", "type": "github" } }, @@ -9825,15 +12371,22 @@ "cardano-base": "cardano-base_9", "cardano-crypto": "cardano-crypto_9", "cardano-prelude": "cardano-prelude_9", - "emanote": "emanote_8", + "emanote": [ + "plutarch-safe-money", + "liqwid-plutarch-extra", + "plutarch", + "haskell-nix", + "nixpkgs-unstable" + ], "flat": "flat_9", - "haskell-language-server": "haskell-language-server_25", + "haskell-language-server": "haskell-language-server_17", "haskell-nix": "haskell-nix_17", "haskell-nix-extra-hackage": "haskell-nix-extra-hackage_9", "hercules-ci-effects": "hercules-ci-effects_9", "iohk-nix": "iohk-nix_17", "nixpkgs": [ "plutarch-safe-money", + "liqwid-plutarch-extra", "plutarch", "haskell-nix", "nixpkgs-unstable" @@ -9844,17 +12397,17 @@ "secp256k1-haskell": "secp256k1-haskell_9" }, "locked": { - "lastModified": 1654108284, - "narHash": "sha256-VD0zX4pFrJJaaUO7uJgioZGg1moe1Fy8nAb5j2mV/Qc=", - "owner": "Liqwid-Labs", - "repo": "plutarch", - "rev": "e7ef565645146e26e75ec29fe97122a74e52c6b7", + "lastModified": 1659381657, + "narHash": "sha256-W0EWY0DV2idbIeqtJnShVHQ83exME8TK2GYQGbVpz8A=", + "owner": "Plutonomicon", + "repo": "plutarch-plutus", + "rev": "45b7c77a9ee9bd6c7dc25ddebcc3d12c58c4c3a2", "type": "github" }, "original": { - "owner": "Liqwid-Labs", + "owner": "Plutonomicon", "ref": "staging", - "repo": "plutarch", + "repo": "plutarch-plutus", "type": "github" } }, @@ -9863,7 +12416,7 @@ "cardano-repo-tool": "cardano-repo-tool", "gitignore-nix": "gitignore-nix", "hackage-nix": "hackage-nix", - "haskell-language-server": "haskell-language-server_3", + "haskell-language-server": "haskell-language-server_2", "haskell-nix": "haskell-nix_2", "iohk-nix": "iohk-nix_2", "nixpkgs": "nixpkgs_5", @@ -9871,11 +12424,11 @@ "sphinxcontrib-haddock": "sphinxcontrib-haddock" }, "locked": { - "lastModified": 1653669501, - "narHash": "sha256-qJrjEeo9Jmar1TwihDFzKQNC1ui4M03iClJM1zMd5Uk=", + "lastModified": 1656595231, + "narHash": "sha256-3EBhSroECMOSP02qZGT0Zb3QHWibI/tYjdcaT5/YotY=", "owner": "input-output-hk", "repo": "plutus", - "rev": "fed48a71550a12290efc84eefb74305d93cde69d", + "rev": "b39a526e983cb931d0cc49b7d073d6d43abd22b5", "type": "github" }, "original": { @@ -9889,25 +12442,153 @@ "cardano-repo-tool": "cardano-repo-tool_10", "gitignore-nix": "gitignore-nix_10", "hackage-nix": "hackage-nix_10", - "haskell-language-server": "haskell-language-server_29", + "haskell-language-server": "haskell-language-server_20", "haskell-nix": "haskell-nix_20", "iohk-nix": "iohk-nix_20", - "nixpkgs": "nixpkgs_49", + "nixpkgs": "nixpkgs_41", "pre-commit-hooks-nix": "pre-commit-hooks-nix_10", - "sphinxcontrib-haddock": "sphinxcontrib-haddock_10", - "stackage-nix": "stackage-nix" + "sphinxcontrib-haddock": "sphinxcontrib-haddock_10" + }, + "locked": { + "lastModified": 1656595231, + "narHash": "sha256-3EBhSroECMOSP02qZGT0Zb3QHWibI/tYjdcaT5/YotY=", + "owner": "input-output-hk", + "repo": "plutus", + "rev": "b39a526e983cb931d0cc49b7d073d6d43abd22b5", + "type": "github" + }, + "original": { + "owner": "input-output-hk", + "repo": "plutus", + "type": "github" + } + }, + "plutus_11": { + "inputs": { + "cardano-repo-tool": "cardano-repo-tool_11", + "gitignore-nix": "gitignore-nix_11", + "hackage-nix": "hackage-nix_11", + "haskell-language-server": "haskell-language-server_22", + "haskell-nix": "haskell-nix_22", + "iohk-nix": "iohk-nix_22", + "nixpkgs": "nixpkgs_45", + "pre-commit-hooks-nix": "pre-commit-hooks-nix_11", + "sphinxcontrib-haddock": "sphinxcontrib-haddock_11" + }, + "locked": { + "lastModified": 1656595231, + "narHash": "sha256-3EBhSroECMOSP02qZGT0Zb3QHWibI/tYjdcaT5/YotY=", + "owner": "input-output-hk", + "repo": "plutus", + "rev": "b39a526e983cb931d0cc49b7d073d6d43abd22b5", + "type": "github" + }, + "original": { + "owner": "input-output-hk", + "repo": "plutus", + "type": "github" + } + }, + "plutus_12": { + "inputs": { + "cardano-repo-tool": "cardano-repo-tool_12", + "gitignore-nix": "gitignore-nix_12", + "hackage-nix": "hackage-nix_12", + "haskell-language-server": "haskell-language-server_24", + "haskell-nix": "haskell-nix_24", + "iohk-nix": "iohk-nix_24", + "nixpkgs": "nixpkgs_49", + "pre-commit-hooks-nix": "pre-commit-hooks-nix_12", + "sphinxcontrib-haddock": "sphinxcontrib-haddock_12" + }, + "locked": { + "lastModified": 1656595231, + "narHash": "sha256-3EBhSroECMOSP02qZGT0Zb3QHWibI/tYjdcaT5/YotY=", + "owner": "input-output-hk", + "repo": "plutus", + "rev": "b39a526e983cb931d0cc49b7d073d6d43abd22b5", + "type": "github" + }, + "original": { + "owner": "input-output-hk", + "repo": "plutus", + "type": "github" + } + }, + "plutus_13": { + "inputs": { + "cardano-repo-tool": "cardano-repo-tool_13", + "gitignore-nix": "gitignore-nix_13", + "hackage-nix": "hackage-nix_13", + "haskell-language-server": "haskell-language-server_26", + "haskell-nix": "haskell-nix_26", + "iohk-nix": "iohk-nix_26", + "nixpkgs": "nixpkgs_52", + "pre-commit-hooks-nix": "pre-commit-hooks-nix_13", + "sphinxcontrib-haddock": "sphinxcontrib-haddock_13" + }, + "locked": { + "lastModified": 1656595231, + "narHash": "sha256-3EBhSroECMOSP02qZGT0Zb3QHWibI/tYjdcaT5/YotY=", + "owner": "input-output-hk", + "repo": "plutus", + "rev": "b39a526e983cb931d0cc49b7d073d6d43abd22b5", + "type": "github" + }, + "original": { + "owner": "input-output-hk", + "repo": "plutus", + "type": "github" + } + }, + "plutus_14": { + "inputs": { + "cardano-repo-tool": "cardano-repo-tool_14", + "gitignore-nix": "gitignore-nix_14", + "hackage-nix": "hackage-nix_14", + "haskell-language-server": "haskell-language-server_28", + "haskell-nix": "haskell-nix_28", + "iohk-nix": "iohk-nix_28", + "nixpkgs": "nixpkgs_56", + "pre-commit-hooks-nix": "pre-commit-hooks-nix_14", + "sphinxcontrib-haddock": "sphinxcontrib-haddock_14" + }, + "locked": { + "lastModified": 1656595231, + "narHash": "sha256-3EBhSroECMOSP02qZGT0Zb3QHWibI/tYjdcaT5/YotY=", + "owner": "input-output-hk", + "repo": "plutus", + "rev": "b39a526e983cb931d0cc49b7d073d6d43abd22b5", + "type": "github" + }, + "original": { + "owner": "input-output-hk", + "repo": "plutus", + "type": "github" + } + }, + "plutus_15": { + "inputs": { + "cardano-repo-tool": "cardano-repo-tool_15", + "gitignore-nix": "gitignore-nix_15", + "hackage-nix": "hackage-nix_15", + "haskell-language-server": "haskell-language-server_30", + "haskell-nix": "haskell-nix_30", + "iohk-nix": "iohk-nix_30", + "nixpkgs": "nixpkgs_60", + "pre-commit-hooks-nix": "pre-commit-hooks-nix_15", + "sphinxcontrib-haddock": "sphinxcontrib-haddock_15" }, "locked": { - "lastModified": 1645203653, - "narHash": "sha256-HAi60mSkyMXzu1Wg3h6KdYZg+ufNMvX6obfcLo0ArL0=", - "owner": "L-as", + "lastModified": 1656595231, + "narHash": "sha256-3EBhSroECMOSP02qZGT0Zb3QHWibI/tYjdcaT5/YotY=", + "owner": "input-output-hk", "repo": "plutus", - "rev": "5ec17953aae3ac9546f6d923201eb1dbb4e058bb", + "rev": "b39a526e983cb931d0cc49b7d073d6d43abd22b5", "type": "github" }, "original": { - "owner": "L-as", - "ref": "ghc9", + "owner": "input-output-hk", "repo": "plutus", "type": "github" } @@ -9917,19 +12598,19 @@ "cardano-repo-tool": "cardano-repo-tool_2", "gitignore-nix": "gitignore-nix_2", "hackage-nix": "hackage-nix_2", - "haskell-language-server": "haskell-language-server_6", + "haskell-language-server": "haskell-language-server_4", "haskell-nix": "haskell-nix_4", "iohk-nix": "iohk-nix_4", - "nixpkgs": "nixpkgs_10", + "nixpkgs": "nixpkgs_9", "pre-commit-hooks-nix": "pre-commit-hooks-nix_2", "sphinxcontrib-haddock": "sphinxcontrib-haddock_2" }, "locked": { - "lastModified": 1653669501, - "narHash": "sha256-qJrjEeo9Jmar1TwihDFzKQNC1ui4M03iClJM1zMd5Uk=", + "lastModified": 1656595231, + "narHash": "sha256-3EBhSroECMOSP02qZGT0Zb3QHWibI/tYjdcaT5/YotY=", "owner": "input-output-hk", "repo": "plutus", - "rev": "fed48a71550a12290efc84eefb74305d93cde69d", + "rev": "b39a526e983cb931d0cc49b7d073d6d43abd22b5", "type": "github" }, "original": { @@ -9943,7 +12624,7 @@ "cardano-repo-tool": "cardano-repo-tool_3", "gitignore-nix": "gitignore-nix_3", "hackage-nix": "hackage-nix_3", - "haskell-language-server": "haskell-language-server_8", + "haskell-language-server": "haskell-language-server_6", "haskell-nix": "haskell-nix_6", "iohk-nix": "iohk-nix_6", "nixpkgs": "nixpkgs_13", @@ -9951,11 +12632,11 @@ "sphinxcontrib-haddock": "sphinxcontrib-haddock_3" }, "locked": { - "lastModified": 1653669501, - "narHash": "sha256-qJrjEeo9Jmar1TwihDFzKQNC1ui4M03iClJM1zMd5Uk=", + "lastModified": 1656595231, + "narHash": "sha256-3EBhSroECMOSP02qZGT0Zb3QHWibI/tYjdcaT5/YotY=", "owner": "input-output-hk", "repo": "plutus", - "rev": "fed48a71550a12290efc84eefb74305d93cde69d", + "rev": "b39a526e983cb931d0cc49b7d073d6d43abd22b5", "type": "github" }, "original": { @@ -9969,19 +12650,19 @@ "cardano-repo-tool": "cardano-repo-tool_4", "gitignore-nix": "gitignore-nix_4", "hackage-nix": "hackage-nix_4", - "haskell-language-server": "haskell-language-server_11", + "haskell-language-server": "haskell-language-server_8", "haskell-nix": "haskell-nix_8", "iohk-nix": "iohk-nix_8", - "nixpkgs": "nixpkgs_18", + "nixpkgs": "nixpkgs_17", "pre-commit-hooks-nix": "pre-commit-hooks-nix_4", "sphinxcontrib-haddock": "sphinxcontrib-haddock_4" }, "locked": { - "lastModified": 1653669501, - "narHash": "sha256-qJrjEeo9Jmar1TwihDFzKQNC1ui4M03iClJM1zMd5Uk=", + "lastModified": 1656595231, + "narHash": "sha256-3EBhSroECMOSP02qZGT0Zb3QHWibI/tYjdcaT5/YotY=", "owner": "input-output-hk", "repo": "plutus", - "rev": "fed48a71550a12290efc84eefb74305d93cde69d", + "rev": "b39a526e983cb931d0cc49b7d073d6d43abd22b5", "type": "github" }, "original": { @@ -9995,19 +12676,19 @@ "cardano-repo-tool": "cardano-repo-tool_5", "gitignore-nix": "gitignore-nix_5", "hackage-nix": "hackage-nix_5", - "haskell-language-server": "haskell-language-server_14", + "haskell-language-server": "haskell-language-server_10", "haskell-nix": "haskell-nix_10", "iohk-nix": "iohk-nix_10", - "nixpkgs": "nixpkgs_23", + "nixpkgs": "nixpkgs_20", "pre-commit-hooks-nix": "pre-commit-hooks-nix_5", "sphinxcontrib-haddock": "sphinxcontrib-haddock_5" }, "locked": { - "lastModified": 1653669501, - "narHash": "sha256-qJrjEeo9Jmar1TwihDFzKQNC1ui4M03iClJM1zMd5Uk=", + "lastModified": 1656595231, + "narHash": "sha256-3EBhSroECMOSP02qZGT0Zb3QHWibI/tYjdcaT5/YotY=", "owner": "input-output-hk", "repo": "plutus", - "rev": "fed48a71550a12290efc84eefb74305d93cde69d", + "rev": "b39a526e983cb931d0cc49b7d073d6d43abd22b5", "type": "github" }, "original": { @@ -10021,19 +12702,19 @@ "cardano-repo-tool": "cardano-repo-tool_6", "gitignore-nix": "gitignore-nix_6", "hackage-nix": "hackage-nix_6", - "haskell-language-server": "haskell-language-server_17", + "haskell-language-server": "haskell-language-server_12", "haskell-nix": "haskell-nix_12", "iohk-nix": "iohk-nix_12", - "nixpkgs": "nixpkgs_28", + "nixpkgs": "nixpkgs_24", "pre-commit-hooks-nix": "pre-commit-hooks-nix_6", "sphinxcontrib-haddock": "sphinxcontrib-haddock_6" }, "locked": { - "lastModified": 1653669501, - "narHash": "sha256-qJrjEeo9Jmar1TwihDFzKQNC1ui4M03iClJM1zMd5Uk=", + "lastModified": 1656595231, + "narHash": "sha256-3EBhSroECMOSP02qZGT0Zb3QHWibI/tYjdcaT5/YotY=", "owner": "input-output-hk", "repo": "plutus", - "rev": "fed48a71550a12290efc84eefb74305d93cde69d", + "rev": "b39a526e983cb931d0cc49b7d073d6d43abd22b5", "type": "github" }, "original": { @@ -10047,19 +12728,19 @@ "cardano-repo-tool": "cardano-repo-tool_7", "gitignore-nix": "gitignore-nix_7", "hackage-nix": "hackage-nix_7", - "haskell-language-server": "haskell-language-server_21", + "haskell-language-server": "haskell-language-server_14", "haskell-nix": "haskell-nix_14", "iohk-nix": "iohk-nix_14", - "nixpkgs": "nixpkgs_33", + "nixpkgs": "nixpkgs_28", "pre-commit-hooks-nix": "pre-commit-hooks-nix_7", "sphinxcontrib-haddock": "sphinxcontrib-haddock_7" }, "locked": { - "lastModified": 1653669501, - "narHash": "sha256-qJrjEeo9Jmar1TwihDFzKQNC1ui4M03iClJM1zMd5Uk=", + "lastModified": 1656595231, + "narHash": "sha256-3EBhSroECMOSP02qZGT0Zb3QHWibI/tYjdcaT5/YotY=", "owner": "input-output-hk", "repo": "plutus", - "rev": "fed48a71550a12290efc84eefb74305d93cde69d", + "rev": "b39a526e983cb931d0cc49b7d073d6d43abd22b5", "type": "github" }, "original": { @@ -10073,19 +12754,19 @@ "cardano-repo-tool": "cardano-repo-tool_8", "gitignore-nix": "gitignore-nix_8", "hackage-nix": "hackage-nix_8", - "haskell-language-server": "haskell-language-server_24", + "haskell-language-server": "haskell-language-server_16", "haskell-nix": "haskell-nix_16", "iohk-nix": "iohk-nix_16", - "nixpkgs": "nixpkgs_38", + "nixpkgs": "nixpkgs_32", "pre-commit-hooks-nix": "pre-commit-hooks-nix_8", "sphinxcontrib-haddock": "sphinxcontrib-haddock_8" }, "locked": { - "lastModified": 1653669501, - "narHash": "sha256-qJrjEeo9Jmar1TwihDFzKQNC1ui4M03iClJM1zMd5Uk=", + "lastModified": 1656595231, + "narHash": "sha256-3EBhSroECMOSP02qZGT0Zb3QHWibI/tYjdcaT5/YotY=", "owner": "input-output-hk", "repo": "plutus", - "rev": "fed48a71550a12290efc84eefb74305d93cde69d", + "rev": "b39a526e983cb931d0cc49b7d073d6d43abd22b5", "type": "github" }, "original": { @@ -10099,19 +12780,19 @@ "cardano-repo-tool": "cardano-repo-tool_9", "gitignore-nix": "gitignore-nix_9", "hackage-nix": "hackage-nix_9", - "haskell-language-server": "haskell-language-server_26", + "haskell-language-server": "haskell-language-server_18", "haskell-nix": "haskell-nix_18", "iohk-nix": "iohk-nix_18", - "nixpkgs": "nixpkgs_43", + "nixpkgs": "nixpkgs_37", "pre-commit-hooks-nix": "pre-commit-hooks-nix_9", "sphinxcontrib-haddock": "sphinxcontrib-haddock_9" }, "locked": { - "lastModified": 1653669501, - "narHash": "sha256-qJrjEeo9Jmar1TwihDFzKQNC1ui4M03iClJM1zMd5Uk=", + "lastModified": 1656595231, + "narHash": "sha256-3EBhSroECMOSP02qZGT0Zb3QHWibI/tYjdcaT5/YotY=", "owner": "input-output-hk", "repo": "plutus", - "rev": "fed48a71550a12290efc84eefb74305d93cde69d", + "rev": "b39a526e983cb931d0cc49b7d073d6d43abd22b5", "type": "github" }, "original": { @@ -10152,6 +12833,86 @@ "type": "github" } }, + "pre-commit-hooks-nix_11": { + "flake": false, + "locked": { + "lastModified": 1624971177, + "narHash": "sha256-Amf/nBj1E77RmbSSmV+hg6YOpR+rddCbbVgo5C7BS0I=", + "owner": "cachix", + "repo": "pre-commit-hooks.nix", + "rev": "397f0713d007250a2c7a745e555fa16c5dc8cadb", + "type": "github" + }, + "original": { + "owner": "cachix", + "repo": "pre-commit-hooks.nix", + "type": "github" + } + }, + "pre-commit-hooks-nix_12": { + "flake": false, + "locked": { + "lastModified": 1624971177, + "narHash": "sha256-Amf/nBj1E77RmbSSmV+hg6YOpR+rddCbbVgo5C7BS0I=", + "owner": "cachix", + "repo": "pre-commit-hooks.nix", + "rev": "397f0713d007250a2c7a745e555fa16c5dc8cadb", + "type": "github" + }, + "original": { + "owner": "cachix", + "repo": "pre-commit-hooks.nix", + "type": "github" + } + }, + "pre-commit-hooks-nix_13": { + "flake": false, + "locked": { + "lastModified": 1624971177, + "narHash": "sha256-Amf/nBj1E77RmbSSmV+hg6YOpR+rddCbbVgo5C7BS0I=", + "owner": "cachix", + "repo": "pre-commit-hooks.nix", + "rev": "397f0713d007250a2c7a745e555fa16c5dc8cadb", + "type": "github" + }, + "original": { + "owner": "cachix", + "repo": "pre-commit-hooks.nix", + "type": "github" + } + }, + "pre-commit-hooks-nix_14": { + "flake": false, + "locked": { + "lastModified": 1624971177, + "narHash": "sha256-Amf/nBj1E77RmbSSmV+hg6YOpR+rddCbbVgo5C7BS0I=", + "owner": "cachix", + "repo": "pre-commit-hooks.nix", + "rev": "397f0713d007250a2c7a745e555fa16c5dc8cadb", + "type": "github" + }, + "original": { + "owner": "cachix", + "repo": "pre-commit-hooks.nix", + "type": "github" + } + }, + "pre-commit-hooks-nix_15": { + "flake": false, + "locked": { + "lastModified": 1624971177, + "narHash": "sha256-Amf/nBj1E77RmbSSmV+hg6YOpR+rddCbbVgo5C7BS0I=", + "owner": "cachix", + "repo": "pre-commit-hooks.nix", + "rev": "397f0713d007250a2c7a745e555fa16c5dc8cadb", + "type": "github" + }, + "original": { + "owner": "cachix", + "repo": "pre-commit-hooks.nix", + "type": "github" + } + }, "pre-commit-hooks-nix_2": { "flake": false, "locked": { @@ -10299,17 +13060,96 @@ "protolude_10": { "flake": false, "locked": { - "lastModified": 1637276813, - "narHash": "sha256-/mgR1Vyp1WYBjdkbwQycrf6lcmOgUFcYUZIMhVgYhdo=", + "lastModified": 1647139352, + "narHash": "sha256-JyHAQfTTUswP8MeGEZibx/2/v01Q7cU5mNpnmDazh24=", + "owner": "protolude", + "repo": "protolude", + "rev": "3e249724fd0ead27370c8c297b1ecd38f92cbd5b", + "type": "github" + }, + "original": { + "owner": "protolude", + "repo": "protolude", + "type": "github" + } + }, + "protolude_11": { + "flake": false, + "locked": { + "lastModified": 1647139352, + "narHash": "sha256-JyHAQfTTUswP8MeGEZibx/2/v01Q7cU5mNpnmDazh24=", + "owner": "protolude", + "repo": "protolude", + "rev": "3e249724fd0ead27370c8c297b1ecd38f92cbd5b", + "type": "github" + }, + "original": { + "owner": "protolude", + "repo": "protolude", + "type": "github" + } + }, + "protolude_12": { + "flake": false, + "locked": { + "lastModified": 1647139352, + "narHash": "sha256-JyHAQfTTUswP8MeGEZibx/2/v01Q7cU5mNpnmDazh24=", + "owner": "protolude", + "repo": "protolude", + "rev": "3e249724fd0ead27370c8c297b1ecd38f92cbd5b", + "type": "github" + }, + "original": { + "owner": "protolude", + "repo": "protolude", + "type": "github" + } + }, + "protolude_13": { + "flake": false, + "locked": { + "lastModified": 1647139352, + "narHash": "sha256-JyHAQfTTUswP8MeGEZibx/2/v01Q7cU5mNpnmDazh24=", + "owner": "protolude", + "repo": "protolude", + "rev": "3e249724fd0ead27370c8c297b1ecd38f92cbd5b", + "type": "github" + }, + "original": { + "owner": "protolude", + "repo": "protolude", + "type": "github" + } + }, + "protolude_14": { + "flake": false, + "locked": { + "lastModified": 1647139352, + "narHash": "sha256-JyHAQfTTUswP8MeGEZibx/2/v01Q7cU5mNpnmDazh24=", + "owner": "protolude", + "repo": "protolude", + "rev": "3e249724fd0ead27370c8c297b1ecd38f92cbd5b", + "type": "github" + }, + "original": { + "owner": "protolude", + "repo": "protolude", + "type": "github" + } + }, + "protolude_15": { + "flake": false, + "locked": { + "lastModified": 1647139352, + "narHash": "sha256-JyHAQfTTUswP8MeGEZibx/2/v01Q7cU5mNpnmDazh24=", "owner": "protolude", "repo": "protolude", - "rev": "d821ef0ac7552cfa2c3e7a7bdf29539f57e3fae6", + "rev": "3e249724fd0ead27370c8c297b1ecd38f92cbd5b", "type": "github" }, "original": { "owner": "protolude", "repo": "protolude", - "rev": "d821ef0ac7552cfa2c3e7a7bdf29539f57e3fae6", "type": "github" } }, @@ -10443,25 +13283,135 @@ }, "root": { "inputs": { + "haskell-language-server": [ + "plutarch", + "haskell-language-server" + ], "haskell-nix": [ "plutarch", "haskell-nix" ], + "haskell-nix-extra-hackage": [ + "plutarch", + "haskell-nix-extra-hackage" + ], + "iohk-nix": [ + "plutarch", + "iohk-nix" + ], + "liqwid-nix": "liqwid-nix", "liqwid-plutarch-extra": "liqwid-plutarch-extra", "nixpkgs": [ "plutarch", "nixpkgs" ], - "nixpkgs-2111": "nixpkgs-2111_5", - "nixpkgs-latest": "nixpkgs-latest_5", - "plutarch": "plutarch_3", - "plutarch-context-builder": "plutarch-context-builder", - "plutarch-numeric": "plutarch-numeric", + "nixpkgs-2111": "nixpkgs-2111_9", + "nixpkgs-latest": "nixpkgs-latest_9", + "plutarch": "plutarch_5", + "plutarch-context-builder": "plutarch-context-builder_2", + "plutarch-numeric": "plutarch-numeric_2", "plutarch-quickcheck": "plutarch-quickcheck_2", - "plutarch-safe-money": "plutarch-safe-money" + "plutarch-safe-money": "plutarch-safe-money", + "plutarch-script-export": "plutarch-script-export" + } + }, + "secp256k1-haskell": { + "flake": false, + "locked": { + "lastModified": 1650290419, + "narHash": "sha256-XrjiqCC7cNTFib78gdMPGNettAkwAxQlbC/n+/mRFt4=", + "owner": "haskoin", + "repo": "secp256k1-haskell", + "rev": "3df963ab6ae14ec122691a97af09a7331511a387", + "type": "github" + }, + "original": { + "owner": "haskoin", + "repo": "secp256k1-haskell", + "type": "github" + } + }, + "secp256k1-haskell_10": { + "flake": false, + "locked": { + "lastModified": 1650290419, + "narHash": "sha256-XrjiqCC7cNTFib78gdMPGNettAkwAxQlbC/n+/mRFt4=", + "owner": "haskoin", + "repo": "secp256k1-haskell", + "rev": "3df963ab6ae14ec122691a97af09a7331511a387", + "type": "github" + }, + "original": { + "owner": "haskoin", + "repo": "secp256k1-haskell", + "type": "github" + } + }, + "secp256k1-haskell_11": { + "flake": false, + "locked": { + "lastModified": 1650290419, + "narHash": "sha256-XrjiqCC7cNTFib78gdMPGNettAkwAxQlbC/n+/mRFt4=", + "owner": "haskoin", + "repo": "secp256k1-haskell", + "rev": "3df963ab6ae14ec122691a97af09a7331511a387", + "type": "github" + }, + "original": { + "owner": "haskoin", + "repo": "secp256k1-haskell", + "type": "github" + } + }, + "secp256k1-haskell_12": { + "flake": false, + "locked": { + "lastModified": 1650290419, + "narHash": "sha256-XrjiqCC7cNTFib78gdMPGNettAkwAxQlbC/n+/mRFt4=", + "owner": "haskoin", + "repo": "secp256k1-haskell", + "rev": "3df963ab6ae14ec122691a97af09a7331511a387", + "type": "github" + }, + "original": { + "owner": "haskoin", + "repo": "secp256k1-haskell", + "type": "github" + } + }, + "secp256k1-haskell_13": { + "flake": false, + "locked": { + "lastModified": 1650290419, + "narHash": "sha256-XrjiqCC7cNTFib78gdMPGNettAkwAxQlbC/n+/mRFt4=", + "owner": "haskoin", + "repo": "secp256k1-haskell", + "rev": "3df963ab6ae14ec122691a97af09a7331511a387", + "type": "github" + }, + "original": { + "owner": "haskoin", + "repo": "secp256k1-haskell", + "type": "github" + } + }, + "secp256k1-haskell_14": { + "flake": false, + "locked": { + "lastModified": 1650290419, + "narHash": "sha256-XrjiqCC7cNTFib78gdMPGNettAkwAxQlbC/n+/mRFt4=", + "owner": "haskoin", + "repo": "secp256k1-haskell", + "rev": "3df963ab6ae14ec122691a97af09a7331511a387", + "type": "github" + }, + "original": { + "owner": "haskoin", + "repo": "secp256k1-haskell", + "type": "github" } }, - "secp256k1-haskell": { + "secp256k1-haskell_15": { "flake": false, "locked": { "lastModified": 1650290419, @@ -10605,24 +13555,23 @@ "type": "github" } }, - "sized-functors": { + "sphinxcontrib-haddock": { "flake": false, "locked": { - "lastModified": 1620614934, - "narHash": "sha256-pVJbEGF4/lvXmWIypwkMQBYygOx3TQwLJbMpfdYovdY=", - "owner": "JonasDuregard", - "repo": "sized-functors", - "rev": "fe6bf78a1b97ff7429630d0e8974c9bc40945dcf", + "lastModified": 1594136664, + "narHash": "sha256-O9YT3iCUBHP3CEF88VDLLCO2HSP3HqkNA2q2939RnVY=", + "owner": "michaelpj", + "repo": "sphinxcontrib-haddock", + "rev": "f3956b3256962b2d27d5a4e96edb7951acf5de34", "type": "github" }, "original": { - "owner": "JonasDuregard", - "repo": "sized-functors", - "rev": "fe6bf78a1b97ff7429630d0e8974c9bc40945dcf", + "owner": "michaelpj", + "repo": "sphinxcontrib-haddock", "type": "github" } }, - "sphinxcontrib-haddock": { + "sphinxcontrib-haddock_10": { "flake": false, "locked": { "lastModified": 1594136664, @@ -10638,7 +13587,71 @@ "type": "github" } }, - "sphinxcontrib-haddock_10": { + "sphinxcontrib-haddock_11": { + "flake": false, + "locked": { + "lastModified": 1594136664, + "narHash": "sha256-O9YT3iCUBHP3CEF88VDLLCO2HSP3HqkNA2q2939RnVY=", + "owner": "michaelpj", + "repo": "sphinxcontrib-haddock", + "rev": "f3956b3256962b2d27d5a4e96edb7951acf5de34", + "type": "github" + }, + "original": { + "owner": "michaelpj", + "repo": "sphinxcontrib-haddock", + "type": "github" + } + }, + "sphinxcontrib-haddock_12": { + "flake": false, + "locked": { + "lastModified": 1594136664, + "narHash": "sha256-O9YT3iCUBHP3CEF88VDLLCO2HSP3HqkNA2q2939RnVY=", + "owner": "michaelpj", + "repo": "sphinxcontrib-haddock", + "rev": "f3956b3256962b2d27d5a4e96edb7951acf5de34", + "type": "github" + }, + "original": { + "owner": "michaelpj", + "repo": "sphinxcontrib-haddock", + "type": "github" + } + }, + "sphinxcontrib-haddock_13": { + "flake": false, + "locked": { + "lastModified": 1594136664, + "narHash": "sha256-O9YT3iCUBHP3CEF88VDLLCO2HSP3HqkNA2q2939RnVY=", + "owner": "michaelpj", + "repo": "sphinxcontrib-haddock", + "rev": "f3956b3256962b2d27d5a4e96edb7951acf5de34", + "type": "github" + }, + "original": { + "owner": "michaelpj", + "repo": "sphinxcontrib-haddock", + "type": "github" + } + }, + "sphinxcontrib-haddock_14": { + "flake": false, + "locked": { + "lastModified": 1594136664, + "narHash": "sha256-O9YT3iCUBHP3CEF88VDLLCO2HSP3HqkNA2q2939RnVY=", + "owner": "michaelpj", + "repo": "sphinxcontrib-haddock", + "rev": "f3956b3256962b2d27d5a4e96edb7951acf5de34", + "type": "github" + }, + "original": { + "owner": "michaelpj", + "repo": "sphinxcontrib-haddock", + "type": "github" + } + }, + "sphinxcontrib-haddock_15": { "flake": false, "locked": { "lastModified": 1594136664, @@ -10798,14 +13811,14 @@ "type": "github" } }, - "stackage-nix": { + "stackage_10": { "flake": false, "locked": { - "lastModified": 1597712578, - "narHash": "sha256-c/pcfZ6w5Yp//7oC0hErOGVVphBLc5vc4IZlWKZ/t6E=", + "lastModified": 1654046327, + "narHash": "sha256-IxX46Dh4OZpF3k7KPMa3tZSScYYGqFxXpCnMc0QRkuQ=", "owner": "input-output-hk", "repo": "stackage.nix", - "rev": "e32c8b06d56954865725514ce0d98d5d1867e43a", + "rev": "cc1d778723fcd431f9b2ed632a50c610c3e38b54", "type": "github" }, "original": { @@ -10814,14 +13827,14 @@ "type": "github" } }, - "stackage_10": { + "stackage_11": { "flake": false, "locked": { - "lastModified": 1644887829, - "narHash": "sha256-tjUXJpqB7MMnqM4FF5cdtZipfratUcTKRQVA6F77sEQ=", + "lastModified": 1654046327, + "narHash": "sha256-IxX46Dh4OZpF3k7KPMa3tZSScYYGqFxXpCnMc0QRkuQ=", "owner": "input-output-hk", "repo": "stackage.nix", - "rev": "db8bdef6588cf4f38e6069075ba76f0024381f68", + "rev": "cc1d778723fcd431f9b2ed632a50c610c3e38b54", "type": "github" }, "original": { @@ -10830,7 +13843,7 @@ "type": "github" } }, - "stackage_2": { + "stackage_12": { "flake": false, "locked": { "lastModified": 1654046327, @@ -10846,7 +13859,7 @@ "type": "github" } }, - "stackage_3": { + "stackage_13": { "flake": false, "locked": { "lastModified": 1654046327, @@ -10862,7 +13875,7 @@ "type": "github" } }, - "stackage_4": { + "stackage_14": { "flake": false, "locked": { "lastModified": 1654046327, @@ -10878,7 +13891,7 @@ "type": "github" } }, - "stackage_5": { + "stackage_15": { "flake": false, "locked": { "lastModified": 1654046327, @@ -10894,7 +13907,7 @@ "type": "github" } }, - "stackage_6": { + "stackage_2": { "flake": false, "locked": { "lastModified": 1654046327, @@ -10910,7 +13923,7 @@ "type": "github" } }, - "stackage_7": { + "stackage_3": { "flake": false, "locked": { "lastModified": 1654046327, @@ -10926,7 +13939,7 @@ "type": "github" } }, - "stackage_8": { + "stackage_4": { "flake": false, "locked": { "lastModified": 1654046327, @@ -10942,7 +13955,7 @@ "type": "github" } }, - "stackage_9": { + "stackage_5": { "flake": false, "locked": { "lastModified": 1654046327, @@ -10958,282 +13971,67 @@ "type": "github" } }, - "tailwind-haskell": { - "inputs": { - "ema": [ - "liqwid-plutarch-extra", - "plutarch", - "emanote", - "ema" - ], - "flake-compat": "flake-compat_2", - "flake-utils": "flake-utils_2", - "nixpkgs": "nixpkgs_2" - }, - "locked": { - "lastModified": 1653230344, - "narHash": "sha256-MNwayqvZHsIsP1uyqwQFvzcfFGBMejzZOqAapDjrV5I=", - "owner": "srid", - "repo": "tailwind-haskell", - "rev": "0fb8a18b0e770bafc17521836658f31c56e6dfdb", - "type": "github" - }, - "original": { - "owner": "srid", - "ref": "master", - "repo": "tailwind-haskell", - "type": "github" - } - }, - "tailwind-haskell_2": { - "inputs": { - "ema": [ - "liqwid-plutarch-extra", - "plutarch-quickcheck", - "plutarch", - "emanote", - "ema" - ], - "flake-compat": "flake-compat_4", - "flake-utils": "flake-utils_5", - "nixpkgs": "nixpkgs_7" - }, - "locked": { - "lastModified": 1653230344, - "narHash": "sha256-MNwayqvZHsIsP1uyqwQFvzcfFGBMejzZOqAapDjrV5I=", - "owner": "srid", - "repo": "tailwind-haskell", - "rev": "0fb8a18b0e770bafc17521836658f31c56e6dfdb", - "type": "github" - }, - "original": { - "owner": "srid", - "ref": "master", - "repo": "tailwind-haskell", - "type": "github" - } - }, - "tailwind-haskell_3": { - "inputs": { - "ema": [ - "plutarch-context-builder", - "plutarch", - "emanote", - "ema" - ], - "flake-compat": "flake-compat_6", - "flake-utils": "flake-utils_9", - "nixpkgs": "nixpkgs_15" - }, - "locked": { - "lastModified": 1653230344, - "narHash": "sha256-MNwayqvZHsIsP1uyqwQFvzcfFGBMejzZOqAapDjrV5I=", - "owner": "srid", - "repo": "tailwind-haskell", - "rev": "0fb8a18b0e770bafc17521836658f31c56e6dfdb", - "type": "github" - }, - "original": { - "owner": "srid", - "ref": "master", - "repo": "tailwind-haskell", - "type": "github" - } - }, - "tailwind-haskell_4": { - "inputs": { - "ema": [ - "plutarch-numeric", - "plutarch", - "emanote", - "ema" - ], - "flake-compat": "flake-compat_8", - "flake-utils": "flake-utils_12", - "nixpkgs": "nixpkgs_20" - }, - "locked": { - "lastModified": 1653230344, - "narHash": "sha256-MNwayqvZHsIsP1uyqwQFvzcfFGBMejzZOqAapDjrV5I=", - "owner": "srid", - "repo": "tailwind-haskell", - "rev": "0fb8a18b0e770bafc17521836658f31c56e6dfdb", - "type": "github" - }, - "original": { - "owner": "srid", - "ref": "master", - "repo": "tailwind-haskell", - "type": "github" - } - }, - "tailwind-haskell_5": { - "inputs": { - "ema": [ - "plutarch-quickcheck", - "plutarch", - "emanote", - "ema" - ], - "flake-compat": "flake-compat_10", - "flake-utils": "flake-utils_15", - "nixpkgs": "nixpkgs_25" - }, - "locked": { - "lastModified": 1653230344, - "narHash": "sha256-MNwayqvZHsIsP1uyqwQFvzcfFGBMejzZOqAapDjrV5I=", - "owner": "srid", - "repo": "tailwind-haskell", - "rev": "0fb8a18b0e770bafc17521836658f31c56e6dfdb", - "type": "github" - }, - "original": { - "owner": "srid", - "ref": "master", - "repo": "tailwind-haskell", - "type": "github" - } - }, - "tailwind-haskell_6": { - "inputs": { - "ema": [ - "plutarch-safe-money", - "liqwid-plutarch-extra", - "plutarch", - "emanote", - "ema" - ], - "flake-compat": "flake-compat_12", - "flake-utils": "flake-utils_18", - "nixpkgs": "nixpkgs_30" - }, - "locked": { - "lastModified": 1653230344, - "narHash": "sha256-MNwayqvZHsIsP1uyqwQFvzcfFGBMejzZOqAapDjrV5I=", - "owner": "srid", - "repo": "tailwind-haskell", - "rev": "0fb8a18b0e770bafc17521836658f31c56e6dfdb", - "type": "github" - }, - "original": { - "owner": "srid", - "ref": "master", - "repo": "tailwind-haskell", - "type": "github" - } - }, - "tailwind-haskell_7": { - "inputs": { - "ema": [ - "plutarch-safe-money", - "liqwid-plutarch-extra", - "plutarch-quickcheck", - "plutarch", - "emanote", - "ema" - ], - "flake-compat": "flake-compat_14", - "flake-utils": "flake-utils_21", - "nixpkgs": "nixpkgs_35" - }, - "locked": { - "lastModified": 1653230344, - "narHash": "sha256-MNwayqvZHsIsP1uyqwQFvzcfFGBMejzZOqAapDjrV5I=", - "owner": "srid", - "repo": "tailwind-haskell", - "rev": "0fb8a18b0e770bafc17521836658f31c56e6dfdb", - "type": "github" - }, - "original": { - "owner": "srid", - "ref": "master", - "repo": "tailwind-haskell", - "type": "github" - } - }, - "tailwind-haskell_8": { - "inputs": { - "ema": [ - "plutarch-safe-money", - "plutarch", - "emanote", - "ema" - ], - "flake-compat": "flake-compat_16", - "flake-utils": "flake-utils_24", - "nixpkgs": "nixpkgs_40" - }, + "stackage_6": { + "flake": false, "locked": { - "lastModified": 1653230344, - "narHash": "sha256-MNwayqvZHsIsP1uyqwQFvzcfFGBMejzZOqAapDjrV5I=", - "owner": "srid", - "repo": "tailwind-haskell", - "rev": "0fb8a18b0e770bafc17521836658f31c56e6dfdb", + "lastModified": 1654046327, + "narHash": "sha256-IxX46Dh4OZpF3k7KPMa3tZSScYYGqFxXpCnMc0QRkuQ=", + "owner": "input-output-hk", + "repo": "stackage.nix", + "rev": "cc1d778723fcd431f9b2ed632a50c610c3e38b54", "type": "github" }, "original": { - "owner": "srid", - "ref": "master", - "repo": "tailwind-haskell", + "owner": "input-output-hk", + "repo": "stackage.nix", "type": "github" } }, - "tailwind-haskell_9": { - "inputs": { - "flake-compat": "flake-compat_19", - "flake-utils": "flake-utils_29", - "nixpkgs": "nixpkgs_46" - }, + "stackage_7": { + "flake": false, "locked": { - "lastModified": 1649519562, - "narHash": "sha256-IVZ4D7JkSCn0sjeTw5b0s2TTIU+g4hk78u1znXY4JjQ=", - "owner": "srid", - "repo": "tailwind-haskell", - "rev": "f5bfc15da3ee6e74a077579fb10269bb450fa5cb", + "lastModified": 1654046327, + "narHash": "sha256-IxX46Dh4OZpF3k7KPMa3tZSScYYGqFxXpCnMc0QRkuQ=", + "owner": "input-output-hk", + "repo": "stackage.nix", + "rev": "cc1d778723fcd431f9b2ed632a50c610c3e38b54", "type": "github" }, "original": { - "owner": "srid", - "ref": "master", - "repo": "tailwind-haskell", + "owner": "input-output-hk", + "repo": "stackage.nix", "type": "github" } }, - "th-extras": { + "stackage_8": { "flake": false, "locked": { - "lastModified": 1641329261, - "narHash": "sha256-+K91xH/zew66ry0EAV5FaEIAHUZdJ3ngD9GzCJiUq7k=", - "owner": "mokus0", - "repo": "th-extras", - "rev": "787ed752c1e5d41b5903b74e171ed087de38bffa", + "lastModified": 1654046327, + "narHash": "sha256-IxX46Dh4OZpF3k7KPMa3tZSScYYGqFxXpCnMc0QRkuQ=", + "owner": "input-output-hk", + "repo": "stackage.nix", + "rev": "cc1d778723fcd431f9b2ed632a50c610c3e38b54", "type": "github" }, "original": { - "owner": "mokus0", - "repo": "th-extras", - "rev": "787ed752c1e5d41b5903b74e171ed087de38bffa", + "owner": "input-output-hk", + "repo": "stackage.nix", "type": "github" } }, - "unionmount": { - "inputs": { - "flake-compat": "flake-compat_20", - "flake-utils": "flake-utils_30", - "nixpkgs": "nixpkgs_47" - }, + "stackage_9": { + "flake": false, "locked": { - "lastModified": 1649012450, - "narHash": "sha256-m0qlPd3jxjyDEkd7cQKLX0GT9a00qnvygec9GCBZ1hc=", - "owner": "srid", - "repo": "unionmount", - "rev": "27584567d9182c12018f988db899593a896f86ff", + "lastModified": 1654046327, + "narHash": "sha256-IxX46Dh4OZpF3k7KPMa3tZSScYYGqFxXpCnMc0QRkuQ=", + "owner": "input-output-hk", + "repo": "stackage.nix", + "rev": "cc1d778723fcd431f9b2ed632a50c610c3e38b54", "type": "github" }, "original": { - "owner": "srid", - "ref": "master", - "repo": "unionmount", + "owner": "input-output-hk", + "repo": "stackage.nix", "type": "github" } } diff --git a/flake.nix b/flake.nix index 2573c319..d60ca23a 100644 --- a/flake.nix +++ b/flake.nix @@ -1,253 +1,109 @@ { description = "agora"; - inputs.nixpkgs.follows = "plutarch/nixpkgs"; - inputs.haskell-nix.follows = "plutarch/haskell-nix"; - inputs.nixpkgs-latest.url = "github:NixOS/nixpkgs?rev=a0a69be4b5ee63f1b5e75887a406e9194012b492"; - # temporary fix for nix versions that have the transitive follows bug - # see https://github.com/NixOS/nix/issues/6013 - inputs.nixpkgs-2111 = { url = "github:NixOS/nixpkgs/nixpkgs-21.11-darwin"; }; - - # Plutarch and its friends - inputs.plutarch.url = - "github:liqwid-labs/plutarch?rev=e7ef565645146e26e75ec29fe97122a74e52c6b7"; - inputs.plutarch.inputs.emanote.follows = - "plutarch/haskell-nix/nixpkgs-unstable"; - inputs.plutarch.inputs.nixpkgs.follows = - "plutarch/haskell-nix/nixpkgs-unstable"; - - inputs.liqwid-plutarch-extra.url = - "github:Liqwid-Labs/liqwid-plutarch-extra?ref=main"; - inputs.plutarch-numeric.url = - "github:Liqwid-Labs/plutarch-numeric?ref=main"; - inputs.plutarch-safe-money.url = - "github:Liqwid-Labs/plutarch-safe-money?rev=9f968b80189c7e4b335527cd5b103dc26952f667"; - - # Testing - inputs.plutarch-quickcheck.url = - "github:liqwid-labs/plutarch-quickcheck?ref=staging"; - inputs.plutarch-context-builder.url = - "github:Liqwid-Labs/plutarch-context-builder?ref=staging"; + inputs = { + nixpkgs.follows = "plutarch/nixpkgs"; + nixpkgs-latest.url = "github:NixOS/nixpkgs?rev=cf63df0364f67848083ff75bc8ac9b7ca7aa5a01"; + # temporary fix for nix versions that have the transitive follows bug + # see https://github.com/NixOS/nix/issues/6013 + nixpkgs-2111 = { url = "github:NixOS/nixpkgs/nixpkgs-21.11-darwin"; }; + + haskell-nix-extra-hackage.follows = "plutarch/haskell-nix-extra-hackage"; + haskell-nix.follows = "plutarch/haskell-nix"; + iohk-nix.follows = "plutarch/iohk-nix"; + haskell-language-server.follows = "plutarch/haskell-language-server"; + + # Plutarch and its friends + plutarch = { + url = "github:Plutonomicon/plutarch-plutus?ref=staging"; + + inputs.emanote.follows = + "plutarch/haskell-nix/nixpkgs-unstable"; + inputs.nixpkgs.follows = + "plutarch/haskell-nix/nixpkgs-unstable"; + }; - outputs = inputs@{ self, nixpkgs, nixpkgs-latest, haskell-nix, plutarch, ... }: + plutarch-numeric.url = + "github:Liqwid-Labs/plutarch-numeric?ref=main"; + plutarch-safe-money.url = + "github:Liqwid-Labs/plutarch-safe-money?ref=main"; + liqwid-plutarch-extra.url = + "github:Liqwid-Labs/liqwid-plutarch-extra?ref=plutus-v1"; + plutarch-quickcheck.url = + "github:liqwid-labs/plutarch-quickcheck?ref=staging"; + plutarch-context-builder.url = + "github:Liqwid-Labs/plutarch-context-builder?ref=plutus-v1"; + plutarch-script-export.url = + "github:Liqwid-Labs/plutarch-script-export?ref=main"; + + liqwid-nix.url = "github:Liqwid-Labs/liqwid-nix?ref=main"; + }; + + outputs = inputs@{ liqwid-nix, ... }: let - supportedSystems = nixpkgs-latest.lib.systems.flakeExposed; - - perSystem = nixpkgs.lib.genAttrs supportedSystems; - - pkgsFor = system: import nixpkgs { - inherit system; - overlays = [ haskell-nix.overlay (import "${plutarch.inputs.iohk-nix}/overlays/crypto") ]; - # This only does bad things for us... - # inherit (haskell-nix) config; - }; - pkgsFor' = system: import nixpkgs-latest { inherit system; }; - - fourmoluFor = system: (pkgsFor' system).haskell.packages.ghc922.fourmolu_0_6_0_0; - - defaultGhcVersion = "ghc923"; - - nonReinstallablePkgs = [ - "array" - "array" - "base" - "binary" - "bytestring" - "Cabal" - "containers" - "deepseq" - "directory" - "exceptions" - "filepath" - "ghc" - "ghc-bignum" - "ghc-boot" - "ghc-boot" - "ghc-boot-th" - "ghc-compact" - "ghc-heap" - # "ghci" - # "haskeline" - "ghcjs-prim" - "ghcjs-th" - "ghc-prim" - "ghc-prim" - "hpc" - "integer-gmp" - "integer-simple" - "mtl" - "parsec" - "pretty" - "process" - "rts" - "stm" - "template-haskell" - "terminfo" - "text" - "time" - "transformers" - "unix" - "Win32" - "xhtml" - ]; - - haskellModules = [ - ({ config, pkgs, hsPkgs, ... }: { - inherit nonReinstallablePkgs; # Needed for a lot of different things - packages = { - cardano-binary.doHaddock = false; - cardano-binary.ghcOptions = [ "-Wwarn" ]; - cardano-crypto-class.components.library.pkgconfig = pkgs.lib.mkForce [ [ pkgs.libsodium-vrf ] ]; - cardano-crypto-class.doHaddock = false; - cardano-crypto-class.ghcOptions = [ "-Wwarn" ]; - cardano-crypto-praos.components.library.pkgconfig = pkgs.lib.mkForce [ [ pkgs.libsodium-vrf ] ]; - cardano-prelude.doHaddock = false; # somehow above options are not applied? - cardano-prelude.ghcOptions = [ "-Wwarn" ]; - # Workaround missing support for build-tools: - # https://github.com/input-output-hk/haskell.nix/issues/231 - plutarch-test.components.exes.plutarch-test.build-tools = [ - config.hsPkgs.hspec-discover - ]; + benchCheckOverlay = self: super: { + toFlake = + let + inherit (self) inputs perSystem pkgsFor'; + flake = super.toFlake or { }; + name = "benchCheck"; + in + flake // { + checks = perSystem (system: + flake.checks.${system} // { + ${name} = + let + pkgs' = pkgsFor' system; + bench = flake.packages.${system}."agora:bench:agora-bench"; + in + pkgs'.runCommand name + { + nativeBuildInputs = [ pkgs'.diffutils ]; + } '' + export LC_CTYPE=C.UTF-8 + export LC_ALL=C.UTF-8 + export LANG=C.UTF-8 + cd ${inputs.self} + ${bench}/bin/agora-bench | diff bench.csv - \ + || (echo "bench.csv is outdated"; exit 1) + mkdir "$out" + ''; + }); }; - }) - ]; - - myhackage = system: compiler-nix-name: plutarch.inputs.haskell-nix-extra-hackage.mkHackageFor system compiler-nix-name ( - [ - "${inputs.plutarch.inputs.flat}" - "${inputs.plutarch.inputs.protolude}" - "${inputs.plutarch.inputs.cardano-prelude}/cardano-prelude" - "${inputs.plutarch.inputs.cardano-crypto}" - "${inputs.plutarch.inputs.cardano-base}/binary" - "${inputs.plutarch.inputs.cardano-base}/cardano-crypto-class" - "${inputs.plutarch.inputs.plutus}/plutus-core" - "${inputs.plutarch.inputs.plutus}/plutus-ledger-api" - "${inputs.plutarch.inputs.plutus}/plutus-tx" - "${inputs.plutarch.inputs.plutus}/prettyprinter-configurable" - "${inputs.plutarch.inputs.plutus}/word-array" - "${inputs.plutarch.inputs.secp256k1-haskell}" - "${inputs.plutarch.inputs.plutus}/plutus-tx-plugin" # necessary for FFI tests - - # Custom deps as a consumer - "${inputs.plutarch}" - "${inputs.plutarch}/plutarch-extra" - "${inputs.liqwid-plutarch-extra}" + }; + in + (liqwid-nix.buildProject + { + inherit inputs; + src = ./.; + } + [ + liqwid-nix.haskellProject + liqwid-nix.plutarchProject + (liqwid-nix.addDependencies [ "${inputs.plutarch-numeric}" "${inputs.plutarch-safe-money}" "${inputs.plutarch-quickcheck}" "${inputs.plutarch-context-builder}" - ] - ); - - applyDep = pkgs: o: - let h = myhackage pkgs.system o.compiler-nix-name; in - (plutarch.applyPlutarchDep pkgs o) // { - modules = haskellModules ++ [ h.module ] ++ (o.modules or [ ]); - extra-hackages = [ (import h.hackageNix) ] ++ (o.extra-hackages or [ ]); - extra-hackage-tarballs = { _xNJUd_plutarch-hackage = h.hackageTarball; } // (o.extra-hackage-tarballs or { }); - }; - - projectForGhc = compiler-nix-name: system: - let pkgs = pkgsFor system; in - let pkgs' = pkgsFor' system; in - let pkgSet = pkgs.haskell-nix.cabalProject' (applyDep pkgs { - src = ./.; - inherit compiler-nix-name; - modules = [ ]; - shell = { - withHoogle = true; - - exactDeps = true; - - # We use the ones from Nixpkgs, since they are cached reliably. - # Eventually we will probably want to build these with haskell.nix. - nativeBuildInputs = [ - pkgs'.cabal-install - pkgs'.hlint - pkgs'.haskellPackages.cabal-fmt - (fourmoluFor system) - pkgs'.nixpkgs-fmt - (plutarch.hlsFor compiler-nix-name system) - ]; - }; - }); in - pkgSet; - - projectFor = projectForGhc defaultGhcVersion; - - formatCheckFor = system: - let - pkgs' = pkgsFor' system; - in - pkgs'.runCommand "format-check" - { - nativeBuildInputs = [ pkgs'.haskellPackages.cabal-fmt pkgs'.nixpkgs-fmt (fourmoluFor system) pkgs'.hlint ]; - } '' - export LC_CTYPE=C.UTF-8 - export LC_ALL=C.UTF-8 - export LANG=C.UTF-8 - cd ${self} - make format_check || (echo " Please run 'make format'" ; exit 1) - find -name '*.hs' -not -path './dist*/*' -not -path './haddock/*' | xargs hlint - mkdir $out - '' - ; - - benchCheckFor = system: agora-bench: - let - pkgs = pkgsFor system; - pkgs' = pkgsFor' system; - in - pkgs.runCommand "bench-check" - { - bench = "${agora-bench}/bin/agora-bench"; - nativeBuildInputs = [ - pkgs'.diffutils - ]; - } '' - export LC_CTYPE=C.UTF-8 - export LC_ALL=C.UTF-8 - export LANG=C.UTF-8 - cd ${self} - make bench_check || (echo " Please run 'make bench'" ; exit 1) - mkdir $out - ''; - in - { - project = perSystem projectFor; - flake = perSystem (system: (projectFor system).flake { }); - - packages = perSystem (system: - self.flake.${system}.packages // { - haddock = - let - agora-doc = self.flake.${system}.packages."agora:lib:agora".doc; - pkgs = pkgsFor system; - in - pkgs.runCommand "haddock-merge" { } '' - cd ${self} - mkdir $out - cp -r ${agora-doc}/share/doc/* $out - ''; - }); - - # Define what we want to test - checks = perSystem (system: - self.flake.${system}.checks // { - formatCheck = formatCheckFor system; - # benchCheck = benchCheckFor system self.flake.${system}.packages."agora:bench:agora-bench"; - agora = self.flake.${system}.packages."agora:lib:agora"; - agora-test = self.flake.${system}.packages."agora:test:agora-test"; - benchCheck = benchCheckFor system self.flake.${system}.packages."agora:bench:agora-bench"; - }); - check = perSystem (system: - (pkgsFor system).runCommand "combined-test" - { - checksss = builtins.attrValues self.checks.${system}; - } '' - echo $checksss - touch $out - ''); - devShell = perSystem (system: self.flake.${system}.devShell); - }; + "${inputs.liqwid-plutarch-extra}" + "${inputs.plutarch-script-export}" + ]) + (liqwid-nix.enableFormatCheck [ + "-XQuasiQuotes" + "-XTemplateHaskell" + "-XTypeApplications" + "-XImportQualifiedPost" + "-XPatternSynonyms" + "-XOverloadedRecordDot" + ]) + liqwid-nix.enableLintCheck + liqwid-nix.enableCabalFormatCheck + liqwid-nix.enableNixFormatCheck + liqwid-nix.addBuildChecks + (liqwid-nix.addCommandLineTools (pkgs: _: [ + pkgs.haskellPackages.hasktags + ])) + benchCheckOverlay + ] + ).toFlake; }