input-output-hk / plutus-apps Goto Github PK
View Code? Open in Web Editor NEWThe Plutus application platform
License: Apache License 2.0
The Plutus application platform
License: Apache License 2.0
[] Plutus Foundation Related to the GHC plugin, Haskell-to-Plutus compiler, on-chain code
[*] Plutus Application Framework Related to the Plutus application backend (PAB), emulator, Plutus libraries
[] Marlowe Related to Marlowe
[] Other Any other topic (Playgrounds, etc.)
When forwardingMintingPolicy
or mkForwardingMintingPolicy
is used to mint, comparation between ownCurrencySymbol and the currency symbol minted fails, therefore rejects the transaction.
Steps to reproduce the behavior:
Forward validations of a minting policy to a validator script
mintPolicy :: MintingPolicy
mintPolicy = forwardingMintingPolicy myTypedValidator
Validate the currency symbol from onchain code
checkMintedAmount :: Bool
checkMintedAmount = case flattenValue (txInfoMint info) of
[(cs, tn', amt)] -> ownCurrencySymbol ctx == cs && tn' == tn && amt == 1
_ -> False
See error:
"WalletError (ValidationError (ScriptFailure (EvaluationError [\"Lh\"] \"CekEvaluationFailure\")))"
Successful validation of ownCurrencySymbol vs currency symbol minted
with a clean pab
db, we spin up a server with the prism-mirror
example contract.
we receive the following errors in the example contract:
this contract seemed to work with the same steps prior to IntersectMBO/plutus@48efaeb
(except for the insufficient funds errors observed in the related ticket)
built against cd49a84 in nix shell
I am running the material in plutus/plutus-pab
. For example using
./result/bin/pab-start-all-servers
or
cabal exec -- plutus-pab-examples --config plutus-pab.yaml.sample webserver
in order to get a pab backend server on port 9080.
In plutus/plutus-pab/ARCHITECTURE.adoc
it reads
[source]
----
POST /api/contract/activate
----
Starts a new instance of the contract. Expects a `ContractActivationArgs` object. Example:
[source,json]
----
{ "caID": "Currency"
, "caWallet": { "getWallet": 1 }
}
----
However when I try to post this to the server it does not approve:
$ curl -X POST -d '{"caID":"Currency", "caWallet": { "getWallet": 1}}' http://localhost:9080/api/contract/activate
Only GET or HEAD is supported
The request GET /api/contract/definitions
does work as described, why does POST not work here?
The function assertNoFailedTransactions
returns True with failing transactions present.
We have run into that several times on our project which lead us to stay away from EmulatorTrace
tests.
Plutus.Contract.Test.walletFundsChange
needs a variant that allows for positive tolerance. My use case involves wallet allocations that are computed with Integer
division which is rounded up by one if not exact division.
newtype PositiveInteger = PositiveInteger Integer
mkPI, mkPositiveInteger :: Integer -> PositiveInteger
mkPI = mkPositiveInteger
mkPositiveInteger n =
if n > 0 then PositiveInteger n
else error ("Integer must be positive: " <> show n)
unPI, unPositiveInteger :: PositiveInteger -> Integer
unPI = unPositiveInteger
unPositiveInteger (PositiveInteger n) = n
----------------------------------------------------------------------------------------
data AddMode = Never | Always | IfNeeded
rationalMult :: AddMode -> PositiveInteger -> Rational -> PositiveInteger
rationalMult mode n positiveR =
let
(d, m) = Prelude.divMod (unPI n * numerator positiveR) $ denominator positiveR
in
mkPI $ case mode of
Never -> d
Always -> d + 1
IfNeeded -> if m == 0 then d else d + 1
----------------------------------------------------------------------------------------
walletFundsChangeWithinPositiveTolerance :: Value -> Wallet -> Value -> TracePredicate
walletFundsChangeWithinPositiveTolerance positiveTolerance w dlt =
flip postMapM (L.generalize $ (,) <$> Folds.walletFunds w <*> Folds.walletFees w) $ \(finalValue', fees) -> do
dist <- ask @InitialDistribution
let exact = False
initialValue = fold (dist ^. at w)
finalValue = finalValue' P.+ if exact then mempty else fees
deltized = initialValue P.+ dlt
result = (deltized `geq` finalValue) && (deltized `leq` (finalValue <> positiveTolerance))
unless result $ do
tell @(Doc Void) $ vsep $
[ "Expected funds of" <+> pretty w <+> "to change by"
, " " <+> viaShow dlt] ++
(if exact then [] else [" (excluding" <+> viaShow (Ada.getLovelace (Ada.fromValue fees)) <+> "lovelace in fees)" ]) ++
if initialValue == finalValue
then ["but they did not change"]
else ["but they changed by", " " <+> viaShow (finalValue P.- initialValue)]
pure result
[] Plutus Foundation Related to the GHC plugin, Haskell-to-Plutus compiler, on-chain code
[] Plutus Application Framework Related to the Plutus application backend (PAB), emulator, Plutus libraries
[] Marlowe Related to Marlowe
[x] Other Any other topic (Playgrounds, etc.)
For a project based on plutus-starter
, Haskell dependencies do not get pulled from the Nix store when I would expect them to.
Clone plutus-starter
. Run nix-shell
. Run cabal update
. Run cabal build
.
If this has been done before on the same machine then it should pull the dependencies from the Nix store and thus not rebuild them.
I need help understanding how to build an efficient CI pipeline for a project using plutus-starter. I don't know if this is an issue with my reading of the docs, or the docs, or plutus-starter. I have written the following CI pipeline:
name: "Test"
on:
pull_request:
push:
jobs:
tests:
runs-on: ubuntu-latest
steps:
- uses: actions/[email protected]
- uses: cachix/install-nix-action@v13
with:
nix_path: nixpkgs=channel:nixos-unstable
extra_nix_config: |
trusted-public-keys = cache.nixos.org-1:6NCHdD59X431o0gWypbMrAURkbJ16ZPMQFGspcDShjY= hydra.iohk.io:f/Ea+s+dFdN+3Y/G+FDgSq+a5NEWhJGzdjvKNGv0/EQ= iohk.cachix.org-1:DpRUyj7h7V830dp/i6Nti+NEO2/nhblbov/8MW7Rqoo=
substituters = https://cache.nixos.org https://hydra.iohk.io https://iohk.cachix.org
- run: nix-shell plutus-starter/shell.nix --command "cd plutus-starter; ./nix/style-check.sh"
- run: nix-shell plutus-starter/shell.nix --command "cd plutus-starter; hlint ."
- run: nix-shell plutus-starter/shell.nix --command "cd plutus-starter; cabal update; cabal run test:danaswap-spec"
- run: nix-shell plutus-starter/shell.nix --command "cd plutus-starter; cabal update; cabal build plutus-starter-pab"
This pipeline is not failing, but the problem I'm having is that it's taking too long, because it's building lots and lots of dependencies. It is hitting the IOHK caches, and it's not building all the dependencies, but it exhibits the same behavior that it does on my local machine (NixOS 20.03), which is that if there is nothing cached in dist-newstyle
then cabal build
will build lots and lots of dependencies.
For me this is an issue with building a CI pipeline, but it's also a lesser issue for local development, because I am used to most or all of the dependencies I need being able to be cached by Nix.
The built-in CI pipeline of plutus-starter
runs release.nix
. I am not sure what this builds, but it doesn't seem to actually build the code of my project. I would like to check that my project builds into an executable file, and run hlint and style checks and unit tests. I would like to check that the nix-shell builds and thus that local development workflows will work. Does the CI included with plutus-starter
cover these things, or does anybody know how I can modify it to cover these things without running into this issue of lots of dependencies being built after I enter the nix-shell
?
I have a validator that is fairly straight forward:
validateSpend :: ValidatorType Burner
validateSpend (MyDatum addrHash) _myRedeemerValue ScriptContext { scriptContextTxInfo = TxInfo { txInfoSignatories = [addr] } } =
addrHash == sha3_256 (getPubKeyHash addr)
validateSpend _ _ _ = traceError "Expecting exactly one signatory."
I compiled this plutus script, built a transaction manually and can lock funds successfully. I do this via wallet api, cardano-cli and other cli tools, because plutus isn't complete yet.
Now I want to lock funds for myself, so I can redeem them, but in order to do that I need to understand the exact format/encoding/hashing of txInfoSignatories
. I've been searching for hours and tried many variations, using the wallet pubkey, account pubkey, address pubkey, hashing with Blake2b_224 etc. pp.
I find it hard to find in the documentation 1) what exact pubkey is this and 2) what exact hash/format is this and how can I create this hash from the command line given that I have full access to the wallet that signed the transaction.
All my attempts so far redeeming the funds ended with:
Command failed: transaction build Error: The following scripts have execution failures:
the script for transaction input 0 (in the order of the TxIds) failed with The Plutus script evaluation failed: An error has occurred: User error:
The provided Plutus code called 'error'.
Thanks.
When the chain index is synchronising with the cardano-node and the node is stopped for a short while (e.g. for version update) then the chain index attempts to resume from the point it was last stopped at, which may have been never, so it rolls back to block 0 and starts again, or it may have been stopped a while ago so it rolls back to there.
Steps to reproduce the behavior:
0. Have node running (mine was synced with the testnet
)
$ cabal run plutus-chain-index -- start-index --socket-path ~/dev/environments/testnet/node/node.sock --network-id $(<~/dev/environments/testnet/node/db/protocolMagicId)
$ curl http://localhost:9083/tip | jq .tipSlot.getSlot
Once cardano-node is back up and the socket exists, chain-index continues syncing with no rollback.
The chain index attempts to resume from the point it was last stopped at, which may have been never, so it rolls back to block 0 and starts again, or it may have been stopped previously but a while ago so it rolls back to there.
Resuming from ChainPointAtGenesis
Rolling back to ChainPointAtGenesis
Note: it may take a while (minutes) after node is re-started for chain-index to log Resuming from ChainPointAtGenesis
or Resuming from ChainPoint
and proceeding to sync from there.
[] Plutus Foundation Related to the GHC plugin, Haskell-to-Plutus compiler, on-chain code
[x] Plutus Application Framework Related to the Plutus application backend (PAB), emulator, Plutus libraries
[] Marlowe Related to Marlowe
[] Other Any other topic (Playgrounds, etc.)
ToSchema
appears not to work when applied to sum types. It fails with the following error message:
• No instance for (Schema.GenericToConstructorName
(GHC.Generics.M1
GHC.Generics.C
('GHC.Generics.MetaCons "BuyIt" 'GHC.Generics.PrefixI 'False)
(GHC.Generics.S1
('GHC.Generics.MetaSel
'Nothing
'GHC.Generics.NoSourceUnpackedness
'GHC.Generics.NoSourceStrictness
'GHC.Generics.DecidedLazy)
(GHC.Generics.Rec0 Integer))))
arising from the 'deriving' clause of a data type declaration
Possible fix:
use a standalone 'deriving instance' declaration,
so you can specify the instance context yourself
• When deriving the instance for (ToSchema SalesType)
data SalesType = SellIt Integer | BuyIt Integer
deriving (Generic, Show, FromJSON, ToJSON, ToSchema, Prelude.Eq, Prelude.Ord)
[X] Plutus Application Framework Related to the Plutus application backend (PAB), emulator, Plutus libraries
ToSchema seems to be useful only for Playground, and provides support for user to input data in the web-interface.
Also PAB is useful on it's own in the headless-mode. When we can run servant server.
Often one or another data type can not be made instance of ToSchema, because it does not support Sum-types
(only sum of constants is supported right now0.
I wonder is it possible to create functional PAB in headless node without requirement for ToSchema instance for it's inputs.
If we are going to use it with cli-executable that can create JSON-values.
So is it possible to relax requirement of PAb from ToSchema down to ToJSON?
it can be super useful to create custom cli-executables.
I've created & tested a Plutus smart contract on the playground. I've been through
the Alonzo-testnet exercises ( including locking & unlocking funds to the helloworld script ).
Searched rigorously, but can not find any documentation to allow me to create
a new Plutus script on the testnet. Is this even possible yet? If so, can you point me to the instructions that show how to create a new Alonzo-testnet project.
[] Plutus Foundation Related to the GHC plugin, Haskell-to-Plutus compiler, on-chain code
[] Plutus Application Framework Related to the Plutus application backend (PAB), emulator, Plutus libraries
[] Marlowe Related to Marlowe
[x] Other Any other topic (Playgrounds, etc.)
Plutus playground docs should include a link to the playground website.
For example, this page should have such a link:
https://playground.plutus.iohkdev.io/tutorial/tutorials/plutus-playground.html
Error:
Compilation Error, Line 89, Column 1 (jump)
error:
• No instance for (Schema.ToSchema (Bool, Bool, Bool))
arising from a use of ‘Playground.Schema.endpointsToSchemas’
• In the expression:
Playground.Schema.endpointsToSchemas
@((Data.Row.Internal..\\) ((.\/) ((.\/) BlockchainActions (Endpoint "give" Integer)) (Endpoint "grab" (Bool,
Bool,
Bool))) BlockchainActions)
In an equation for ‘schemas’:
schemas
= Playground.Schema.endpointsToSchemas
@((Data.Row.Internal..\\) ((.\/) ((.\/) BlockchainActions (Endpoint "give" Integer)) (Endpoint "grab" (Bool,
Bool,
Bool))) BlockchainActions)
|
89 | mkSchemaDefinitions ''GiftSchema
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
[X] Plutus Application Framework Related to the Plutus application backend (PAB), emulator, Plutus libraries
It's often we have to supply endpoint name alongside with enpoint input.
for example in Endpoint "get-giggle" GiggleInput
. Later on that forces us to use @"get-giggle" in the endpoint
or in calling emulator trace method.
I've defined class that binds the name to input:
class (FromJSON a, ToJSON a, KnownSymbol (EndpointSymbol a)) => IsEndpoint a where
type EndpointSymbol a :: Symbol
endpointName :: forall a . IsEndpoint a => a -> String
endpointName a = symbolVal (toProxy a)
where
toProxy :: a -> Proxy (EndpointSymbol a)
toProxy _ = Proxy
With that we can define a type synonym (or refactor Endpoint):
type Call a = Endpoint (EndpointSymbol a) a
And we can define schemas:
type AppSchema = Call GiggleInput
And we can define (or refactor) endpoint
. I use it like this:
getEndpoint :: forall a w (s :: Row Type) e b . (HasEndpoint (EndpointSymbol a) a s, AsContractError e, IsEndpoint a) => (a -> Contract w s
getEndpoint = endpoint @(EndpointSymbol a)
This allows us to declare endpoints without redundant type-annotations:
appEndpoints :: EscrowContract ()
appEndpoints = forever $ selectList
[ getEndpoint swapAction
, getEndpoint depositAction
, getEndpoint withdrawAction
]
The same trick we can use for callEndpoint
which requires users to supply endpoint name symbol.
also endpoint name is used in callEndpointOnInstance
and it can be derived from the input with proposed IsEndpoint
class.
Plutus Application Framework
It would be useful to allow users of BalanceTx API (https://github.com/input-output-hk/plutus-apps/blob/942bd8c6de6a2d5981d91c704b0258bddd9d9d7c/plutus-contract/src/Plutus/Contract/Request.hs#L706) to provide script and data for inputs consumed by an unbalanced transaction (currently UnbalancedTx
doesn't contain any info about scripts and data of inputs).
Maybe there is already a way to do so?
How does PAB deduce which scripts and data to put into witness of final TX so that it can spend its inputs which are locked by scripts?
Plutus Application Framework Related to the Plutus application backend (PAB), emulator, Plutus libraries
The default config of the simulator creates 10 wallets with 100000000000 lovelaces each.
However, manually created wallets get 10000000000 lovelaces (tested for up to 4 extra wallets).
Using the PAB Simulator from the plutus-starter (version 1.0.9, commit: a85818c27926f34d627225636f463cc6698706fc), I'm getting some odd behavior in terms of wallet creation.
I've created a simple contract (GiftContract) and use a shell script to create four wallets. I have not changed the main function within the pab/Main.hs.
Yet, I am getting this output after shutting down the PAB via hitting return.
[INFO] {, ""}: 59999999960
[INFO] Wallet 36cb1d44654c33ed6b26cbe2da0848de2ebfdb20010679a06c5f609c474f349b8003380446e9159a34504f9fd19da3e93f215efa30cae9455d441be0eac8db66291a5a5e8c961f9da5fb8cb616ab630a6600f4a44acd520fa701b330849e4446d7d1711ac606ae93a2b3d457dd7f4f36b3af92dd0de82a7caf471fb5ed2b5ea3:
[INFO] {, ""}: 100000000000
[INFO] Wallet 3e983a2291ed95a079bfbbf1c447180c90241c6eb288ca1d7fa9f3a4f1f4879e1d5b3a2dcc7f6a4207c71987e38a66172d5111c8ef874408f786cafba51a74fc2b68037bbb9a4507f9268eea9fc89e8035fa867020d74f16bc9dc65cc8bd876798585d84f5bd641ec9fa6e44be139edbbab1d6fefb42a303415903e79fe19738:
[INFO] {, ""}: 10000000000
[INFO] Wallet 562f269ac4ce35c9be75343cb9d76b3149d1ea5a509299204de6b61dfec1908ec7a4aeed5057be46ff9881d276f9b4050acf9fbc68b61708e33f64db34f479bddd497ff6d3a59aadc10782de888dc139213f444fe7af7b469cab15d50e1cb6d58fba680762c1963f345178e1a7daf62c2eac026b62ceba08c1c5020326d75c20:
[INFO] {, ""}: 100000000000
[INFO] Wallet 7628f55f34ca6d864c05aae491e67a5cc0998c4e9461d716fa728fefa837058e3adcc42d910d0404fbddaa157f4d0869f2863faf6cc706eae8eafd204af69a33bd3f819a795f4f7388759a4355436e7bddebbdc14a903df8e4ee733d98616cade35c741d39593e68ea7e331bb145f032cf704ed6d1324d9647ecc1aaaee4f7e8:
[INFO] {, ""}: 100000000000
[INFO] Wallet 76d5e1291d51f16eb442267faccd0ab51a3b0c4a21eb6b8f72d5f0a4ca467189ac5f70a018c6df3f632b48fd8ead1b68f39a44de06f5a5de42a6a131af0f085d44becd56fa30041efea5ff2637205181837dffd03545d3db1c11e6dcbbd3415ce8f85aad41776b99eb62a797b8c5abbe82061e1634efc4c7d5ac6fff3ca94d7f:
[INFO] {, ""}: 100000000000
[INFO] Wallet 7e203f38109d82c064e95ff2008d84cf6f5c95ec5dbea86d24f407011f65e3868232a16b2bdab56ccff3ab77e24b6a5c88291dd6519b32943fe85ec52c7e6ffe4ab780e3653ceefb79a9e697805ccd430501b09b9a932def195173d96c91013c8b2e8b948109b07a0cae8725f7a8b2b4a892954971891425b4ef3b2eec05f9a1:
[INFO] {, ""}: 100000000000
[INFO] Wallet 86c4c1d06a6cd0480865a836fafd97daeba7c79bdc043dff34f9d4553c026e831a4a36760c1d8a0a5458efcb33394ce936b139549570e0f2e80739d50abb6402fcd5201fc11e20cdba72c7440a5e406d314cd1f63fa1d87c83881e0dc1fe3ac5bf6f6a576cf7c56f8d46926bcd24b7de630455a7df7cebb0afadce72d1ede55c:
[INFO] {, ""}: 100000000000
[INFO] Wallet 86c6ea24ce790fd9e422a3d22fa6cbc4cf72802675f40b8e2783b4cf38bd4a89a20ee5f32e19499768d274044f825d7251d2bf05c0ce85bfd183127b87376acf115f3ee432684888a2a7b059ba6bffedded97918daf53582e3790082d62856450d8e0efdd7e7b81bcba6c333bb10af271637a9c781d8788db7dc8a8a30763b7e:
[INFO] {, ""}: 10000000000
[INFO] Wallet b6d40a76f3fd73233a7e0c52a1bb99174151b3643f462016b8b39f776acd4081429729fd15129139332ede3e94ac805090d6e80b78e187ea85c29012c7b4f4b6e9929aa98f85a5d3173cfc128f4198c437ee3484f676ae741412698a00603111c2b887a0b36c23620aca53026dddc27a4c078aec919e739e2b81bb2f729c5943:
[INFO] {, ""}: 100000000000
[INFO] Wallet c6794804ca7d19368487af2aa7324296b34274cc69137d1c6187b18a2cb2ce873cb2519aee42967cb4e9661fb3cd106dd68158f16bdfc9b4da04046d06c9d5accaafea24be9b96b417e47d713c3481db821bce2dab3d4bee156d4ef80b249310f227a7eaefdc7a311ea4c93437610d16b02119e4300778573d96107e829035d7:
[INFO] {, ""}: 10000000000
[INFO] Wallet ce5bf0869d6720212e4dcf3ea6992cf4a9b88c39261fd9d6a635f046a17da49b6125ba6748c542e5821ec9d1e9d2f0564bc7572c1ec0e1a82cce88951dec70639e228ed6586bd2946247d66f88fac7e266a9cf37ab49ef1b9b17befd34a3db085e5af768f7297f0e1138220378a2d13c470da5a79639d8313911adeb0436d91e:
[INFO] {, ""}: 100000000000
[INFO] Wallet e6778caeed9911d9b0b49f4fd026052395b6b7025b016052c7ca937e8f332e82338bbe4abdb5d91b348b8361c04117e538f8e6c98f716354837ec822b970419f61636d94a191bc8efbe1e7b53ef59d7b77c67adeb5a3f11fe754ee5ce407045f0da5b9850ac337f62d3bacbbd5ec336736dcb26dcebdea6fb5620b3e4837d177:
[INFO] {, ""}: 100000000000
[INFO] Wallet e6a9e1d3c75218fe4658682642498ddc2de21d4c852985d86aa574642e4aa98332ee626af31520ec3a6425bfb19492f04bdf09e0a1c9d17c32712870f4649acc8c6ef7b2d2ac09cfbdf8b9894393f8cfd6375a9380864d7003dd52c022e81b449459eccd92f62fb1797abf4dd421772635497fd195a4fd0263a4f1c0d4f64f3c:
[INFO] {, ""}: 10000000000
As you can see, we have our 10 regular wallets with a balance of 100,000,000,000 lovelaces each. Yet, there is also three wallets with a balance of 10,000,000,000 lovelaces each and a wallet of 59,999,999,960 lovelaces. The sum of those last wallets minus 4 * 10 lovelaces fee (for creation?) would add up to 100,000,000,000 lovelaces (the value of one default simulator wallet), but it is not intuitive nor did I find any documentation on this behavior.
I have followed the plutus-starter readme to create the wallets and activate the contracts in this manner:
input-output-hk/plutus#1/bin/sh
export W1=`curl -s -d '' http://localhost:9080/wallet/create | jq '.wiWallet.getWalletId'`
export W2=`curl -s -d '' http://localhost:9080/wallet/create | jq '.wiWallet.getWalletId'`
export W3=`curl -s -d '' http://localhost:9080/wallet/create | jq '.wiWallet.getWalletId'`
export W4=`curl -s -d '' http://localhost:9080/wallet/create | jq '.wiWallet.getWalletId'`
export W1_IID=$(curl -s -H "Content-Type: application/json" -X POST -d '{"caID": "GiftContract", "caWallet":{"getWalletId": '$W1'}}' http://localhost:9080/api/contract/activate | jq .unContractInstanceId | tr -d '"')
export W2_IID=$(curl -s -H "Content-Type: application/json" -X POST -d '{"caID": "GiftContract", "caWallet":{"getWalletId": '$W2'}}' http://localhost:9080/api/contract/activate | jq .unContractInstanceId | tr -d '"')
export W3_IID=$(curl -s -H "Content-Type: application/json" -X POST -d '{"caID": "GiftContract", "caWallet":{"getWalletId": '$W3'}}' http://localhost:9080/api/contract/activate | jq .unContractInstanceId | tr -d '"')
export W4_IID=$(curl -s -H "Content-Type: application/json" -X POST -d '{"caID": "GiftContract", "caWallet":{"getWalletId": '$W4'}}' http://localhost:9080/api/contract/activate | jq .unContractInstanceId | tr -d '"')
To make things more explainable, is there a way for me to disable the automatic creation of the 10 wallets and instead pass how many lovelaces I want the manually created wallets to start with?
Wallets created by hitting the /wallet/create endpoint should have the same amount of lovelaces as the default wallets.
The previous Plutus-Starter version worked as expected (with varying curl commands).
I'm following instruction of release v2021-11-05 for PAB
I was able to run:
cabal run plutus-pab-test-psgenerator src/Plutus/PAB/Run
and it generates something that might indicate success
The following purescript packages are needed by the generated code:
- purescript-enums
- purescript-prelude
- purescript-profunctor-lenses
Successfully created your PureScript modules!
[INFO] Slot 0: TxnValidate 8cc29ae699b906e31bbb8b3e55eea772477cd9aeb7154ce8526752f6f986a31a
[nix-shell:~/plutus-apps]$ cabal run plutus-pab -- migrate
cabal: The run command is for running a single executable at once. The target
'plutus-pab' refers to the package plutus-pab-0.1.0.0 which includes the
executable 'tx-inject', the executable 'sync-client', the executable
'plutus-uniswap', the executable 'plutus-pab-test-psgenerator', the executable
'plutus-pab-setup', the executable 'plutus-pab-local-cluster', the executable
'plutus-pab-examples', the test suite 'plutus-pab-test-light', the test suite
'plutus-pab-test-full-long-running' and the test suite 'plutus-pab-test-full'.
[nix-shell:~/plutus-apps]$ cabal run plutus-pab -- all-servers
cabal: The run command is for running a single executable at once. The target
'plutus-pab' refers to the package plutus-pab-0.1.0.0 which includes the
executable 'tx-inject', the executable 'sync-client', the executable
'plutus-uniswap', the executable 'plutus-pab-test-psgenerator', the executable
'plutus-pab-setup', the executable 'plutus-pab-local-cluster', the executable
'plutus-pab-examples', the test suite 'plutus-pab-test-light', the test suite
'plutus-pab-test-full-long-running' and the test suite 'plutus-pab-test-full'.
Please let me know if I'm doing something wrong.
My git status returns:
[nix-shell:~/plutus-apps]$ git status
HEAD detached at v2021-11-05
[] Plutus Application Framework Related to the Plutus application backend (PAB), emulator, Plutus libraries
No instance for (OpenApi.ToSchema Ada)
Currently, there is no standard suite of Arbitrary
instances that seem to actually be suitable for testing smart-contracts -
Plutus.PAB.Arbitrary
has some generic-based instances which are suitable for some of the types,
but in particular, this isn't sufficient to generate well-behaved values of Value
.
For example with the generic Arbitrary
instance - the following property will fail:
propReflEq :: Value -> Bool
propReflEq x = x == x
with value:
(Map {unMap = [(,Map {unMap = []}),(,Map {unMap = [(0xcd,-1),(\"\",-2)]})]})"
It would be useful to have a (better-located) module with more well-behaved instances.
for now Value
, we have the following instance. A library-suitable instance may want a more particular implementation, and an impl of shrink
...
instance Arbitrary Value where
arbitrary = foldMap (Tuple.Extra.uncurry3 Value.singleton) <$> arbitrary
I'm not sure if this is strictly correct since, for example, maybe it's technically valid to have a value such as in txInfoForge
, with both positive and negative values of a given AssetClass
... The exact expectations aren't clear.
Modules with types such as Value
should export functions to check/make an existing value well-behaved. normalizeValue
, which is not exported from Plutus.V1.Ledger.Value
is a (partial) example of this.
When a contract is activated the "Activate Contract" section doesn't update to display it. Page refresh is required.
Steps to reproduce the behavior:
UI updates to display active contract
UI doesn't display newly activated contract. Must refresh page to see it.
[] Plutus Foundation Related to the GHC plugin, Haskell-to-Plutus compiler, on-chain code
[] Plutus Application Framework Related to the Plutus application backend (PAB), emulator, Plutus libraries
[] Marlowe Related to Marlowe
[x] Other Any other topic (Playgrounds, etc.)
When working with the Plutus playground I would really like two features:
The tedious procedure now is to "cat" the script to a terminal or open it in a text editor, copy it to the clipboard, clear the script in the editor window, then paste the clipboard's content in the editor. This could be improved for usability.
Naming of the wallets would make them more human understandable. Also, Lars is explaining in his video the story of Alice, Bob, Charly which students need to translate to wallet 1, wallet 2, wallet 3.
These are small changes, but they could already massively improve usability of the playground.
Plutus Application Framework Related to the Plutus application backend (PAB), emulator, Plutus libraries
I'm following the first lecture in the plutus pioneer program but I cannot set up the local environment. The error happens when running npm start
on a nix-shell after initializing the playground server.
The following purescript packages are needed by the generated code:
- plutus-playground-client
- purescript-either
- purescript-foreign-generic
- purescript-maybe
- purescript-ordered-collections
- purescript-profunctor-lenses
- web-common
Successfully created your PureScript modules!
plutus-playground-server: user error (Error evaluating simulation: JsonDecodingError {expected = "EvaluationResult", decodingError = "Error in $: not enough input", input = ""})
Steps to reproduce the behavior:
A clear and concise description of what you expected to happen.
I expected to have the playground running.
[] Plutus Foundation Related to the GHC plugin, Haskell-to-Plutus compiler, on-chain code
[x] Plutus Application Framework Related to the Plutus application backend (PAB), emulator, Plutus libraries
[] Marlowe Related to Marlowe
[] Other Any other topic (Playgrounds, etc.)
Currently there are two versions of the Uniswap example: one in plutus and another one is in https://github.com/input-output-hk/plutus-pioneer-program. The suggestion is try and merge the pioneer version of starting Uniswap example and make one unique version that can be used as a reference for Plutus example.
[O] Plutus Foundation Related to the GHC plugin, Haskell-to-Plutus compiler, on-chain code
[X] Plutus Application Framework Related to the Plutus application backend (PAB), emulator, Plutus libraries
[O] Marlowe Related to Marlowe
[O] Other Any other topic (Playgrounds, etc.)
Introduce save/restore emulator state snapshots instead of the InitialChainState
param.
When calling runEmulatorTrace
, the user is expected to supply InitialChainState
in EmulatorConfig
. It is defined as:
type InitialChainState = Either InitialDistribution Block
where InitialDistribution
is a synonym for Map Wallet Value
. So the InitialChainState
is basically serving as a genesis block for each EmulatorTrace
run. It would be useful to be able to prerun some of the chain operations and supply a snapshot of EmulatorTrace
to runEmulatorTrace
instead of a single genesis block.
Prerunning parts of the operations is also required to be able to acquire "runtime" arguments and feed them as contract parameters, if necessary. Consider such an example: Contract B is expecting value returned by a Contract A as a parameter. The value is depending on a runtime argument such as UTxO. There is no easy/elegant way to acquire the value before running the EmulatorTrace
. If one is using the Plutus.Contract.Test.ContractModel
framework, it severely hurts the ability to run the tests:
handleSpec :: [ContractInstanceSpec MyModel]
handleSpec =
[ ContractInstanceSpec (MyActionKeyA w1) w1 contractA ] ++
[ ContractInstanceSpec (MyActionKeyB w) w (contractB aValue) | w <- knownWallets ] -- how to get the `aValue`?
Lack of the feature also slows down the testing performance, as one has to rerun in every test the same boilerplate initial operations that usually are irrelevant to a specific test suite.
In the plutus-use-cases
code, there is function, which basically preruns the first contract to acquire its state token, which later is given to the contract depending on it (cf. ). I have used the same trick (almost the same code) to acquire value from Contract A. The value then can be passed to Contract B:
handleSpec :: [ContractInstanceSpec MyModel]
handleSpec =
let aValue = getValueFromA in
[ ContractInstanceSpec (MyActionKeyB w) w (contractB aValue) | w <- knownWallets ]
This is all happening before running tests. Now, the problem is that we are assuming that the aValue
will be a correct one because both prerun and the tests themselves would be run sharing the same genesis block. This assumption will fall apart if someone e.g. changes the order of contracts to be run in the "Initial Action".
When trying to access nix shell from my macOS machine, I get "too many open files" error.
...
derivation: w6y44qg0j1hhyvaz32vkas3gyyzc9klz-network-info-lib-network-info-0.2.0.10-config.drv
required (system, features): (x86_64-darwin, )
1 available machines:
(systems, maxjobs, supportedFeatures, mandatoryFeatures)
(x86_64-linux, 1, big-parallel, kvm, )
Failed to find a machine for remote build!
derivation: f5f64wn9x75z7gbxbx9h8y0nw4zf1b2k-network-lib-network-3.1.2.2-config.drv
required (system, features): (x86_64-darwin, )
1 available machines:
(systems, maxjobs, supportedFeatures, mandatoryFeatures)
(x86_64-linux, 1, big-parallel, kvm, )
error: opening directory '/nix/store/g47vrfhwv20kprd9dbzfdd4ik8agsiy2-network-lib-network-3.1.2.2-config': Too many open files
I've tried increasing open fds limit by 4, but the problem persists:
> sysctl kern.maxfiles kern.maxfilesperproc
kern.maxfiles: 49152
kern.maxfilesperproc: 24576
So I expect that the root of this issue is somewhere else. I've added sandbox paths as was suggested in README and the packages remain unbuildable with the same error. I've even tried clean nix installation, but does not seem to be helping either.
The packages are able to build.
406f5f951358c1d44d31b1c5ba5f35b393eed195
Hi, please can someone give specific examples of how to use the PAB API to activate contracts? The material here is not correct. I can not really guess what to do here.
The instructions state:
===== Starting a new instance of a contract
[source]
----
POST /api/contract/activate
----
Starts a new instance of the contract. Expects a `ContractActivationArgs` object. Example:
[source,json]
----
{ "caID": "Currency"
, "caWallet": { "getWallet": 1 }
}
----
The `caID` field describes the contract that is to be started. In our case (simulator PAB configuration) the string `"Currency"` is enough to identify the currency contract.
The `caWallet` field describes the wallet that this instance should connect to. In the simulator PAB configuration there are ten wallets with IDs 1-10 that can be used for te
st purposes.
This call returns the UUID of the newly started contract instance.
Haskell does not deserialise this properly
lc@aiur ~/S/g/i/plutus-apps (main)> curl -X POST http://localhost:9080/api/contract/activate -H "Content-Type: application/json" -d '{ "caID": "Currency", "caWallet": { "getWallet": 1 }}'
Error in $.caID: parsing ContractExample.ExampleContracts failed, expected Object, but encountered String⏎
There is seemingly an "activation.json" in plutus-pab/test-node, with different contents:
{
"caID": {
"contents": "e828c6c644870a15e09ee1ac511d31a2d4d484d1e5032762f576699ae7f5c881",
"tag": "WaitForTx"
},
"caWallet": {
"getWallet": 1
}
}
This doesn't work either.
lc@aiur ~/S/g/i/p/p/test-node (main)> curl -X POST http://localhost:9080/api/contract/activate -H "Content-Type: application/json" [email protected]
Error in $.caID.contents: parsing Plutus.V1.Ledger.TxId.TxId(TxId) failed, expected Object, but encountered String⏎
On MacOS I used to do this ...
523f349f3d68db07c98150734793ed7003d1f562
# Checkout the Plutus version referencenced in cabal.project
cd ~/git/plutus \
&& git checkout 523f349f3d68db07c98150734793ed7003d1f562 \
&& nix-shell
# Start the Plutus Playground Server
[nix-shell] cd plutus-playground-client && plutus-playground-server
# Start the Plutus Playground Client in another nix-shell
[nix-shell] cd plutus-playground-client && npm run start
https://localhost:8009
executable-dynamic: True
vi ~/.cabal/config
executable-dynamic: True
cabal clean # just to be sure
cabal build exe:haskell-language-server-wrapper
cabal install exe:haskell-language-server-wrapper --overwrite-policy=always
https://atom-haskell.github.io
apm install language-haskell ide-haskell ide-haskell-cabal ide-haskell-hls
This no longer works, because of a plutus dependency issue documented here.
Could we please start a page that documents how to setup "known good" dev environments?
I would like users can give my smart contract delegation permission to their wallets in order to make automated delegations based on some user configurations.
If the smart contract can not do that yet, then an alternative would be to use the YOROI wallet. For example, the users authorize through my website YOROI via API to delegate the ADA somewhere based on configurations.
But YOROI neither has an API at the moment for this situation I need.
All other alternatives are not really serious, since we would need:
[*] Other Any other topic (Playgrounds, etc.)
I'm in trouble with unit tests. So far we test in EmulatorTrace
with checks against pure TracePredicate
.
there are several functions but they all look the same as:
checkPredicate :: String -> TracePredicate -> EmulatorTrace () -> TestTree
The problem starts when TestPredicate
depends on run-time information that is available only inside EmulatorTrace
.
Here is an example:
If we deal with NFT. And in Cardano style NFT it depends on TxOutRef
to make it true NFT that can be issued only once.
If I want to check the funds exchanges I need to know the CurrencySymbol
for the NFT. But it depends
on the call inside EmulatorTrace
and there it can be known. but there is no way for me to specify that currency symbol
in pure manner. I can not do any checks against it.
It's truly limiting. I guess we need to change it to:
checkPredicate :: String -> EmulatorTrace TracePredicate -> TestTree
This way it becomes possible to test such cases.
[x] Plutus Application Framework Related to the Plutus application backend (PAB), emulator, Plutus libraries
We should improve error handling.
This issue is part of the #4 mega-thread.
[] Plutus Foundation Related to the GHC plugin, Haskell-to-Plutus compiler, on-chain code
[x] Plutus Application Framework Related to the Plutus application backend (PAB), emulator, Plutus libraries
[] Marlowe Related to Marlowe
[] Other Any other topic (Playgrounds, etc.)
Generalize mkTypedValidator
to :: CompiledCode a -> CompiledCode (a -> WrappedValidatorType) -> TypedValidator datum redeemer
.
This would need one breaking API change - TypedValidator
would need to be parameterized on datum and redeemer instead of a ValidatorTypes
instance.
This will give validator authors considerably more freedom to play around with types using custom wrappers. For example:
I would love to be able to use Maybe String
as a return type instead of Bool
, with Nothing
for success and Just msg
for failure
Validator authors could define and use custom types isomorphic to ScriptConext
to represent the transaction, unwrapping in the wrapper
Authors would be able to use newtypes around the entire validator function
This feature would have the advantage of making the ValidatorTypes
class/type family mechanism specific to wrapValidator
rather than all uses of mkTypedValidator
.
No change to Plutus API. A user who wants more advanced validator typing implements their own wrapper layer CustomValidatorType -> ValidatorType a
.
This as the advantage of running off-chain.
It has the following disadvantages:
Hard requirement for dummy type and ValidatorTypes
instance to be defined for any validator type - I would love to play with alternatives to this pattern
Makes Plutus API less general than necessary
More work for developer who wants to customise validator types.
State Machine API isn't usable due to it compiling down to a size too large to submit due to the TX size limit.
We should be able to use our contract on-chain if we write it using the API.
We've known this issue for a while now -- initially discovered by one of our clients.
Use regular plutus -- And this is what we've been doing instead. If there's no clear warning or notice about the API being unusable then many developers will run into this problem and will have to do costly refactors.
The link to the documentation opens up an empty read the docs
Steps to reproduce the behavior:
User documentation
The main documentation is located here.
Readable documentation
[] Plutus Foundation Related to the GHC plugin, Haskell-to-Plutus compiler, on-chain code
[x] Plutus Application Framework Related to the Plutus application backend (PAB), emulator, Plutus libraries
[] Marlowe Related to Marlowe
[] Other Any other topic (Playgrounds, etc.)
No instance for (ToSchema Slot)
I got this when i used Slot as a type for the parameters of a function while coding in the Plutus Playground.
For example:
data ExampleParams = ExampleParams {
Param :: Slot
}
deriving stock (Prelude.Eq, Show, Generic)
deriving anyclass (FromJSON, ToJSON, ToSchema)
Not entirely sure if this is per se something that can be fixed in a convenient way, but it should be documented at least.
BigInteger
s encode wrongly as strings by default when using Data.BigInteger and this causes aeson to fail to decode.
A specific example that a user is quite likely to encounter:
The Wallet
type (as generated by PSGenerator.Common) will create a newtype containing a BigInteger
. Whenever we encode
this using Foreign.Class
, and consequently with stringify
, we will face a "2"
, for Wallet { getWallet: BigInteger.fromInt 2 }
. Which causes aeson to complain on the PAB API decode. The problem lies in JSON.stringify
for bignumber.js
.
JSON.stringify
should work correctly on a Foreign
-encoded BigInteger.
Using json-bigint's stringify
seems to circumvent the problem.
bignumber.js ^9.0.1
web-common(-plutus) from rev 5cdd2c3d708bf4c33514681dee096da6463273b7
node v14.15.4
purs 0.13.8
plutus-playground-server
fails to start due to error.
[nix-shell:~/Projects/iohk/plutus-apps/plutus-playground-server]$ plutus-playground-server plutus-playground-server: for development use only
error: attribute 'plutus' missing, at (string):1:1
error: attribute 'plutus' in selection path 'plutus.haskell.packages.plutus-playground-server.components.exes.plutus-playground-server' not found
/nix/store/zn0d3pp69cv469rxbm0w1c5srpjh2mwi-plutus-playground-server/bin/plutus-playground-server: line 10: /bin/plutus-playground-server: No such file or directory
nix-shell
plutus-playground-client
plutus-playground-server
Server should start.
fea746e645f431b2bc13dbf56b81b1d17fa9aa19
Why not
unsafeMkTypedValidator :: Scripts.Validator -> TypedValidator a
I can coerce
from TypedValidator Any
to anything, because TypedValidator
has phantom role, but I think that role is wrong too, and you need to have
type role TypedValidator nominal
But then I'd need to use unsafeCoerce
.
It would be useful to introduce a function
mapWriter :: Monoid w Monoid w' => (w -> w') -> Contract w a s b -> Contract w' a s b
to easily allow stitching together contracts with different writer instances.
Using Writer
instances with Last Either
types ~ but it can become very cumbersome.
[] Plutus Foundation Related to the GHC plugin, Haskell-to-Plutus compiler, on-chain code
[X] Plutus Application Framework Related to the Plutus application backend (PAB), emulator, Plutus libraries
[] Marlowe Related to Marlowe
[] Other Any other topic (Playgrounds, etc.)
There is no instance of ToSchema for address. Sometimes there is demand for that.
[] Plutus Application Framework Related to the Plutus application backend (PAB), emulator, Plutus libraries
As of now, there are two folders that contain reusable purescript code. The problem is that these folders aren't purescript projects and it is not possible to include them as dependencies. It would be nice to have a way of reusing the code and avoid copy&paste.
You can either develop inside the repo or copy the code over. Not sure what is the preferred way of developing frontend for plutus application, but both options seem suboptimal.
Summary:
The nix-build of Plutus Playground with both Windows Subsystem for Linux (wsl) and inside a Docker container fails if you previously have cloned Plutus with the common default git config core.autocrlf=true
on Windows.
Possible solution:
One might disable autocrlf in the whole project. This is, for example, what vcpkg does here.
This issue is relevant because:
Using wsl is quite common these days and this issue is very hard to track down.
Diagnostic info:
If you clone the repository with core.autocrlf=true on Windows (usually the default) and try to build inside a Docker container:
git config --global core.autocrlf
git clone https://github.com/input-output-hk/plutus.git
cd plutus
docker run -it --rm -v "${PWD}:/plutus" nixos/nix
Inside the container, I ran the following commands:
cd /plutus
nix-build --option substituters "https://hydra.iohk.io https://iohk.cachix.org https://cache.nixos.org/" --option 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=" --option use-sqlite-wal false --show-trace
This fails with the following output:
unpacking 'https://github.com/NixOS/nixpkgs/archive/7d71001b796340b219d1bfa8552c81995017544a.tar.gz'...
unpacking 'https://github.com/input-output-hk/haskell.nix/archive/99fdad764061f4166e4c0d1d8783bd039c7bb851.tar.gz'...
unpacking 'https://github.com/input-output-hk/iohk-nix/archive/9dd0d1d10ae187df885996b85c9cb4f6990dae86.tar.gz'...
error: while evaluating the attribute 'packages.marlowe.components.exes' at /plutus/nix/pkgs/haskell/default.nix:63:11:
while evaluating the attribute 'hsPkgs' at /nix/store/cf4ksa58yibwkmx2z83y7qd9zwpyjwmy-haskell.nix-src/overlays/haskell.while evaluating the attribute 'hsPkgs' at /nix/store/cf4ksa58yibwkmx2z83y7qd9zwpyjwmy-haskell.nix-src/overlays/haskell.nix:516:43:
while evaluating 'mkCabalProjectPkgSet' at /nix/store/cf4ksa58yibwkmx2z83y7qd9zwpyjwmy-haskell.nix-src/overlays/haskell.nix:152:13, called from /nix/store/cf4ksa58yibwkmx2z83y7qd9zwpyjwmy-haskell.nix-src/overlays/haskell.nix:501:30:
while evaluating the attribute 'buildPackages.haskell-nix.compiler."${(((plan-pkgs).pkgs hackage)).compiler.nix-name}".version' at /nix/store/qrbp0y6mfscqhfhzivnhc91hvby45nv7-nixpkgs-src/lib/attrsets.nix:344:7:
while evaluating anonymous function at /nix/store/cf4ksa58yibwkmx2z83y7qd9zwpyjwmy-haskell.nix-src/lib/import-and-filter-project.nix:5:1, called from /nix/store/cf4ksa58yibwkmx2z83y7qd9zwpyjwmy-haskell.nix-src/overlays/haskell.nix:503:31:
while evaluating anonymous function at /nix/store/cf4ksa58yibwkmx2z83y7qd9zwpyjwmy-haskell.nix-src/lib/call-cabal-project-to-nix.nix:9:1, called from /nix/store/cf4ksa58yibwkmx2z83y7qd9zwpyjwmy-haskell.nix-src/overlays/haskell.nix:500:36:
Index state found was 2021-02-24T00:00:00Z and noindex-sha256
was provided.
But it works once I set "core.autocrlf=false" or clone inside the container.
I am referring to the Docker container nixos/nix (digest "a6bcef50c7ca82ca66965935a848c8c388beb78c9a5de3e3b3d4ea298c95c708") for reproducibility but the same thing happens with Windows Subsystem for Linux (wsl). With wsl you can "accidentally" fix it by cloning inside wsl (autocrlf will checkout Linux line endings).
Other Any other topic (Playgrounds, etc.)
A clear and specific description of what the bug is.
plutus master % nix-shell --pure
[nix-shell:.../plutus]$ cd plutus-playground-client/
[nix-shell:.../plutus/plutus-playground-client]$ plutus-playground-server
plutus-playground-server: for development use only
/nix/store/badky2d6xiw987cb66r3hddbkqccxxmn-plutus-playground-server/bin/plutus-playground-server: line 3: nix-build: command not found
/nix/store/badky2d6xiw987cb66r3hddbkqccxxmn-plutus-playground-server/bin/plutus-playground-server: line 10: nix-build: command not found
/nix/store/badky2d6xiw987cb66r3hddbkqccxxmn-plutus-playground-server/bin/plutus-playground-server: line 10: /bin/plutus-playground-server: No such file or directory
Just work
non-pure shell doesn't work either. On my machine it says
bash-4.4$ plutus-playground-server
bash: plutus-playground-server: command not found
but that's probably because my bash startup files are completely broken I'm not using bash. And that's why I want nix-shell --pure
to work, so my machine is out of the equation.
Also npm start
of playground client doesn't work in pure or non-pure shell either. Pure needs nix-build
too,
[X] Plutus Foundation Related to the GHC plugin, Haskell-to-Plutus compiler, on-chain code
[X] Other Any other topic (Playgrounds, etc.)
I'm sure being a core developer you are aware of it. For those who don't here is sad description of affairs:
We have big problem with contention. UTXO that holds datum is often associated with the state of the app.
And we imagine that it's single App in the blockchain. We even create a dedicated token to it so that user can find it
and we should check that it's spent to itself and properly updated.
Conceptually it's a single app that user interact with. Contrary on the blockchain (level of implementation)
we emulate this with tricks like dedicated miniting token, checking that token is spent to itself.
So the user thinks about it as an app that is identifier by the ScriptHash, but it's attached to UTXO
and we identify it by the concrete token, and we check that it's spent to itself. UTXO has to carry a value.
Concurrency in blockchain is handled when we put many TXs on the block. We can have hundreds of them.
So it seems that many users can interact with a single App and be happy.
Yet this is not the case. Because conceptual model breaks on the implementation level.
App is attached to the UTXO which is referenced by address, and TX changes that address.
That means that user A and user B submit TX_A and TX_B and both reference to the App state by the same address.
But first TX which succeeds overrides the UTXO address making the second TX invalid.
This brings dramatic impact on the APPs. We are reduced to only one TX per block, which is suffocating for real world apps.
We need to devise workaraunds. But TX-size is limited and we have workaraound-logic that drain the TX-space,
for bridging the gap between concept and implementation.
This TX-size limit of 16 kb and the need to implement the logic of workarounds is suffocating and
it's hard to do anything real on blockchain like this.
I think the core of the problem is inability to reference the App by it's ScriptHash. The need to reference it by ref to UTXO which is not even used in validation logic and going to change unexpectedly based on which user submits TX first.
We need to devise some valid method for that that is built in the Plutus.
Here is my idea, maybe you will have even better ones. Let's discuss that before it's too late.
Singleton contract can have only one UTXO that can be identified by it's script hash.
Globally on block chain there should be only one such UTXO. Every write to it overrides it.
It can be identified by the ScriptHash since there is 1-to-1 correspondence to it.
It can be enforced by it's special type.
Users should be able to reference this singleton by script hash alone. and this brings together concept of DApp state and the implementation for it. No need for dedicated token, no need for logic to check that it's spent to itself. No need for processing TXs in batch to avoid contention.
Singleton contract output can be referenced by Script hash. this way we can update it multiple times per block,
this saves enormous amount of trouble we are having now as a team and I'm sure many other teams are fighting with that.
If we want several such apps in the wild we can parametrize them by TxOutRef (trick used in NFT) and use it only once. Not all the time.
According to our data most space used in TX (~ 90%) is space for scripts or contracts in the inputs. We can reduce that if we
substitute them for hashes. Let's say user allocates contract on blockchain and pays for the space. Then User can use hash to the contract instead of the whole body. This way we can save almost all space.
This solution is cool that it does not sacrifices the purity of blockchain. In case of so called singleton UTXO
we update inplace the datum. In this case there is no need to update in place. We save on input contracts.
We considered creation of App state and association it with NFT.
we need logic that consumes TX-space to check the NFT and to check spending to itself all the time we use it.
Still it does not solve the problem of single action per block.
To mitigate problem of single action per block we create a special logic that accumulates actions and executes them in batch mode. This is non trivial action and it consumed all the space in TX. We do it only to find that we can execute single action in such a list of actions. It all took enormous amount of R&D and hitting our heads against the wall :(
We need something better than that. Your input is very welcome. Proposed solution can have shortcomings that I'm not aware of.
but let's not skip it as not so important issue. We can say that mathematically it can be shown that this stuff is the same.
And we can reduce one to another given infinite amount of space in TX and infinite small time for block confirmation.
We have neither of them.
We take a lot of efforts to make workaround to build very simple apps that do not work on the given limitations.
[x] Plutus Application Framework Related to the Plutus application backend (PAB), emulator, Plutus libraries
Why are redeemers stored together with scripts? For our security work, we want to track all scripts hence all rows in the script table. At the moment, we have to get a row and deserialize it as a Script
to tell if it is a script or redeemer. Therefore, we have to fetch and check all scripts and redeemers when we experiment with a new transpiler or something. The redeemers are simply dropped in that scenario. On the other hand, we care about redeemers but barely need scripts for dApp integration. Our suggestion is to have two separate tables for them.
They are already separated in DiskState
:
https://github.com/input-output-hk/plutus-apps/blob/56fc3fa79781ab461020264f0cf00cb667e86f79/plutus-chain-index/src/Plutus/ChainIndex/Emulator/DiskState.hs#L121-L131
The confusion is even more apparent when the current diagnostics
endpoint also counts redeemers for scripts.
https://github.com/input-output-hk/plutus-apps/blob/942bd8c6de6a2d5981d91c704b0258bddd9d9d7c/plutus-chain-index/src/Plutus/ChainIndex/Handlers.hs#L422
We have to fetch and deserialize the whole table to tell what is a script and what is a redeemer.
This issue is part of the #4 mega-thread.
[x] Plutus Application Framework Related to the Plutus application backend (PAB), emulator, Plutus libraries
We should extend the configuration file to let users decide what they want to track and store. For example, we only care for Alonzo's data for our current security work. The ability to store data by era would likely be helpful. For dApp work, we mainly care for transactions that interact with our protocol. The ability to not store irrelevant data would be excellent.
For example, a small addition to AppendBlock
like in #72 allows applications to configure the choice to store a batch of transactions to the DB or not. Given that tip and UTXO processing is unaffected, most of these configurations are pretty safe to the functioning of the chain index?
We have been customizing the chain index to our needs, but it is prone to upstream changes. I guess the more people can share and have in upstream, the better as well.
This issue is part of the #4 mega-thread.
[] Plutus Foundation Related to the GHC plugin, Haskell-to-Plutus compiler, on-chain code
[x] Plutus Application Framework Related to the Plutus application backend (PAB), emulator, Plutus libraries
[] Marlowe Related to Marlowe
[] Other Any other topic (Playgrounds, etc.)
While working on deployment story it feels like explicit description of workflow of how to go from On-chain + Off-chain code
to dApp
is missing.
It looks like for dApp beind deployed developer need:
Contract
endpoints to PAB handlers and build PAB executable with Contract(s)
embedded in it.user wallets
to balance and sign partial transactions, built by Off-chain code
of dApp
Some parts of the workflow doesn't look quite clear considering the following:
For providing REST API for Contract
several examples available now:
Simulator
related from pioneer lectures - seems to be outdatedSimulator
related for uniswaprunWith
from Plutus.PAB.Run
- linkWhat is the recommended way to start "production" version of PAB for Contract
?
(It looks like last one is a way to go, as PAB demo uses it)
PAB configuring: how to start PAB with ability to:
Note: a way to start chain index for testnet (Alonzo testnet as example):
cabal run exe:plutus-chain-index -- --socket-path /path/ to/node.socket --db-path /path/to/chain-index.db --network-id 8 start-index
PAB - WBE integration.
WBE docs says that:
Plutus Application Backend provides payload of unbalanced transaction
Hosted deployment scenario says that:
The PAB produces a link (URI) for each partial transaction that needs to be balanced and signed. When the user clicks the link, the user’s operating system opens the wallet that is registered to handle the link schema
Does this mean, that dApp
developer's task will be to deliver link for partial transaction to user through dApp
's frontend, and then user will click it and whatever wallet registered for that (and if it works through WBE) will execute REST API call with CBOR-encoded transaction in request body as Using Cardano Wallet with Plutus Application Backend describes it?
Who then submits transaction after it's balanced and signed - PAB
or Wallet
? If PAB
, how does it get signed and balanced transaction back from the user?
Cover topics above in some How-to documentation section.
In the instructions on testing the PAB round-trip on the public testnet, step 2 now fails due to a version mismatch with cardano-node
.
Steps to reproduce the behavior:
[...:cardano.node.ChainDB:Error:46] [2021-11-08 08:08:52.46 UTC] Invalid block 2fbd8c97cb0643a879564f6fe42c4710486b636c1876a0c454ae8ea202c87d26 at slot 41763999: ExtValidationErrorLedger (
HardForkLedgerErrorFromEra S (
S (
S (
S (
Z (
WrapLedgerErr {
unwrapLedgerErr = BBodyError (
BlockTransitionError [
ShelleyInAlonzoPredFail (
LedgersFailure (
LedgerFailure (
UtxowFailure (
WrappedShelleyEraFailure (
UtxoFailure (
UtxosFailure (
ValidationTagMismatch (IsValid True) (
FailedUnexpectedly [
PlutusFailure "\nThe 2 arg plutus script (
PlutusScript PlutusV1 ScriptHash \"8fd8fe8fce219f0ac0f71aa5afd3c98d4ff8c0ccea1c5882852b7914\"
) fails.\nCekError An error has occurred: User error:\nThe budget was overspent. Final negative state: ({ cpu: -35982 | mem: 0 })\nThe redeemer is: List []\nThe context is:\nPurpose: Minting 8fd8fe8fce219f0ac0f71aa5afd3c98d4ff8c0ccea1c5882852b7914\nTxInfo:\n TxId: ecee1d36dc6f4df7e731deba70e14aa51fade20b01aca8089667fc76ba388ba9\n Inputs: [
The sync to work.
The problem is due to a mismatch between cardano-node
versions. A fix is to obtain cardano-node the executable from nix
instead of building it from our source, which has newer dependencies; which causes the mismatch.
I have installed the repo using nix-shell and tried running cabal build plutus-pab
.
I'm getting the below error.
Warning: Requested index-state 2021-10-20T00:00:00Z is newer than
'hackage.haskell.org'! Falling back to older state (2021-10-19T23:39:06Z).
Resolving dependencies...
cabal: Could not resolve dependencies:
[__0] next goal: cardano-crypto-class (user goal)
[__0] rejecting: cardano-crypto-class-2.0.0 (conflict: pkg-config package
libsodium-any, not found in the pkg-config database)
[__0] fail (backjumping, conflict set: cardano-crypto-class)
After searching the rest of the dependency tree exhaustively, these were the
goals I've had most trouble fulfilling: cardano-crypto-class
nix-shell
cabal build plutus-pab
Expected to start the Plutus PAB server.
[] Plutus Foundation Related to the GHC plugin, Haskell-to-Plutus compiler, on-chain code
[x] Plutus Application Framework Related to the Plutus application backend (PAB), emulator, Plutus libraries
[] Marlowe Related to Marlowe
[] Other Any other topic (Playgrounds, etc.)
Change plutus-contract MonadState Spec instance to have state as state.
Deprecate $=
and $~
as they become redundant, the lens own .=
and %=
will suffice.
diff --git a/plutus-contract/src/Plutus/Contract/Test/ContractModel.hs b/plutus-contract/src/Plutus/Contract/Test/ContractModel.hs
index 7fefa8c18..f85c32c72 100644
--- a/plutus-contract/src/Plutus/Contract/Test/ContractModel.hs
+++ b/plutus-contract/src/Plutus/Contract/Test/ContractModel.hs
@@ -17,6 +17,7 @@
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE GADTs #-}
{-# LANGUAGE GeneralizedNewtypeDeriving #-}
+{-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE PolyKinds #-}
{-# LANGUAGE QuantifiedConstraints #-}
{-# LANGUAGE RankNTypes #-}
@@ -235,7 +236,18 @@ dummyModelState s = ModelState 0 Map.empty mempty s
-- | The `Spec` monad is a state monad over the `ModelState`. It is used exclusively by the
-- `nextState` function to model the effects of an action on the blockchain.
newtype Spec state a = Spec (State (ModelState state) a)
- deriving (Functor, Applicative, Monad, MonadState (ModelState state))
+ deriving (Functor, Applicative, Monad)
+
+instance MonadState state (Spec state) where
+ state f = Spec $ State.state $ \s -> case f (_contractState s) of
+ (a, cs) -> (a, s { _contractState = cs })
+ {-# INLINE state #-}
+
+ get = Spec $ fmap _contractState State.get
+ {-# INLINE get #-}
+
+ put cs = Spec $ State.modify' $ \s -> s { _contractState = cs }
+ {-# INLINE put #-}
-- $contractModel
--
@@ -479,15 +491,15 @@ modifyContractState f = modState contractState f
-- | Set a specific field of the contract state.
($=) :: Setter' state a -> a -> Spec state ()
-l $= x = l $~ const x
+($=) = (.=)
-- | Modify a specific field of the contract state.
($~) :: Setter' state a -> (a -> a) -> Spec state ()
-l $~ f = modState (contractState . l) f
+($~) = (%=)
instance GetModelState (Spec state) where
type StateType (Spec state) = state
- getModelState = State.get
+ getModelState = Spec State.get
handle :: (ContractModel s) => Handles s -> HandleFun s
handle handles key =
I compiled plutus-use-cases
with this change, nothing broke.
Not inventing new lens
combinators (which don't follow the naming logic) will make using the library easier. As seasoned lens
user I was surprised to see a combinator I haven't ever seen before, which seemingly did the same thing .=
would do.
Side note: AFAIU, DL
monad is the same as https://hackage.haskell.org/package/mtl-c-0.1.1/docs/Control-Monad-State-CPS.html which could have MonadState state (DL state)
instance as well, potentially making GetModelState
unnecessary.
Don't change anything. But the current setup is crippled, it uses lens
abstractions, but doesn't seem to benefit from then to the fullest. E.g. there is no use
variant, so then we need to write use (contractState . l)
to get part of the contract state in the tests. Or (IMHO) worse, do
s <- getModelState
let x = s ^. contractState . l
[x] Plutus Application Framework Related to the Plutus application backend (PAB), emulator, Plutus libraries
We should write documentation for setup, API, use cases, customization, and more. A good start is to add Moved to #129.openapi3
support to the RESTful endpoints, similar to IntersectMBO/plutus#3807.
We should improve error handling. For example, a wrong socket path is not handled at the moment. The program does not even crash; it just hangs! We sometimes experienced unexpected corrupted DB as well. Moved to #69.
We should package the ChainIndex CLI with a Cardano Node with Docker/Nix. We already have a raw Docker image that may or may not be helpful for upstream. A more appropriate upstream setup is to build the Docker image with Nix, using devcontainer.nix
as an example.
Why are redeemers stored together with scripts? For our security work, we want to track all scripts hence all rows in the script table. At the moment, we have to get a row and deserialize it as a Moved to #70.Script
to tell if it is a script or redeemer. Therefore, we have to fetch and check all scripts and redeemers when we experiment with a new transpiler or something. The redeemers are simply dropped in that scenario. For our dApp work, we care a lot about redeemers but barely need scripts in any way. Our suggestion is to have two separate tables for them.
Why are transactions (ChainIndexTx
) stored in full in the database? We think it is better to strip them down to save disk usage. For instance, we should only store hashes in the transactions with the actual values already stored in the script/datum tables. Else we end up storing duplicated data for each transaction interacting with a known script. We suspect there are still redundant data elsewhere as well.
Make the DB more queriable if possible. For example, to get all transactions of a script in a single query. For now, we would have to fetch then filter on all transactions on the client-side.
We should extend the configuration file to let users decide what they want to track and store. For example, we only care for Alonzo's data for our current security work. The ability to store data by era would likely be helpful. For dApp work, we mainly care for transactions that interact with our protocol. The ability to not store irrelevant data would be excellent. Moved to #73.
Add an extension/customization interface for developers to structure their caches/UTXO pools for faster queries and UTXO discovery. Not all logic can be well represented in config files, while maintaining forks is generally painful for end developers. It would then be nicer to customize the DB scheme, sync logic, effects structure, and more in Haskell. Maybe we can port tight code in app
to src
to keep everything in app
application-specific. We can then gradually expand our extension/customization interface in src
for developers to import and call in app
. chainSyncHandler
in app/Main.hs
is already a good start!
We should write benchmarks for both resource usage and query performance. We have been working with fully synced chain index instances for both the mainnet and testnet, and a simple query may take several seconds at times. We also had to restart the chain index instances occasionally as it consumes more memory with time. This behaviour might suggest memory leaks over long-running periods. These were our low-traffic local experiences as well. We fear it will not scale for high-traffic user requests over the Internet, especially when a dApp endpoint might require several API calls to the Chain Index to have enough data to serve the user. Caching helps, but every performance improvement is still significant.
Write more tests.
We should host standard DB snapshots.
We have been customizing the chain index to our needs, but it is prone to upstream changes. I guess the more people can share and have in upstream, the better as well.
We have several people who are willing to help with all these proposals. Just assign us the proposals that you approve.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.