diff --git a/.github/workflows/ci-oci.yaml b/.github/workflows/ci-oci.yaml new file mode 100644 index 0000000..1d759f6 --- /dev/null +++ b/.github/workflows/ci-oci.yaml @@ -0,0 +1,48 @@ +# https://github.com/marketplace/actions/install-nix + +# Builds oci container in a rather convoluted way. + +name: "ci-oci" +on: + pull_request: + push: + +concurrency: + group: ${{ github.ref }} + cancel-in-progress: true + +jobs: + tests: + runs-on: ubuntu-latest + steps: + + - uses: actions/checkout@v4 + + - name: Install nix + uses: cachix/install-nix-action@v27 + + # https://github.com/marketplace/actions/cache-nix-store + - name: Restore and cache Nix store + uses: nix-community/cache-nix-action@v5 + with: + # restore and save a cache using this key + # TODO: Also hash the cabal.config and *cabal files, since we depend on them + primary-key: nix-${{ runner.os }}-${{ hashFiles('**/*.nix') }} + # if there's no cache hit, restore a cache by this prefix + restore-prefixes-first-match: nix-${{ runner.os }}- + # collect garbage until Nix store size (in bytes) is at most this number + # before trying to save a new cache + gc-max-store-size-linux: 1073741824 + # do purge caches + purge: true + # purge all versions of the cache + purge-prefixes: cache-${{ runner.os }}- + # created more than this number of seconds ago relative to the start of the `Post Restore` phase + purge-created: 0 + # except the version with the `primary-key`, if it exists + purge-primary-key: never + + - run: nix build --accept-flake-config .#containers.x86_64-linux.wst.copyTo + - run: ./result/bin/copy-to oci-archive:oci.tar + - run: ls -alh oci.tar + diff --git a/nix/containers.nix b/nix/containers.nix new file mode 100644 index 0000000..8790466 --- /dev/null +++ b/nix/containers.nix @@ -0,0 +1,18 @@ +{ repoRoot, inputs, pkgs, lib, system }: +{ + + # Builds a docker container for the cabal executable given as input. First we + # build the container json itself. Note the explicit architecture. + # + # $ nix build .#containers.x86_64-linux.wst + # + wst = lib.iogx.mkContainerFromCabalExe { + exe = inputs.self.packages.wst-poc; + name = "wst-poc"; + description = "WST Proof of Concept"; + packages = [ ]; + sourceUrl = "https://github.com/input-output-hk/wsc-poc"; + }; + +} + diff --git a/nix/outputs.nix b/nix/outputs.nix index 0d779d2..258aea1 100644 --- a/nix/outputs.nix +++ b/nix/outputs.nix @@ -1,9 +1,9 @@ { repoRoot, inputs, pkgs, lib, system }: let project = repoRoot.nix.project; + containers = repoRoot.nix.containers; in [ - ( - project.flake - ) + ( project.flake ) + { inherit containers; } ] diff --git a/src/lib/SmartTokens/Types/PTokenDirectory.hs b/src/lib/SmartTokens/Types/PTokenDirectory.hs index a8b118a..300ca92 100644 --- a/src/lib/SmartTokens/Types/PTokenDirectory.hs +++ b/src/lib/SmartTokens/Types/PTokenDirectory.hs @@ -1,13 +1,13 @@ {-# OPTIONS_GHC -Wno-unused-do-bind #-} {-# OPTIONS_GHC -Wno-partial-type-signatures #-} {-# LANGUAGE ImpredicativeTypes #-} +{-# LANGUAGE NamedFieldPuns #-} {-# LANGUAGE OverloadedLabels #-} {-# LANGUAGE OverloadedRecordDot #-} {-# LANGUAGE OverloadedStrings #-} {-# LANGUAGE PartialTypeSignatures #-} {-# LANGUAGE QualifiedDo #-} {-# LANGUAGE UndecidableInstances #-} -{-# LANGUAGE NamedFieldPuns #-} module SmartTokens.Types.PTokenDirectory ( DirectorySetNode (..), @@ -42,6 +42,21 @@ import Plutarch.Unsafe (punsafeCoerce) import PlutusLedgerApi.V3 (BuiltinByteString, Credential, CurrencySymbol) import PlutusTx (Data (B, Constr), FromData, ToData, UnsafeFromData) +-- $setup +-- +-- >>> import GHC.Stack (HasCallStack) +-- >>> import Plutarch.Internal.Other (printScript) +-- >>> import qualified Data.Text as T +-- >>> import qualified Plutarch.Internal as PI +-- >>> let printTerm :: HasCallStack => Config -> ClosedTerm a -> String ; printTerm config term = printScript $ either (error . T.unpack) id $ PI.compile config term +-- +-- Setup for doctest / HLS. Everything in this block is available for each test. Function +-- definitions are a bit annoying but we probably should introduce printTerm somewhere anyway and +-- then just import. +-- +-- Note: Dont put comments over the setup line! +-- + data BlacklistNode = BlacklistNode { blnKey :: BuiltinByteString, @@ -57,7 +72,7 @@ data BlacklistNode = -- let blnKeyBstr = head $ snd $ BI.unsafeDataAsConstr (toBuiltinData blnKey) -- blnNextBstr = head $ snd $ BI.unsafeDataAsConstr (toBuiltinData blnNext) -- in BI.mkList [blnKeyBstr, blnNextBstr] --- +-- -- instance PlutusTx.FromData BlacklistNode where -- fromBuiltinData builtinData = -- let fields = BI.unsafeDataAsList builtinData @@ -65,12 +80,12 @@ data BlacklistNode = -- fields1 = tail fields -- next = head fields1 -- in Just $ undefined -- Don't know how to determine whether credential is pub key or script - + deriving via (DerivePConstantViaData BlacklistNode PBlacklistNode) instance (PConstantDecl BlacklistNode) -{- +{- >>> _printTerm $ unsafeEvalTerm NoTracing (mkRecordConstr PBlacklistNode (#blnKey .= pconstant "ffffffffffffffffffffffffffffffffffffffffffffffffffffffff" .& #blnNext .= pconstant "")) No instance for `IsString (PAsDataLifted PByteString)' arising from the literal `"ffffffffffffffffffffffffffffffffffffffffffffffffffffffff"' @@ -104,6 +119,17 @@ instance DerivePlutusType PBlacklistNode where instance PUnsafeLiftDecl PBlacklistNode where type PLifted PBlacklistNode = BlacklistNode +-- _printTerm (communicated by Philip) just print some term as string. The term we want to print is +-- @ +-- _term :: forall {s :: S}. Term s PBlacklistNode +-- _term = unsafeEvalTerm NoTracing (pconstant $ BlackListNode { key = "a", next = "b" }) +-- @ +-- Below, we inline the term and have it in a code lens. You can even run the code lens via Haskell +-- language server. The lens will then replace the string starting with "program ..." with exactly +-- the same string. +-- +-- >>> printTerm NoTracing (pconstantData $ BlacklistNode { blnKey = "a hi", blnNext = "a" }) +-- "program 1.0.0 (List [B #61206869, B #61])" type PBlacklistNodeHRec (s :: S) = HRec @@ -112,7 +138,7 @@ type PBlacklistNodeHRec (s :: S) = ] -- | Helper function to extract fields from a 'PBlacklistNode' term. --- >>> _printTerm $ unsafeEvalTerm NoTracing (pletFieldsBlacklistNode (unsafeEvalTerm NoTracing (pconstantData $ BlacklistNode { blnKey = "deadbeee", blnNext = "deadbeef" })) $ \fields -> fields.key) +-- >>> printTerm NoTracing $ unsafeEvalTerm NoTracing (pletFieldsBlacklistNode (unsafeEvalTerm NoTracing (pconstantData $ BlacklistNode { blnKey = "deadbeee", blnNext = "deadbeef" })) $ \fields -> fields.key) -- "programs 1.0.0 (B #6465616462656565)" pletFieldsBlacklistNode :: forall {s :: S} {r :: PType}. Term s (PAsData PBlacklistNode) -> (PBlacklistNodeHRec s -> Term s r) -> Term s r pletFieldsBlacklistNode term = runTermCont $ do