diff --git a/README.md b/README.md index cab7e8bc..eb7b0898 100644 --- a/README.md +++ b/README.md @@ -65,8 +65,6 @@ instance HasDefinitions MyContracts where 3. Write your main entrypoint for the application and the configuration file ```haskell -import BotPlutusInterface qualified -import BotPlutusInterface.Config qualified as BotPlutusInterface import Prelude main :: IO () @@ -79,7 +77,7 @@ main = do Configuration format (example: ): -``` console +```console $ cabal repl --disable-optimisation --repl-options -Wwarn ... BotPlutusInterface> :m Prelude diff --git a/bot-plutus-interface.cabal b/bot-plutus-interface.cabal index d291b941..1924933f 100644 --- a/bot-plutus-interface.cabal +++ b/bot-plutus-interface.cabal @@ -27,12 +27,10 @@ common common-lang -Wall -Wcompat -Wincomplete-record-updates -Wincomplete-uni-patterns -Wredundant-constraints -fobject-code -fno-ignore-interface-pragmas -fno-omit-interface-pragmas - -fplugin=RecordDotPreprocessor - - -- -Werror + -fplugin=RecordDotPreprocessor -Werror build-depends: - , base ^>=4.14 + , base , record-dot-preprocessor , record-hasfield @@ -80,7 +78,10 @@ library BotPlutusInterface BotPlutusInterface.Balance BotPlutusInterface.BodyBuilder + BotPlutusInterface.CardanoAPI BotPlutusInterface.CardanoCLI + BotPlutusInterface.CardanoNode.Effects + BotPlutusInterface.CardanoNode.Query BotPlutusInterface.ChainIndex BotPlutusInterface.CoinSelection BotPlutusInterface.Collateral @@ -90,7 +91,6 @@ library BotPlutusInterface.ExBudget BotPlutusInterface.Files BotPlutusInterface.Helpers - BotPlutusInterface.QueryNode BotPlutusInterface.Server BotPlutusInterface.TimeSlot BotPlutusInterface.Types @@ -103,13 +103,15 @@ library PlutusConfig.Types build-depends: - , aeson ^>=1.5.0.0 + , aeson , attoparsec >=0.13.2.2 , bytestring ^>=0.10.12.0 , cardano-api , cardano-crypto , cardano-ledger-alonzo + , cardano-ledger-babbage , cardano-ledger-core + , cardano-ledger-shelley , cardano-prelude , cardano-slotting , config-schema @@ -138,6 +140,7 @@ library , plutus-ledger-api , plutus-ledger-constraints , plutus-pab + , plutus-script-utils , plutus-tx , plutus-tx-plugin , pretty @@ -176,6 +179,7 @@ test-suite bot-plutus-interface-test main-is: Spec.hs ghc-options: -fplugin-opt PlutusTx.Plugin:defer-errors other-modules: + Spec.BotPlutusInterface.AdjustUnbalanced Spec.BotPlutusInterface.Balance Spec.BotPlutusInterface.CoinSelection Spec.BotPlutusInterface.Collateral @@ -184,12 +188,11 @@ test-suite bot-plutus-interface-test Spec.BotPlutusInterface.ContractStats Spec.BotPlutusInterface.Server Spec.BotPlutusInterface.TxStatusChange - Spec.BotPlutusInterface.UtxoParser Spec.MockContract Spec.RandomLedger build-depends: - , aeson ^>=1.5.0.0 + , aeson , attoparsec , base , base-compat @@ -220,6 +223,7 @@ test-suite bot-plutus-interface-test , plutus-ledger-api , plutus-ledger-constraints , plutus-pab + , plutus-script-utils , plutus-tx , plutus-tx-plugin , pretty-diff diff --git a/cabal.project b/cabal.project index fdb457c8..95ba46ad 100644 --- a/cabal.project +++ b/cabal.project @@ -1,4 +1,4 @@ -index-state: 2022-01-22T00:00:00Z +index-state: 2022-05-18T00:00:00Z packages: ./bot-plutus-interface.cabal ./examples/plutus-game/plutus-game.cabal diff --git a/examples/plutus-game/cabal.project b/examples/plutus-game/cabal.project index 67d6ae9c..bbcecc5f 100644 --- a/examples/plutus-game/cabal.project +++ b/examples/plutus-game/cabal.project @@ -1,5 +1,5 @@ -- Bump this if you need newer packages -index-state: 2021-10-20T00:00:00Z +index-state: 2022-05-18T00:00:00Z packages: ./. @@ -11,4 +11,3 @@ write-ghc-environment-files: never -- Always build tests and benchmarks. tests: true benchmarks: true - diff --git a/examples/plutus-game/pabConfig.value b/examples/plutus-game/pabConfig.value index 833c4a70..ca76860d 100644 --- a/examples/plutus-game/pabConfig.value +++ b/examples/plutus-game/pabConfig.value @@ -1,7 +1,7 @@ -- Calling the cli locally or through an ssh connection cliLocation: local chainIndexUrl: "http://localhost:9083" -networkId: 1097911063 +networkId: 9 -- Directory name of the script and data files scriptFileDir: "./scripts" diff --git a/examples/plutus-game/plutus-game.cabal b/examples/plutus-game/plutus-game.cabal index 20b71950..e8d9975b 100644 --- a/examples/plutus-game/plutus-game.cabal +++ b/examples/plutus-game/plutus-game.cabal @@ -74,7 +74,7 @@ library import: common-lang exposed-modules: Cardano.PlutusExample.Game build-depends: - , aeson ^>=1.5.0.0 + , aeson , attoparsec >=0.13.2.2 , bot-plutus-interface , bytestring ^>=0.10.12.0 @@ -126,7 +126,7 @@ library executable plutus-game-pab import: common-lang build-depends: - , aeson ^>=1.5.0.0 + , aeson , bot-plutus-interface , bytestring , cardano-api diff --git a/examples/plutus-game/protocol.json b/examples/plutus-game/protocol.json index a1718e8e..1ac232cd 100644 --- a/examples/plutus-game/protocol.json +++ b/examples/plutus-game/protocol.json @@ -1,208 +1,385 @@ { - "maxValueSize": 5000, - "minUTxOValue": null, - "minPoolCost": 340000000, - "monetaryExpansion": 3.0e-3, - "stakeAddressDeposit": 2000000, - "txFeeFixed": 155381, - "poolRetireMaxEpoch": 18, - "stakePoolDeposit": 500000000, - "maxBlockExecutionUnits": { - "memory": 80000000, - "steps": 40000000000 - }, - "extraPraosEntropy": null, - "stakePoolTargetNum": 500, - "maxBlockHeaderSize": 1100, - "maxCollateralInputs": 3, - "txFeePerByte": 44, - "treasuryCut": 0.2, - "protocolVersion": { - "minor": 0, - "major": 6 - }, "collateralPercentage": 150, - "poolPledgeInfluence": 0.3, "costModels": { "PlutusScriptV1": { - "mapData-memory-arguments": 32, - "lessThanInteger-memory-arguments": 1, - "sha3_256-cpu-arguments-slope": 82363, - "bData-cpu-arguments": 150000, - "equalsByteString-cpu-arguments-intercept": 112536, - "equalsString-cpu-arguments-constant": 1000, - "modInteger-memory-arguments-slope": 1, - "equalsInteger-memory-arguments": 1, - "trace-cpu-arguments": 150000, - "iData-cpu-arguments": 150000, - "equalsByteString-memory-arguments": 1, - "unIData-memory-arguments": 32, - "consByteString-memory-arguments-intercept": 0, - "cekLamCost-exBudgetCPU": 29773, - "indexByteString-cpu-arguments": 150000, - "cekStartupCost-exBudgetMemory": 100, - "listData-memory-arguments": 32, - "divideInteger-cpu-arguments-constant": 148000, - "lessThanInteger-cpu-arguments-intercept": 179690, - "verifySignature-cpu-arguments-slope": 1, - "appendString-memory-arguments-intercept": 0, - "equalsString-cpu-arguments-slope": 1000, - "blake2b-cpu-arguments-intercept": 2477736, - "encodeUtf8-cpu-arguments-slope": 1000, - "mapData-cpu-arguments": 150000, - "equalsByteString-cpu-arguments-slope": 247, - "multiplyInteger-cpu-arguments-intercept": 61516, + "addInteger-cpu-arguments-intercept": 205665, + "addInteger-cpu-arguments-slope": 812, + "addInteger-memory-arguments-intercept": 1, + "addInteger-memory-arguments-slope": 1, + "appendByteString-cpu-arguments-intercept": 1000, + "appendByteString-cpu-arguments-slope": 571, + "appendByteString-memory-arguments-intercept": 0, + "appendByteString-memory-arguments-slope": 1, + "appendString-cpu-arguments-intercept": 1000, + "appendString-cpu-arguments-slope": 24177, + "appendString-memory-arguments-intercept": 4, + "appendString-memory-arguments-slope": 1, + "bData-cpu-arguments": 1000, + "bData-memory-arguments": 32, + "blake2b_256-cpu-arguments-intercept": 117366, + "blake2b_256-cpu-arguments-slope": 10475, + "blake2b_256-memory-arguments": 4, + "cekApplyCost-exBudgetCPU": 23000, + "cekApplyCost-exBudgetMemory": 100, + "cekBuiltinCost-exBudgetCPU": 23000, + "cekBuiltinCost-exBudgetMemory": 100, + "cekConstCost-exBudgetCPU": 23000, + "cekConstCost-exBudgetMemory": 100, + "cekDelayCost-exBudgetCPU": 23000, + "cekDelayCost-exBudgetMemory": 100, + "cekForceCost-exBudgetCPU": 23000, + "cekForceCost-exBudgetMemory": 100, + "cekLamCost-exBudgetCPU": 23000, + "cekLamCost-exBudgetMemory": 100, "cekStartupCost-exBudgetCPU": 100, - "sndPair-memory-arguments": 32, - "sha3_256-cpu-arguments-intercept": 0, - "addInteger-cpu-arguments-slope": 0, + "cekStartupCost-exBudgetMemory": 100, + "cekVarCost-exBudgetCPU": 23000, + "cekVarCost-exBudgetMemory": 100, + "chooseData-cpu-arguments": 19537, + "chooseData-memory-arguments": 32, + "chooseList-cpu-arguments": 175354, + "chooseList-memory-arguments": 32, + "chooseUnit-cpu-arguments": 46417, + "chooseUnit-memory-arguments": 4, + "consByteString-cpu-arguments-intercept": 221973, + "consByteString-cpu-arguments-slope": 511, + "consByteString-memory-arguments-intercept": 0, + "consByteString-memory-arguments-slope": 1, + "constrData-cpu-arguments": 89141, "constrData-memory-arguments": 32, + "decodeUtf8-cpu-arguments-intercept": 497525, + "decodeUtf8-cpu-arguments-slope": 14068, + "decodeUtf8-memory-arguments-intercept": 4, + "decodeUtf8-memory-arguments-slope": 2, + "divideInteger-cpu-arguments-constant": 196500, + "divideInteger-cpu-arguments-model-arguments-intercept": 453240, + "divideInteger-cpu-arguments-model-arguments-slope": 220, "divideInteger-memory-arguments-intercept": 0, - "cekForceCost-exBudgetCPU": 29773, - "equalsByteString-cpu-arguments-constant": 150000, - "modInteger-cpu-arguments-model-arguments-intercept": 425507, - "sliceByteString-memory-arguments-slope": 1, + "divideInteger-memory-arguments-minimum": 1, + "divideInteger-memory-arguments-slope": 1, + "encodeUtf8-cpu-arguments-intercept": 1000, + "encodeUtf8-cpu-arguments-slope": 28662, + "encodeUtf8-memory-arguments-intercept": 4, + "encodeUtf8-memory-arguments-slope": 2, + "equalsByteString-cpu-arguments-constant": 245000, + "equalsByteString-cpu-arguments-intercept": 216773, + "equalsByteString-cpu-arguments-slope": 62, + "equalsByteString-memory-arguments": 1, + "equalsData-cpu-arguments-intercept": 1060367, + "equalsData-cpu-arguments-slope": 12586, + "equalsData-memory-arguments": 1, + "equalsInteger-cpu-arguments-intercept": 208512, + "equalsInteger-cpu-arguments-slope": 421, + "equalsInteger-memory-arguments": 1, + "equalsString-cpu-arguments-constant": 187000, + "equalsString-cpu-arguments-intercept": 1000, + "equalsString-cpu-arguments-slope": 52998, "equalsString-memory-arguments": 1, - "cekLamCost-exBudgetMemory": 100, - "lessThanEqualsInteger-cpu-arguments-intercept": 145276, - "quotientInteger-memory-arguments-minimum": 1, - "consByteString-cpu-arguments-intercept": 150000, - "appendByteString-memory-arguments-slope": 1, - "lessThanByteString-cpu-arguments-slope": 248, + "fstPair-cpu-arguments": 80436, + "fstPair-memory-arguments": 32, + "headList-cpu-arguments": 43249, + "headList-memory-arguments": 32, + "iData-cpu-arguments": 1000, + "iData-memory-arguments": 32, + "ifThenElse-cpu-arguments": 80556, + "ifThenElse-memory-arguments": 1, + "indexByteString-cpu-arguments": 57667, + "indexByteString-memory-arguments": 4, + "lengthOfByteString-cpu-arguments": 1000, + "lengthOfByteString-memory-arguments": 10, + "lessThanByteString-cpu-arguments-intercept": 197145, + "lessThanByteString-cpu-arguments-slope": 156, "lessThanByteString-memory-arguments": 1, - "multiplyInteger-cpu-arguments-slope": 11218, - "cekVarCost-exBudgetCPU": 29773, - "cekDelayCost-exBudgetMemory": 100, - "blake2b-cpu-arguments-slope": 29175, - "mkNilData-cpu-arguments": 150000, - "appendByteString-cpu-arguments-slope": 621, - "appendString-memory-arguments-slope": 1, - "lessThanInteger-cpu-arguments-slope": 497, - "chooseUnit-memory-arguments": 32, - "divideInteger-cpu-arguments-model-arguments-slope": 118, - "decodeUtf8-cpu-arguments-slope": 1000, - "chooseData-cpu-arguments": 150000, - "verifySignature-cpu-arguments-intercept": 3345831, - "modInteger-memory-arguments-minimum": 1, + "lessThanEqualsByteString-cpu-arguments-intercept": 197145, + "lessThanEqualsByteString-cpu-arguments-slope": 156, "lessThanEqualsByteString-memory-arguments": 1, - "quotientInteger-cpu-arguments-constant": 148000, - "consByteString-memory-arguments-slope": 1, - "tailList-memory-arguments": 32, - "divideInteger-cpu-arguments-model-arguments-intercept": 425507, - "decodeUtf8-cpu-arguments-intercept": 150000, + "lessThanEqualsInteger-cpu-arguments-intercept": 204924, + "lessThanEqualsInteger-cpu-arguments-slope": 473, "lessThanEqualsInteger-memory-arguments": 1, - "appendByteString-cpu-arguments-intercept": 396231, - "unMapData-memory-arguments": 32, - "chooseList-cpu-arguments": 150000, - "divideInteger-memory-arguments-minimum": 1, - "unListData-memory-arguments": 32, - "remainderInteger-cpu-arguments-constant": 148000, - "addInteger-memory-arguments-slope": 1, - "sha3_256-memory-arguments": 4, - "lessThanByteString-cpu-arguments-intercept": 103599, - "modInteger-cpu-arguments-constant": 148000, - "lessThanEqualsInteger-cpu-arguments-slope": 1366, - "appendByteString-memory-arguments-intercept": 0, - "listData-cpu-arguments": 150000, - "ifThenElse-memory-arguments": 1, - "cekApplyCost-exBudgetMemory": 100, - "sliceByteString-memory-arguments-intercept": 0, - "unIData-cpu-arguments": 150000, - "modInteger-cpu-arguments-model-arguments-slope": 118, - "equalsData-cpu-arguments-intercept": 150000, - "mkNilPairData-memory-arguments": 32, - "cekConstCost-exBudgetCPU": 29773, - "indexByteString-memory-arguments": 1, - "blake2b-memory-arguments": 4, - "lessThanEqualsByteString-cpu-arguments-slope": 248, - "cekDelayCost-exBudgetCPU": 29773, - "multiplyInteger-memory-arguments-slope": 1, - "remainderInteger-memory-arguments-slope": 1, - "subtractInteger-cpu-arguments-slope": 0, - "iData-memory-arguments": 32, - "cekBuiltinCost-exBudgetCPU": 29773, + "lessThanInteger-cpu-arguments-intercept": 208896, + "lessThanInteger-cpu-arguments-slope": 511, + "lessThanInteger-memory-arguments": 1, + "listData-cpu-arguments": 52467, + "listData-memory-arguments": 32, + "mapData-cpu-arguments": 64832, + "mapData-memory-arguments": 32, + "mkCons-cpu-arguments": 65493, + "mkCons-memory-arguments": 32, + "mkNilData-cpu-arguments": 22558, "mkNilData-memory-arguments": 32, - "cekForceCost-exBudgetMemory": 100, - "trace-memory-arguments": 32, - "encodeUtf8-cpu-arguments-intercept": 150000, - "sha2_256-cpu-arguments-intercept": 2477736, - "headList-memory-arguments": 32, - "unBData-cpu-arguments": 150000, - "remainderInteger-memory-arguments-minimum": 1, - "unMapData-cpu-arguments": 150000, - "sha2_256-cpu-arguments-slope": 29175, + "mkNilPairData-cpu-arguments": 16563, + "mkNilPairData-memory-arguments": 32, + "mkPairData-cpu-arguments": 76511, + "mkPairData-memory-arguments": 32, + "modInteger-cpu-arguments-constant": 196500, + "modInteger-cpu-arguments-model-arguments-intercept": 453240, + "modInteger-cpu-arguments-model-arguments-slope": 220, "modInteger-memory-arguments-intercept": 0, - "ifThenElse-cpu-arguments": 1, - "tailList-cpu-arguments": 150000, + "modInteger-memory-arguments-minimum": 1, + "modInteger-memory-arguments-slope": 1, + "multiplyInteger-cpu-arguments-intercept": 69522, + "multiplyInteger-cpu-arguments-slope": 11687, "multiplyInteger-memory-arguments-intercept": 0, - "remainderInteger-memory-arguments-intercept": 0, - "consByteString-cpu-arguments-slope": 1000, - "lengthOfByteString-memory-arguments": 4, - "fstPair-memory-arguments": 32, - "mkPairData-cpu-arguments": 150000, - "appendString-cpu-arguments-intercept": 150000, - "verifySignature-memory-arguments": 1, - "sliceByteString-cpu-arguments-intercept": 150000, - "equalsData-cpu-arguments-slope": 10000, - "lessThanEqualsByteString-cpu-arguments-intercept": 103599, - "chooseList-memory-arguments": 32, + "multiplyInteger-memory-arguments-slope": 1, + "nullList-cpu-arguments": 60091, "nullList-memory-arguments": 32, - "unListData-cpu-arguments": 150000, - "equalsData-memory-arguments": 1, - "quotientInteger-cpu-arguments-model-arguments-slope": 118, - "sha2_256-memory-arguments": 4, - "quotientInteger-cpu-arguments-model-arguments-intercept": 425507, - "encodeUtf8-memory-arguments-intercept": 0, + "quotientInteger-cpu-arguments-constant": 196500, + "quotientInteger-cpu-arguments-model-arguments-intercept": 453240, + "quotientInteger-cpu-arguments-model-arguments-slope": 220, + "quotientInteger-memory-arguments-intercept": 0, + "quotientInteger-memory-arguments-minimum": 1, "quotientInteger-memory-arguments-slope": 1, - "unConstrData-cpu-arguments": 150000, - "sliceByteString-cpu-arguments-slope": 5000, - "cekBuiltinCost-exBudgetMemory": 100, - "equalsInteger-cpu-arguments-slope": 1326, + "remainderInteger-cpu-arguments-constant": 196500, + "remainderInteger-cpu-arguments-model-arguments-intercept": 453240, + "remainderInteger-cpu-arguments-model-arguments-slope": 220, + "remainderInteger-memory-arguments-intercept": 0, + "remainderInteger-memory-arguments-minimum": 1, + "remainderInteger-memory-arguments-slope": 1, + "sha2_256-cpu-arguments-intercept": 806990, + "sha2_256-cpu-arguments-slope": 30482, + "sha2_256-memory-arguments": 4, + "sha3_256-cpu-arguments-intercept": 1927926, + "sha3_256-cpu-arguments-slope": 82523, + "sha3_256-memory-arguments": 4, + "sliceByteString-cpu-arguments-intercept": 265318, + "sliceByteString-cpu-arguments-slope": 0, + "sliceByteString-memory-arguments-intercept": 4, + "sliceByteString-memory-arguments-slope": 0, + "sndPair-cpu-arguments": 85931, + "sndPair-memory-arguments": 32, + "subtractInteger-cpu-arguments-intercept": 205665, + "subtractInteger-cpu-arguments-slope": 812, + "subtractInteger-memory-arguments-intercept": 1, "subtractInteger-memory-arguments-slope": 1, - "mkCons-cpu-arguments": 150000, - "chooseUnit-cpu-arguments": 150000, - "chooseData-memory-arguments": 32, - "bData-memory-arguments": 32, - "appendString-cpu-arguments-slope": 1000, - "decodeUtf8-memory-arguments-slope": 8, - "fstPair-cpu-arguments": 150000, + "tailList-cpu-arguments": 41182, + "tailList-memory-arguments": 32, + "trace-cpu-arguments": 212342, + "trace-memory-arguments": 32, + "unBData-cpu-arguments": 31220, + "unBData-memory-arguments": 32, + "unConstrData-cpu-arguments": 32696, "unConstrData-memory-arguments": 32, - "sndPair-cpu-arguments": 150000, + "unIData-cpu-arguments": 43357, + "unIData-memory-arguments": 32, + "unListData-cpu-arguments": 32247, + "unListData-memory-arguments": 32, + "unMapData-cpu-arguments": 38314, + "unMapData-memory-arguments": 32, + "verifyEd25519Signature-cpu-arguments-intercept": 9462713, + "verifyEd25519Signature-cpu-arguments-slope": 1021, + "verifyEd25519Signature-memory-arguments": 10 + }, + "PlutusScriptV2": { + "addInteger-cpu-arguments-intercept": 205665, + "addInteger-cpu-arguments-slope": 812, "addInteger-memory-arguments-intercept": 1, + "addInteger-memory-arguments-slope": 1, + "appendByteString-cpu-arguments-intercept": 1000, + "appendByteString-cpu-arguments-slope": 571, + "appendByteString-memory-arguments-intercept": 0, + "appendByteString-memory-arguments-slope": 1, + "appendString-cpu-arguments-intercept": 1000, + "appendString-cpu-arguments-slope": 24177, + "appendString-memory-arguments-intercept": 4, + "appendString-memory-arguments-slope": 1, + "bData-cpu-arguments": 1000, + "bData-memory-arguments": 32, + "blake2b_256-cpu-arguments-intercept": 117366, + "blake2b_256-cpu-arguments-slope": 10475, + "blake2b_256-memory-arguments": 4, + "cekApplyCost-exBudgetCPU": 23000, + "cekApplyCost-exBudgetMemory": 100, + "cekBuiltinCost-exBudgetCPU": 23000, + "cekBuiltinCost-exBudgetMemory": 100, + "cekConstCost-exBudgetCPU": 23000, "cekConstCost-exBudgetMemory": 100, - "remainderInteger-cpu-arguments-model-arguments-intercept": 425507, - "equalsString-cpu-arguments-intercept": 150000, + "cekDelayCost-exBudgetCPU": 23000, + "cekDelayCost-exBudgetMemory": 100, + "cekForceCost-exBudgetCPU": 23000, + "cekForceCost-exBudgetMemory": 100, + "cekLamCost-exBudgetCPU": 23000, + "cekLamCost-exBudgetMemory": 100, + "cekStartupCost-exBudgetCPU": 100, + "cekStartupCost-exBudgetMemory": 100, + "cekVarCost-exBudgetCPU": 23000, + "cekVarCost-exBudgetMemory": 100, + "chooseData-cpu-arguments": 19537, + "chooseData-memory-arguments": 32, + "chooseList-cpu-arguments": 175354, + "chooseList-memory-arguments": 32, + "chooseUnit-cpu-arguments": 46417, + "chooseUnit-memory-arguments": 4, + "consByteString-cpu-arguments-intercept": 221973, + "consByteString-cpu-arguments-slope": 511, + "consByteString-memory-arguments-intercept": 0, + "consByteString-memory-arguments-slope": 1, + "constrData-cpu-arguments": 89141, + "constrData-memory-arguments": 32, + "decodeUtf8-cpu-arguments-intercept": 497525, + "decodeUtf8-cpu-arguments-slope": 14068, + "decodeUtf8-memory-arguments-intercept": 4, + "decodeUtf8-memory-arguments-slope": 2, + "divideInteger-cpu-arguments-constant": 196500, + "divideInteger-cpu-arguments-model-arguments-intercept": 453240, + "divideInteger-cpu-arguments-model-arguments-slope": 220, + "divideInteger-memory-arguments-intercept": 0, + "divideInteger-memory-arguments-minimum": 1, + "divideInteger-memory-arguments-slope": 1, + "encodeUtf8-cpu-arguments-intercept": 1000, + "encodeUtf8-cpu-arguments-slope": 28662, + "encodeUtf8-memory-arguments-intercept": 4, + "encodeUtf8-memory-arguments-slope": 2, + "equalsByteString-cpu-arguments-constant": 245000, + "equalsByteString-cpu-arguments-intercept": 216773, + "equalsByteString-cpu-arguments-slope": 62, + "equalsByteString-memory-arguments": 1, + "equalsData-cpu-arguments-intercept": 1060367, + "equalsData-cpu-arguments-slope": 12586, + "equalsData-memory-arguments": 1, + "equalsInteger-cpu-arguments-intercept": 208512, + "equalsInteger-cpu-arguments-slope": 421, + "equalsInteger-memory-arguments": 1, + "equalsString-cpu-arguments-constant": 187000, + "equalsString-cpu-arguments-intercept": 1000, + "equalsString-cpu-arguments-slope": 52998, + "equalsString-memory-arguments": 1, + "fstPair-cpu-arguments": 80436, + "fstPair-memory-arguments": 32, + "headList-cpu-arguments": 43249, + "headList-memory-arguments": 32, + "iData-cpu-arguments": 1000, + "iData-memory-arguments": 32, + "ifThenElse-cpu-arguments": 80556, + "ifThenElse-memory-arguments": 1, + "indexByteString-cpu-arguments": 57667, + "indexByteString-memory-arguments": 4, + "lengthOfByteString-cpu-arguments": 1000, + "lengthOfByteString-memory-arguments": 10, + "lessThanByteString-cpu-arguments-intercept": 197145, + "lessThanByteString-cpu-arguments-slope": 156, + "lessThanByteString-memory-arguments": 1, + "lessThanEqualsByteString-cpu-arguments-intercept": 197145, + "lessThanEqualsByteString-cpu-arguments-slope": 156, + "lessThanEqualsByteString-memory-arguments": 1, + "lessThanEqualsInteger-cpu-arguments-intercept": 204924, + "lessThanEqualsInteger-cpu-arguments-slope": 473, + "lessThanEqualsInteger-memory-arguments": 1, + "lessThanInteger-cpu-arguments-intercept": 208896, + "lessThanInteger-cpu-arguments-slope": 511, + "lessThanInteger-memory-arguments": 1, + "listData-cpu-arguments": 52467, + "listData-memory-arguments": 32, + "mapData-cpu-arguments": 64832, + "mapData-memory-arguments": 32, + "mkCons-cpu-arguments": 65493, "mkCons-memory-arguments": 32, + "mkNilData-cpu-arguments": 22558, + "mkNilData-memory-arguments": 32, + "mkNilPairData-cpu-arguments": 16563, + "mkNilPairData-memory-arguments": 32, + "mkPairData-cpu-arguments": 76511, "mkPairData-memory-arguments": 32, - "lengthOfByteString-cpu-arguments": 150000, - "remainderInteger-cpu-arguments-model-arguments-slope": 118, - "cekApplyCost-exBudgetCPU": 29773, - "constrData-cpu-arguments": 150000, - "nullList-cpu-arguments": 150000, - "headList-cpu-arguments": 150000, - "decodeUtf8-memory-arguments-intercept": 0, - "subtractInteger-cpu-arguments-intercept": 197209, - "subtractInteger-memory-arguments-intercept": 1, - "encodeUtf8-memory-arguments-slope": 8, - "equalsInteger-cpu-arguments-intercept": 136542, + "modInteger-cpu-arguments-constant": 196500, + "modInteger-cpu-arguments-model-arguments-intercept": 453240, + "modInteger-cpu-arguments-model-arguments-slope": 220, + "modInteger-memory-arguments-intercept": 0, + "modInteger-memory-arguments-minimum": 1, + "modInteger-memory-arguments-slope": 1, + "multiplyInteger-cpu-arguments-intercept": 69522, + "multiplyInteger-cpu-arguments-slope": 11687, + "multiplyInteger-memory-arguments-intercept": 0, + "multiplyInteger-memory-arguments-slope": 1, + "nullList-cpu-arguments": 60091, + "nullList-memory-arguments": 32, + "quotientInteger-cpu-arguments-constant": 196500, + "quotientInteger-cpu-arguments-model-arguments-intercept": 453240, + "quotientInteger-cpu-arguments-model-arguments-slope": 220, "quotientInteger-memory-arguments-intercept": 0, - "cekVarCost-exBudgetMemory": 100, + "quotientInteger-memory-arguments-minimum": 1, + "quotientInteger-memory-arguments-slope": 1, + "remainderInteger-cpu-arguments-constant": 196500, + "remainderInteger-cpu-arguments-model-arguments-intercept": 453240, + "remainderInteger-cpu-arguments-model-arguments-slope": 220, + "remainderInteger-memory-arguments-intercept": 0, + "remainderInteger-memory-arguments-minimum": 1, + "remainderInteger-memory-arguments-slope": 1, + "serialiseData-cpu-arguments-intercept": 1159724, + "serialiseData-cpu-arguments-slope": 392670, + "serialiseData-memory-arguments-intercept": 0, + "serialiseData-memory-arguments-slope": 2, + "sha2_256-cpu-arguments-intercept": 806990, + "sha2_256-cpu-arguments-slope": 30482, + "sha2_256-memory-arguments": 4, + "sha3_256-cpu-arguments-intercept": 1927926, + "sha3_256-cpu-arguments-slope": 82523, + "sha3_256-memory-arguments": 4, + "sliceByteString-cpu-arguments-intercept": 265318, + "sliceByteString-cpu-arguments-slope": 0, + "sliceByteString-memory-arguments-intercept": 4, + "sliceByteString-memory-arguments-slope": 0, + "sndPair-cpu-arguments": 85931, + "sndPair-memory-arguments": 32, + "subtractInteger-cpu-arguments-intercept": 205665, + "subtractInteger-cpu-arguments-slope": 812, + "subtractInteger-memory-arguments-intercept": 1, + "subtractInteger-memory-arguments-slope": 1, + "tailList-cpu-arguments": 41182, + "tailList-memory-arguments": 32, + "trace-cpu-arguments": 212342, + "trace-memory-arguments": 32, + "unBData-cpu-arguments": 31220, "unBData-memory-arguments": 32, - "addInteger-cpu-arguments-intercept": 197209, - "mkNilPairData-cpu-arguments": 150000, - "divideInteger-memory-arguments-slope": 1 + "unConstrData-cpu-arguments": 32696, + "unConstrData-memory-arguments": 32, + "unIData-cpu-arguments": 43357, + "unIData-memory-arguments": 32, + "unListData-cpu-arguments": 32247, + "unListData-memory-arguments": 32, + "unMapData-cpu-arguments": 38314, + "unMapData-memory-arguments": 32, + "verifyEcdsaSecp256k1Signature-cpu-arguments": 35892428, + "verifyEcdsaSecp256k1Signature-memory-arguments": 10, + "verifyEd25519Signature-cpu-arguments-intercept": 9462713, + "verifyEd25519Signature-cpu-arguments-slope": 1021, + "verifyEd25519Signature-memory-arguments": 10, + "verifySchnorrSecp256k1Signature-cpu-arguments-intercept": 38887044, + "verifySchnorrSecp256k1Signature-cpu-arguments-slope": 32947, + "verifySchnorrSecp256k1Signature-memory-arguments": 10 } }, + "decentralization": null, + "executionUnitPrices": { + "priceMemory": 5.77e-2, + "priceSteps": 7.21e-5 + }, + "extraPraosEntropy": null, + "maxBlockBodySize": 65536, + "maxBlockExecutionUnits": { + "memory": 50000000, + "steps": 40000000000 + }, + "maxBlockHeaderSize": 1100, + "maxCollateralInputs": 3, "maxTxExecutionUnits": { - "memory": 16000000, + "memory": 10000000, "steps": 10000000000 }, - "executionUnitPrices": { - "priceSteps": 7.21e-5, - "priceMemory": 5.77e-2 - }, - "decentralization": 0, - "utxoCostPerWord": 34482, "maxTxSize": 16384, - "maxBlockBodySize": 98304 + "maxValueSize": 5000, + "minPoolCost": 0, + "minUTxOValue": null, + "monetaryExpansion": 1.78650067e-3, + "poolPledgeInfluence": 0.1, + "poolRetireMaxEpoch": 18, + "protocolVersion": { + "major": 7, + "minor": 0 + }, + "stakeAddressDeposit": 400000, + "stakePoolDeposit": 500000000, + "stakePoolTargetNum": 50, + "treasuryCut": 0.1, + "txFeeFixed": 155381, + "txFeePerByte": 44, + "utxoCostPerWord": 34480 } \ No newline at end of file diff --git a/examples/plutus-game/src/Cardano/PlutusExample/Game.hs b/examples/plutus-game/src/Cardano/PlutusExample/Game.hs index 2183e181..158dd2b4 100644 --- a/examples/plutus-game/src/Cardano/PlutusExample/Game.hs +++ b/examples/plutus-game/src/Cardano/PlutusExample/Game.hs @@ -16,7 +16,7 @@ import Data.Text (Text) import GHC.Generics (Generic) import Ledger qualified import Ledger.Ada qualified as Ada -import Ledger.Constraints as Constraints +import Ledger.Constraints qualified as Constraints import Ledger.Scripts qualified as Scripts import Ledger.Typed.Scripts ( TypedValidator, @@ -24,7 +24,7 @@ import Ledger.Typed.Scripts ( validatorAddress, validatorHash, ) -import Ledger.Typed.Scripts qualified as Scripts +import Ledger.Typed.Scripts qualified as TypedScripts import Plutus.Contract (Contract, Endpoint, submitTxConstraints, submitTxConstraintsWith, utxosAt, type (.\/)) import Plutus.V1.Ledger.Scripts (Datum (Datum), Redeemer (Redeemer)) import PlutusTx qualified @@ -41,19 +41,19 @@ mkValidator _ datum redeemer _ = gameValidator :: Integer -> TypedValidator Game gameValidator gameId = - Scripts.mkTypedValidator @Game + TypedScripts.mkTypedValidator @Game ($$(PlutusTx.compile [||mkValidator||]) `PlutusTx.applyCode` PlutusTx.liftCode gameId) $$(PlutusTx.compile [||wrap||]) where - wrap = Scripts.wrapValidator @BuiltinByteString @BuiltinByteString + wrap = TypedScripts.mkUntypedValidator @BuiltinByteString @BuiltinByteString data Game instance ValidatorTypes Game where type RedeemerType Game = BuiltinByteString type DatumType Game = BuiltinByteString -script :: Integer -> Ledger.Script -script = Scripts.unValidatorScript . Scripts.validatorScript . gameValidator +script :: Integer -> Scripts.Script +script = Scripts.unValidatorScript . TypedScripts.validatorScript . gameValidator lockScriptSBS :: Integer -> SBS.ShortByteString lockScriptSBS gameId = SBS.toShort . LBS.toStrict $ serialise $ script gameId @@ -99,7 +99,7 @@ guess GuessParams {guessGameId = gameId, guessSecret = secret} = do utxos <- utxosAt valAddr let lookups = - Constraints.otherScript (Scripts.validatorScript validator) + Constraints.plutusV1OtherScript (TypedScripts.validatorScript validator) <> Constraints.unspentOutputs utxos tx = mconcat $ map (`Constraints.mustSpendScriptOutput` redeemer) $ Map.keys utxos diff --git a/examples/plutus-nft/cabal.project b/examples/plutus-nft/cabal.project index 67d6ae9c..bbcecc5f 100644 --- a/examples/plutus-nft/cabal.project +++ b/examples/plutus-nft/cabal.project @@ -1,5 +1,5 @@ -- Bump this if you need newer packages -index-state: 2021-10-20T00:00:00Z +index-state: 2022-05-18T00:00:00Z packages: ./. @@ -11,4 +11,3 @@ write-ghc-environment-files: never -- Always build tests and benchmarks. tests: true benchmarks: true - diff --git a/examples/plutus-nft/pabConfig.value b/examples/plutus-nft/pabConfig.value index 833c4a70..ca76860d 100644 --- a/examples/plutus-nft/pabConfig.value +++ b/examples/plutus-nft/pabConfig.value @@ -1,7 +1,7 @@ -- Calling the cli locally or through an ssh connection cliLocation: local chainIndexUrl: "http://localhost:9083" -networkId: 1097911063 +networkId: 9 -- Directory name of the script and data files scriptFileDir: "./scripts" diff --git a/examples/plutus-nft/plutus-nft.cabal b/examples/plutus-nft/plutus-nft.cabal index 95b92886..7622d729 100644 --- a/examples/plutus-nft/plutus-nft.cabal +++ b/examples/plutus-nft/plutus-nft.cabal @@ -74,7 +74,7 @@ library import: common-lang exposed-modules: Cardano.PlutusExample.NFT build-depends: - , aeson ^>=1.5.0.0 + , aeson , attoparsec >=0.13.2.2 , base16-bytestring , bytestring ^>=0.10.12.0 @@ -103,6 +103,7 @@ library , plutus-ledger-api , plutus-ledger-constraints , plutus-pab + , plutus-script-utils , plutus-tx , plutus-tx-plugin , process @@ -127,7 +128,7 @@ library executable plutus-nft-pab import: common-lang build-depends: - , aeson ^>=1.5.0.0 + , aeson , bot-plutus-interface , bytestring , cardano-api diff --git a/examples/plutus-nft/protocol.json b/examples/plutus-nft/protocol.json index daa1b5f1..1ac232cd 100644 --- a/examples/plutus-nft/protocol.json +++ b/examples/plutus-nft/protocol.json @@ -1,208 +1,385 @@ { - "txFeePerByte": 44, - "minUTxOValue": null, - "decentralization": 0.7, - "utxoCostPerWord": 34482, - "stakePoolDeposit": 0, - "poolRetireMaxEpoch": 18, - "extraPraosEntropy": null, "collateralPercentage": 150, - "stakePoolTargetNum": 100, - "maxBlockBodySize": 65536, - "minPoolCost": 0, - "maxTxSize": 16384, - "treasuryCut": 0.1, - "maxBlockExecutionUnits": { - "memory": 50000000, - "steps": 40000000000 - }, - "maxCollateralInputs": 3, - "maxValueSize": 5000, - "maxBlockHeaderSize": 1100, - "maxTxExecutionUnits": { - "memory": 10000000, - "steps": 10000000000 - }, "costModels": { "PlutusScriptV1": { + "addInteger-cpu-arguments-intercept": 205665, + "addInteger-cpu-arguments-slope": 812, + "addInteger-memory-arguments-intercept": 1, + "addInteger-memory-arguments-slope": 1, + "appendByteString-cpu-arguments-intercept": 1000, + "appendByteString-cpu-arguments-slope": 571, + "appendByteString-memory-arguments-intercept": 0, + "appendByteString-memory-arguments-slope": 1, + "appendString-cpu-arguments-intercept": 1000, + "appendString-cpu-arguments-slope": 24177, + "appendString-memory-arguments-intercept": 4, + "appendString-memory-arguments-slope": 1, + "bData-cpu-arguments": 1000, + "bData-memory-arguments": 32, + "blake2b_256-cpu-arguments-intercept": 117366, + "blake2b_256-cpu-arguments-slope": 10475, + "blake2b_256-memory-arguments": 4, + "cekApplyCost-exBudgetCPU": 23000, + "cekApplyCost-exBudgetMemory": 100, + "cekBuiltinCost-exBudgetCPU": 23000, + "cekBuiltinCost-exBudgetMemory": 100, + "cekConstCost-exBudgetCPU": 23000, "cekConstCost-exBudgetMemory": 100, - "unBData-cpu-arguments": 150000, - "divideInteger-memory-arguments-minimum": 1, - "nullList-cpu-arguments": 150000, + "cekDelayCost-exBudgetCPU": 23000, "cekDelayCost-exBudgetMemory": 100, - "appendByteString-cpu-arguments-slope": 621, - "sha2_256-memory-arguments": 4, - "multiplyInteger-cpu-arguments-intercept": 61516, - "iData-cpu-arguments": 150000, - "equalsString-cpu-arguments-intercept": 150000, - "trace-cpu-arguments": 150000, - "lessThanEqualsByteString-cpu-arguments-intercept": 103599, - "encodeUtf8-cpu-arguments-slope": 1000, - "equalsString-cpu-arguments-constant": 1000, - "blake2b-cpu-arguments-slope": 29175, - "consByteString-memory-arguments-intercept": 0, - "headList-cpu-arguments": 150000, - "listData-cpu-arguments": 150000, - "divideInteger-cpu-arguments-model-arguments-slope": 118, - "divideInteger-memory-arguments-slope": 1, - "bData-cpu-arguments": 150000, + "cekForceCost-exBudgetCPU": 23000, + "cekForceCost-exBudgetMemory": 100, + "cekLamCost-exBudgetCPU": 23000, + "cekLamCost-exBudgetMemory": 100, + "cekStartupCost-exBudgetCPU": 100, + "cekStartupCost-exBudgetMemory": 100, + "cekVarCost-exBudgetCPU": 23000, + "cekVarCost-exBudgetMemory": 100, + "chooseData-cpu-arguments": 19537, "chooseData-memory-arguments": 32, - "cekBuiltinCost-exBudgetCPU": 29773, - "mkNilData-memory-arguments": 32, - "equalsInteger-cpu-arguments-intercept": 136542, - "lengthOfByteString-cpu-arguments": 150000, - "subtractInteger-cpu-arguments-slope": 0, - "unIData-cpu-arguments": 150000, - "sliceByteString-cpu-arguments-slope": 5000, - "unMapData-cpu-arguments": 150000, - "modInteger-cpu-arguments-model-arguments-slope": 118, - "lessThanInteger-cpu-arguments-intercept": 179690, - "appendString-memory-arguments-intercept": 0, - "mkCons-cpu-arguments": 150000, - "sha3_256-cpu-arguments-slope": 82363, - "ifThenElse-cpu-arguments": 1, - "mkNilPairData-cpu-arguments": 150000, - "constrData-memory-arguments": 32, - "lessThanEqualsInteger-cpu-arguments-intercept": 145276, - "addInteger-memory-arguments-slope": 1, + "chooseList-cpu-arguments": 175354, "chooseList-memory-arguments": 32, + "chooseUnit-cpu-arguments": 46417, + "chooseUnit-memory-arguments": 4, + "consByteString-cpu-arguments-intercept": 221973, + "consByteString-cpu-arguments-slope": 511, + "consByteString-memory-arguments-intercept": 0, + "consByteString-memory-arguments-slope": 1, + "constrData-cpu-arguments": 89141, + "constrData-memory-arguments": 32, + "decodeUtf8-cpu-arguments-intercept": 497525, + "decodeUtf8-cpu-arguments-slope": 14068, + "decodeUtf8-memory-arguments-intercept": 4, + "decodeUtf8-memory-arguments-slope": 2, + "divideInteger-cpu-arguments-constant": 196500, + "divideInteger-cpu-arguments-model-arguments-intercept": 453240, + "divideInteger-cpu-arguments-model-arguments-slope": 220, + "divideInteger-memory-arguments-intercept": 0, + "divideInteger-memory-arguments-minimum": 1, + "divideInteger-memory-arguments-slope": 1, + "encodeUtf8-cpu-arguments-intercept": 1000, + "encodeUtf8-cpu-arguments-slope": 28662, + "encodeUtf8-memory-arguments-intercept": 4, + "encodeUtf8-memory-arguments-slope": 2, + "equalsByteString-cpu-arguments-constant": 245000, + "equalsByteString-cpu-arguments-intercept": 216773, + "equalsByteString-cpu-arguments-slope": 62, + "equalsByteString-memory-arguments": 1, + "equalsData-cpu-arguments-intercept": 1060367, + "equalsData-cpu-arguments-slope": 12586, "equalsData-memory-arguments": 1, - "decodeUtf8-cpu-arguments-intercept": 150000, - "bData-memory-arguments": 32, - "lessThanByteString-cpu-arguments-slope": 248, - "listData-memory-arguments": 32, - "consByteString-cpu-arguments-intercept": 150000, + "equalsInteger-cpu-arguments-intercept": 208512, + "equalsInteger-cpu-arguments-slope": 421, + "equalsInteger-memory-arguments": 1, + "equalsString-cpu-arguments-constant": 187000, + "equalsString-cpu-arguments-intercept": 1000, + "equalsString-cpu-arguments-slope": 52998, + "equalsString-memory-arguments": 1, + "fstPair-cpu-arguments": 80436, + "fstPair-memory-arguments": 32, + "headList-cpu-arguments": 43249, "headList-memory-arguments": 32, - "subtractInteger-memory-arguments-slope": 1, - "appendByteString-memory-arguments-intercept": 0, - "unIData-memory-arguments": 32, + "iData-cpu-arguments": 1000, + "iData-memory-arguments": 32, + "ifThenElse-cpu-arguments": 80556, + "ifThenElse-memory-arguments": 1, + "indexByteString-cpu-arguments": 57667, + "indexByteString-memory-arguments": 4, + "lengthOfByteString-cpu-arguments": 1000, + "lengthOfByteString-memory-arguments": 10, + "lessThanByteString-cpu-arguments-intercept": 197145, + "lessThanByteString-cpu-arguments-slope": 156, + "lessThanByteString-memory-arguments": 1, + "lessThanEqualsByteString-cpu-arguments-intercept": 197145, + "lessThanEqualsByteString-cpu-arguments-slope": 156, + "lessThanEqualsByteString-memory-arguments": 1, + "lessThanEqualsInteger-cpu-arguments-intercept": 204924, + "lessThanEqualsInteger-cpu-arguments-slope": 473, + "lessThanEqualsInteger-memory-arguments": 1, + "lessThanInteger-cpu-arguments-intercept": 208896, + "lessThanInteger-cpu-arguments-slope": 511, + "lessThanInteger-memory-arguments": 1, + "listData-cpu-arguments": 52467, + "listData-memory-arguments": 32, + "mapData-cpu-arguments": 64832, + "mapData-memory-arguments": 32, + "mkCons-cpu-arguments": 65493, + "mkCons-memory-arguments": 32, + "mkNilData-cpu-arguments": 22558, + "mkNilData-memory-arguments": 32, + "mkNilPairData-cpu-arguments": 16563, + "mkNilPairData-memory-arguments": 32, + "mkPairData-cpu-arguments": 76511, + "mkPairData-memory-arguments": 32, + "modInteger-cpu-arguments-constant": 196500, + "modInteger-cpu-arguments-model-arguments-intercept": 453240, + "modInteger-cpu-arguments-model-arguments-slope": 220, + "modInteger-memory-arguments-intercept": 0, + "modInteger-memory-arguments-minimum": 1, + "modInteger-memory-arguments-slope": 1, + "multiplyInteger-cpu-arguments-intercept": 69522, + "multiplyInteger-cpu-arguments-slope": 11687, + "multiplyInteger-memory-arguments-intercept": 0, + "multiplyInteger-memory-arguments-slope": 1, + "nullList-cpu-arguments": 60091, + "nullList-memory-arguments": 32, + "quotientInteger-cpu-arguments-constant": 196500, + "quotientInteger-cpu-arguments-model-arguments-intercept": 453240, + "quotientInteger-cpu-arguments-model-arguments-slope": 220, + "quotientInteger-memory-arguments-intercept": 0, + "quotientInteger-memory-arguments-minimum": 1, + "quotientInteger-memory-arguments-slope": 1, + "remainderInteger-cpu-arguments-constant": 196500, + "remainderInteger-cpu-arguments-model-arguments-intercept": 453240, + "remainderInteger-cpu-arguments-model-arguments-slope": 220, + "remainderInteger-memory-arguments-intercept": 0, "remainderInteger-memory-arguments-minimum": 1, - "lengthOfByteString-memory-arguments": 4, - "encodeUtf8-memory-arguments-intercept": 0, - "cekStartupCost-exBudgetCPU": 100, "remainderInteger-memory-arguments-slope": 1, - "multiplyInteger-memory-arguments-intercept": 0, - "cekForceCost-exBudgetCPU": 29773, + "sha2_256-cpu-arguments-intercept": 806990, + "sha2_256-cpu-arguments-slope": 30482, + "sha2_256-memory-arguments": 4, + "sha3_256-cpu-arguments-intercept": 1927926, + "sha3_256-cpu-arguments-slope": 82523, + "sha3_256-memory-arguments": 4, + "sliceByteString-cpu-arguments-intercept": 265318, + "sliceByteString-cpu-arguments-slope": 0, + "sliceByteString-memory-arguments-intercept": 4, + "sliceByteString-memory-arguments-slope": 0, + "sndPair-cpu-arguments": 85931, + "sndPair-memory-arguments": 32, + "subtractInteger-cpu-arguments-intercept": 205665, + "subtractInteger-cpu-arguments-slope": 812, + "subtractInteger-memory-arguments-intercept": 1, + "subtractInteger-memory-arguments-slope": 1, + "tailList-cpu-arguments": 41182, + "tailList-memory-arguments": 32, + "trace-cpu-arguments": 212342, + "trace-memory-arguments": 32, + "unBData-cpu-arguments": 31220, + "unBData-memory-arguments": 32, + "unConstrData-cpu-arguments": 32696, + "unConstrData-memory-arguments": 32, + "unIData-cpu-arguments": 43357, + "unIData-memory-arguments": 32, + "unListData-cpu-arguments": 32247, "unListData-memory-arguments": 32, - "sha2_256-cpu-arguments-slope": 29175, - "indexByteString-memory-arguments": 1, - "equalsInteger-memory-arguments": 1, - "remainderInteger-cpu-arguments-model-arguments-slope": 118, - "cekVarCost-exBudgetCPU": 29773, - "lessThanEqualsInteger-cpu-arguments-slope": 1366, + "unMapData-cpu-arguments": 38314, + "unMapData-memory-arguments": 32, + "verifyEd25519Signature-cpu-arguments-intercept": 9462713, + "verifyEd25519Signature-cpu-arguments-slope": 1021, + "verifyEd25519Signature-memory-arguments": 10 + }, + "PlutusScriptV2": { + "addInteger-cpu-arguments-intercept": 205665, + "addInteger-cpu-arguments-slope": 812, "addInteger-memory-arguments-intercept": 1, - "sndPair-cpu-arguments": 150000, - "lessThanInteger-memory-arguments": 1, - "cekLamCost-exBudgetCPU": 29773, - "chooseUnit-cpu-arguments": 150000, - "decodeUtf8-cpu-arguments-slope": 1000, - "fstPair-cpu-arguments": 150000, - "quotientInteger-memory-arguments-minimum": 1, - "lessThanEqualsInteger-memory-arguments": 1, - "chooseUnit-memory-arguments": 32, - "fstPair-memory-arguments": 32, - "quotientInteger-cpu-arguments-constant": 148000, - "mapData-cpu-arguments": 150000, - "unConstrData-cpu-arguments": 150000, - "mkPairData-cpu-arguments": 150000, - "sndPair-memory-arguments": 32, - "decodeUtf8-memory-arguments-slope": 8, - "equalsData-cpu-arguments-intercept": 150000, - "addInteger-cpu-arguments-intercept": 197209, - "modInteger-memory-arguments-intercept": 0, + "addInteger-memory-arguments-slope": 1, + "appendByteString-cpu-arguments-intercept": 1000, + "appendByteString-cpu-arguments-slope": 571, + "appendByteString-memory-arguments-intercept": 0, + "appendByteString-memory-arguments-slope": 1, + "appendString-cpu-arguments-intercept": 1000, + "appendString-cpu-arguments-slope": 24177, + "appendString-memory-arguments-intercept": 4, + "appendString-memory-arguments-slope": 1, + "bData-cpu-arguments": 1000, + "bData-memory-arguments": 32, + "blake2b_256-cpu-arguments-intercept": 117366, + "blake2b_256-cpu-arguments-slope": 10475, + "blake2b_256-memory-arguments": 4, + "cekApplyCost-exBudgetCPU": 23000, + "cekApplyCost-exBudgetMemory": 100, + "cekBuiltinCost-exBudgetCPU": 23000, + "cekBuiltinCost-exBudgetMemory": 100, + "cekConstCost-exBudgetCPU": 23000, + "cekConstCost-exBudgetMemory": 100, + "cekDelayCost-exBudgetCPU": 23000, + "cekDelayCost-exBudgetMemory": 100, + "cekForceCost-exBudgetCPU": 23000, + "cekForceCost-exBudgetMemory": 100, + "cekLamCost-exBudgetCPU": 23000, + "cekLamCost-exBudgetMemory": 100, + "cekStartupCost-exBudgetCPU": 100, "cekStartupCost-exBudgetMemory": 100, - "divideInteger-cpu-arguments-model-arguments-intercept": 425507, - "divideInteger-memory-arguments-intercept": 0, + "cekVarCost-exBudgetCPU": 23000, "cekVarCost-exBudgetMemory": 100, + "chooseData-cpu-arguments": 19537, + "chooseData-memory-arguments": 32, + "chooseList-cpu-arguments": 175354, + "chooseList-memory-arguments": 32, + "chooseUnit-cpu-arguments": 46417, + "chooseUnit-memory-arguments": 4, + "consByteString-cpu-arguments-intercept": 221973, + "consByteString-cpu-arguments-slope": 511, + "consByteString-memory-arguments-intercept": 0, "consByteString-memory-arguments-slope": 1, - "cekForceCost-exBudgetMemory": 100, - "unListData-cpu-arguments": 150000, - "subtractInteger-cpu-arguments-intercept": 197209, - "indexByteString-cpu-arguments": 150000, - "equalsInteger-cpu-arguments-slope": 1326, - "lessThanByteString-memory-arguments": 1, - "blake2b-cpu-arguments-intercept": 2477736, - "encodeUtf8-cpu-arguments-intercept": 150000, - "multiplyInteger-cpu-arguments-slope": 11218, - "tailList-cpu-arguments": 150000, - "appendByteString-cpu-arguments-intercept": 396231, - "equalsString-cpu-arguments-slope": 1000, - "lessThanEqualsByteString-cpu-arguments-slope": 248, - "remainderInteger-cpu-arguments-constant": 148000, - "chooseList-cpu-arguments": 150000, + "constrData-cpu-arguments": 89141, + "constrData-memory-arguments": 32, + "decodeUtf8-cpu-arguments-intercept": 497525, + "decodeUtf8-cpu-arguments-slope": 14068, + "decodeUtf8-memory-arguments-intercept": 4, + "decodeUtf8-memory-arguments-slope": 2, + "divideInteger-cpu-arguments-constant": 196500, + "divideInteger-cpu-arguments-model-arguments-intercept": 453240, + "divideInteger-cpu-arguments-model-arguments-slope": 220, + "divideInteger-memory-arguments-intercept": 0, + "divideInteger-memory-arguments-minimum": 1, + "divideInteger-memory-arguments-slope": 1, + "encodeUtf8-cpu-arguments-intercept": 1000, + "encodeUtf8-cpu-arguments-slope": 28662, + "encodeUtf8-memory-arguments-intercept": 4, + "encodeUtf8-memory-arguments-slope": 2, + "equalsByteString-cpu-arguments-constant": 245000, + "equalsByteString-cpu-arguments-intercept": 216773, + "equalsByteString-cpu-arguments-slope": 62, "equalsByteString-memory-arguments": 1, - "constrData-cpu-arguments": 150000, - "cekApplyCost-exBudgetCPU": 29773, - "equalsData-cpu-arguments-slope": 10000, - "decodeUtf8-memory-arguments-intercept": 0, - "modInteger-memory-arguments-slope": 1, - "addInteger-cpu-arguments-slope": 0, - "appendString-cpu-arguments-intercept": 150000, - "quotientInteger-cpu-arguments-model-arguments-slope": 118, - "unMapData-memory-arguments": 32, - "cekApplyCost-exBudgetMemory": 100, - "quotientInteger-memory-arguments-slope": 1, - "mkNilPairData-memory-arguments": 32, + "equalsData-cpu-arguments-intercept": 1060367, + "equalsData-cpu-arguments-slope": 12586, + "equalsData-memory-arguments": 1, + "equalsInteger-cpu-arguments-intercept": 208512, + "equalsInteger-cpu-arguments-slope": 421, + "equalsInteger-memory-arguments": 1, + "equalsString-cpu-arguments-constant": 187000, + "equalsString-cpu-arguments-intercept": 1000, + "equalsString-cpu-arguments-slope": 52998, + "equalsString-memory-arguments": 1, + "fstPair-cpu-arguments": 80436, + "fstPair-memory-arguments": 32, + "headList-cpu-arguments": 43249, + "headList-memory-arguments": 32, + "iData-cpu-arguments": 1000, + "iData-memory-arguments": 32, + "ifThenElse-cpu-arguments": 80556, "ifThenElse-memory-arguments": 1, - "equalsByteString-cpu-arguments-slope": 247, - "sliceByteString-memory-arguments-slope": 1, - "sha3_256-memory-arguments": 4, - "mkCons-memory-arguments": 32, - "verifySignature-cpu-arguments-intercept": 3345831, - "cekBuiltinCost-exBudgetMemory": 100, - "remainderInteger-memory-arguments-intercept": 0, + "indexByteString-cpu-arguments": 57667, + "indexByteString-memory-arguments": 4, + "lengthOfByteString-cpu-arguments": 1000, + "lengthOfByteString-memory-arguments": 10, + "lessThanByteString-cpu-arguments-intercept": 197145, + "lessThanByteString-cpu-arguments-slope": 156, + "lessThanByteString-memory-arguments": 1, + "lessThanEqualsByteString-cpu-arguments-intercept": 197145, + "lessThanEqualsByteString-cpu-arguments-slope": 156, "lessThanEqualsByteString-memory-arguments": 1, - "mkNilData-cpu-arguments": 150000, - "equalsString-memory-arguments": 1, - "chooseData-cpu-arguments": 150000, - "remainderInteger-cpu-arguments-model-arguments-intercept": 425507, - "tailList-memory-arguments": 32, - "sha2_256-cpu-arguments-intercept": 2477736, + "lessThanEqualsInteger-cpu-arguments-intercept": 204924, + "lessThanEqualsInteger-cpu-arguments-slope": 473, + "lessThanEqualsInteger-memory-arguments": 1, + "lessThanInteger-cpu-arguments-intercept": 208896, + "lessThanInteger-cpu-arguments-slope": 511, + "lessThanInteger-memory-arguments": 1, + "listData-cpu-arguments": 52467, + "listData-memory-arguments": 32, + "mapData-cpu-arguments": 64832, + "mapData-memory-arguments": 32, + "mkCons-cpu-arguments": 65493, + "mkCons-memory-arguments": 32, + "mkNilData-cpu-arguments": 22558, + "mkNilData-memory-arguments": 32, + "mkNilPairData-cpu-arguments": 16563, + "mkNilPairData-memory-arguments": 32, + "mkPairData-cpu-arguments": 76511, + "mkPairData-memory-arguments": 32, + "modInteger-cpu-arguments-constant": 196500, + "modInteger-cpu-arguments-model-arguments-intercept": 453240, + "modInteger-cpu-arguments-model-arguments-slope": 220, + "modInteger-memory-arguments-intercept": 0, + "modInteger-memory-arguments-minimum": 1, + "modInteger-memory-arguments-slope": 1, + "multiplyInteger-cpu-arguments-intercept": 69522, + "multiplyInteger-cpu-arguments-slope": 11687, + "multiplyInteger-memory-arguments-intercept": 0, "multiplyInteger-memory-arguments-slope": 1, - "iData-memory-arguments": 32, - "divideInteger-cpu-arguments-constant": 148000, - "cekDelayCost-exBudgetCPU": 29773, - "encodeUtf8-memory-arguments-slope": 8, - "subtractInteger-memory-arguments-intercept": 1, + "nullList-cpu-arguments": 60091, "nullList-memory-arguments": 32, - "lessThanByteString-cpu-arguments-intercept": 103599, - "appendByteString-memory-arguments-slope": 1, - "blake2b-memory-arguments": 4, - "unBData-memory-arguments": 32, - "cekConstCost-exBudgetCPU": 29773, - "consByteString-cpu-arguments-slope": 1000, - "trace-memory-arguments": 32, + "quotientInteger-cpu-arguments-constant": 196500, + "quotientInteger-cpu-arguments-model-arguments-intercept": 453240, + "quotientInteger-cpu-arguments-model-arguments-slope": 220, "quotientInteger-memory-arguments-intercept": 0, - "mapData-memory-arguments": 32, - "verifySignature-cpu-arguments-slope": 1, - "quotientInteger-cpu-arguments-model-arguments-intercept": 425507, - "modInteger-cpu-arguments-constant": 148000, - "appendString-cpu-arguments-slope": 1000, + "quotientInteger-memory-arguments-minimum": 1, + "quotientInteger-memory-arguments-slope": 1, + "remainderInteger-cpu-arguments-constant": 196500, + "remainderInteger-cpu-arguments-model-arguments-intercept": 453240, + "remainderInteger-cpu-arguments-model-arguments-slope": 220, + "remainderInteger-memory-arguments-intercept": 0, + "remainderInteger-memory-arguments-minimum": 1, + "remainderInteger-memory-arguments-slope": 1, + "serialiseData-cpu-arguments-intercept": 1159724, + "serialiseData-cpu-arguments-slope": 392670, + "serialiseData-memory-arguments-intercept": 0, + "serialiseData-memory-arguments-slope": 2, + "sha2_256-cpu-arguments-intercept": 806990, + "sha2_256-cpu-arguments-slope": 30482, + "sha2_256-memory-arguments": 4, + "sha3_256-cpu-arguments-intercept": 1927926, + "sha3_256-cpu-arguments-slope": 82523, + "sha3_256-memory-arguments": 4, + "sliceByteString-cpu-arguments-intercept": 265318, + "sliceByteString-cpu-arguments-slope": 0, + "sliceByteString-memory-arguments-intercept": 4, + "sliceByteString-memory-arguments-slope": 0, + "sndPair-cpu-arguments": 85931, + "sndPair-memory-arguments": 32, + "subtractInteger-cpu-arguments-intercept": 205665, + "subtractInteger-cpu-arguments-slope": 812, + "subtractInteger-memory-arguments-intercept": 1, + "subtractInteger-memory-arguments-slope": 1, + "tailList-cpu-arguments": 41182, + "tailList-memory-arguments": 32, + "trace-cpu-arguments": 212342, + "trace-memory-arguments": 32, + "unBData-cpu-arguments": 31220, + "unBData-memory-arguments": 32, + "unConstrData-cpu-arguments": 32696, "unConstrData-memory-arguments": 32, - "mkPairData-memory-arguments": 32, - "equalsByteString-cpu-arguments-constant": 150000, - "equalsByteString-cpu-arguments-intercept": 112536, - "sliceByteString-memory-arguments-intercept": 0, - "lessThanInteger-cpu-arguments-slope": 497, - "verifySignature-memory-arguments": 1, - "cekLamCost-exBudgetMemory": 100, - "sliceByteString-cpu-arguments-intercept": 150000, - "modInteger-cpu-arguments-model-arguments-intercept": 425507, - "modInteger-memory-arguments-minimum": 1, - "appendString-memory-arguments-slope": 1, - "sha3_256-cpu-arguments-intercept": 0 + "unIData-cpu-arguments": 43357, + "unIData-memory-arguments": 32, + "unListData-cpu-arguments": 32247, + "unListData-memory-arguments": 32, + "unMapData-cpu-arguments": 38314, + "unMapData-memory-arguments": 32, + "verifyEcdsaSecp256k1Signature-cpu-arguments": 35892428, + "verifyEcdsaSecp256k1Signature-memory-arguments": 10, + "verifyEd25519Signature-cpu-arguments-intercept": 9462713, + "verifyEd25519Signature-cpu-arguments-slope": 1021, + "verifyEd25519Signature-memory-arguments": 10, + "verifySchnorrSecp256k1Signature-cpu-arguments-intercept": 38887044, + "verifySchnorrSecp256k1Signature-cpu-arguments-slope": 32947, + "verifySchnorrSecp256k1Signature-memory-arguments": 10 } }, + "decentralization": null, + "executionUnitPrices": { + "priceMemory": 5.77e-2, + "priceSteps": 7.21e-5 + }, + "extraPraosEntropy": null, + "maxBlockBodySize": 65536, + "maxBlockExecutionUnits": { + "memory": 50000000, + "steps": 40000000000 + }, + "maxBlockHeaderSize": 1100, + "maxCollateralInputs": 3, + "maxTxExecutionUnits": { + "memory": 10000000, + "steps": 10000000000 + }, + "maxTxSize": 16384, + "maxValueSize": 5000, + "minPoolCost": 0, + "minUTxOValue": null, + "monetaryExpansion": 1.78650067e-3, + "poolPledgeInfluence": 0.1, + "poolRetireMaxEpoch": 18, "protocolVersion": { - "minor": 0, - "major": 5 + "major": 7, + "minor": 0 }, + "stakeAddressDeposit": 400000, + "stakePoolDeposit": 500000000, + "stakePoolTargetNum": 50, + "treasuryCut": 0.1, "txFeeFixed": 155381, - "stakeAddressDeposit": 0, - "monetaryExpansion": 0.1, - "poolPledgeInfluence": 0, - "executionUnitPrices": { - "priceSteps": 7.21e-5, - "priceMemory": 5.77e-2 - } + "txFeePerByte": 44, + "utxoCostPerWord": 34480 } \ No newline at end of file diff --git a/examples/plutus-nft/src/Cardano/PlutusExample/NFT.hs b/examples/plutus-nft/src/Cardano/PlutusExample/NFT.hs index eb0a4b2f..14324f8d 100644 --- a/examples/plutus-nft/src/Cardano/PlutusExample/NFT.hs +++ b/examples/plutus-nft/src/Cardano/PlutusExample/NFT.hs @@ -17,35 +17,23 @@ import Data.Void (Void) import Ledger ( CurrencySymbol, PaymentPubKeyHash, - Script, ScriptContext (scriptContextTxInfo), TokenName, TxInInfo (txInInfoOutRef), TxInfo (txInfoInputs, txInfoMint), TxOutRef, - mkMintingPolicyScript, ownCurrencySymbol, pubKeyHashAddress, - scriptCurrencySymbol, ) import Ledger.Address (StakePubKeyHash) import Ledger.Constraints as Constraints -import Ledger.Constraints.Metadata ( - NftMetadata (NftMetadata), - NftMetadataToken (NftMetadataToken), - TxMetadata (TxMetadata), - nmtDescription, - nmtFiles, - nmtImage, - nmtMediaType, - nmtName, - nmtOtherFields, - ) -import Ledger.Typed.Scripts (wrapMintingPolicy) + +import Ledger.Scripts qualified as Scripts +import Ledger.Typed.Scripts qualified as TypedScripts import Ledger.Value (flattenValue, singleton) import Plutus.Contract (Contract, Endpoint, submitTxConstraintsWith, tell, utxosAt) import Plutus.Contract qualified as Contract -import Plutus.V1.Ledger.Scripts qualified as Scripts +import Plutus.Script.Utils.V1.Scripts qualified as ScriptUtils import PlutusTx qualified import PlutusTx.Prelude import Text.Printf (printf) @@ -70,12 +58,12 @@ mkPolicy oref tn _ ctx = policy :: TxOutRef -> TokenName -> Scripts.MintingPolicy policy oref tn = - mkMintingPolicyScript $ - $$(PlutusTx.compile [||\oref' tn' -> wrapMintingPolicy $ mkPolicy oref' tn'||]) + Scripts.mkMintingPolicyScript $ + $$(PlutusTx.compile [||\oref' tn' -> TypedScripts.mkUntypedMintingPolicy $ mkPolicy oref' tn'||]) `PlutusTx.applyCode` PlutusTx.liftCode oref `PlutusTx.applyCode` PlutusTx.liftCode tn -policyScript :: TxOutRef -> TokenName -> Script +policyScript :: TxOutRef -> TokenName -> Scripts.Script policyScript oref tn = Scripts.unMintingPolicyScript $ policy oref tn policySBS :: TxOutRef -> TokenName -> SBS.ShortByteString @@ -85,7 +73,7 @@ policySerialised :: TxOutRef -> TokenName -> PlutusScript PlutusScriptV1 policySerialised oref tn = PlutusScriptSerialised $ policySBS oref tn curSymbol :: TxOutRef -> TokenName -> CurrencySymbol -curSymbol oref tn = scriptCurrencySymbol $ policy oref tn +curSymbol oref tn = ScriptUtils.scriptCurrencySymbol $ policy oref tn type NFTSchema = Endpoint "mint" TokenName @@ -104,7 +92,7 @@ $(deriveJSON defaultOptions ''MintParams) mintNft :: MintParams -> Contract (Last Text) NFTSchema Text () mintNft MintParams {..} = do - pkh <- Contract.ownPaymentPubKeyHash + pkh <- Contract.ownFirstPaymentPubKeyHash utxos <- utxosAt (pubKeyHashAddress pkh Nothing) case Map.keys utxos of [] -> Contract.logError @Hask.String "no utxo found" @@ -112,21 +100,11 @@ mintNft MintParams {..} = do tell $ Last $ Just $ "Using oref:" Hask.<> Text.pack (Hask.show oref) let cs = curSymbol oref mpTokenName val = singleton cs mpTokenName 1 - meta = - NftMetadata $ - Map.singleton cs $ - Map.singleton mpTokenName $ - NftMetadataToken - { nmtName = mpName - , nmtImage = mpImage - , nmtMediaType = Hask.pure "image/png" - , nmtDescription = mpDescription - , nmtFiles = Hask.mempty - , nmtOtherFields = Hask.mempty - } + -- TODO: Add metadata in the tx. + -- Currently this is not possible, as metadata is not supported. lookups = Hask.mconcat - [ Constraints.mintingPolicy (policy oref mpTokenName) + [ Constraints.plutusV1MintingPolicy (policy oref mpTokenName) , Constraints.unspentOutputs utxos ] tx = @@ -134,7 +112,6 @@ mintNft MintParams {..} = do [ Constraints.mustMintValue val , Constraints.mustSpendPubKeyOutput oref , Constraints.mustPayToPubKeyAddress mpPubKeyHash mpStakeHash val - , Constraints.mustIncludeMetadata $ TxMetadata (Just meta) Hask.mempty ] void $ submitTxConstraintsWith @Void lookups tx Contract.logInfo @Hask.String $ printf "forged %s" (Hask.show val) diff --git a/examples/plutus-transfer/cabal.project b/examples/plutus-transfer/cabal.project index 67d6ae9c..bbcecc5f 100644 --- a/examples/plutus-transfer/cabal.project +++ b/examples/plutus-transfer/cabal.project @@ -1,5 +1,5 @@ -- Bump this if you need newer packages -index-state: 2021-10-20T00:00:00Z +index-state: 2022-05-18T00:00:00Z packages: ./. @@ -11,4 +11,3 @@ write-ghc-environment-files: never -- Always build tests and benchmarks. tests: true benchmarks: true - diff --git a/examples/plutus-transfer/pabConfig.value b/examples/plutus-transfer/pabConfig.value index 9c465699..ca76860d 100644 --- a/examples/plutus-transfer/pabConfig.value +++ b/examples/plutus-transfer/pabConfig.value @@ -1,7 +1,7 @@ -- Calling the cli locally or through an ssh connection cliLocation: local chainIndexUrl: "http://localhost:9083" -networkId: 42 +networkId: 9 -- Directory name of the script and data files scriptFileDir: "./scripts" diff --git a/examples/plutus-transfer/plutus-transfer.cabal b/examples/plutus-transfer/plutus-transfer.cabal index 4ff08a19..c8124466 100644 --- a/examples/plutus-transfer/plutus-transfer.cabal +++ b/examples/plutus-transfer/plutus-transfer.cabal @@ -74,7 +74,7 @@ library import: common-lang exposed-modules: Cardano.PlutusExample.Transfer build-depends: - , aeson ^>=1.5.0.0 + , aeson , attoparsec >=0.13.2.2 , bytestring ^>=0.10.12.0 , cardano-api @@ -125,7 +125,7 @@ library executable plutus-transfer-pab import: common-lang build-depends: - , aeson ^>=1.5.0.0 + , aeson , bot-plutus-interface , bytestring , cardano-api diff --git a/examples/plutus-transfer/protocol.json b/examples/plutus-transfer/protocol.json index daa1b5f1..1ac232cd 100644 --- a/examples/plutus-transfer/protocol.json +++ b/examples/plutus-transfer/protocol.json @@ -1,208 +1,385 @@ { - "txFeePerByte": 44, - "minUTxOValue": null, - "decentralization": 0.7, - "utxoCostPerWord": 34482, - "stakePoolDeposit": 0, - "poolRetireMaxEpoch": 18, - "extraPraosEntropy": null, "collateralPercentage": 150, - "stakePoolTargetNum": 100, - "maxBlockBodySize": 65536, - "minPoolCost": 0, - "maxTxSize": 16384, - "treasuryCut": 0.1, - "maxBlockExecutionUnits": { - "memory": 50000000, - "steps": 40000000000 - }, - "maxCollateralInputs": 3, - "maxValueSize": 5000, - "maxBlockHeaderSize": 1100, - "maxTxExecutionUnits": { - "memory": 10000000, - "steps": 10000000000 - }, "costModels": { "PlutusScriptV1": { + "addInteger-cpu-arguments-intercept": 205665, + "addInteger-cpu-arguments-slope": 812, + "addInteger-memory-arguments-intercept": 1, + "addInteger-memory-arguments-slope": 1, + "appendByteString-cpu-arguments-intercept": 1000, + "appendByteString-cpu-arguments-slope": 571, + "appendByteString-memory-arguments-intercept": 0, + "appendByteString-memory-arguments-slope": 1, + "appendString-cpu-arguments-intercept": 1000, + "appendString-cpu-arguments-slope": 24177, + "appendString-memory-arguments-intercept": 4, + "appendString-memory-arguments-slope": 1, + "bData-cpu-arguments": 1000, + "bData-memory-arguments": 32, + "blake2b_256-cpu-arguments-intercept": 117366, + "blake2b_256-cpu-arguments-slope": 10475, + "blake2b_256-memory-arguments": 4, + "cekApplyCost-exBudgetCPU": 23000, + "cekApplyCost-exBudgetMemory": 100, + "cekBuiltinCost-exBudgetCPU": 23000, + "cekBuiltinCost-exBudgetMemory": 100, + "cekConstCost-exBudgetCPU": 23000, "cekConstCost-exBudgetMemory": 100, - "unBData-cpu-arguments": 150000, - "divideInteger-memory-arguments-minimum": 1, - "nullList-cpu-arguments": 150000, + "cekDelayCost-exBudgetCPU": 23000, "cekDelayCost-exBudgetMemory": 100, - "appendByteString-cpu-arguments-slope": 621, - "sha2_256-memory-arguments": 4, - "multiplyInteger-cpu-arguments-intercept": 61516, - "iData-cpu-arguments": 150000, - "equalsString-cpu-arguments-intercept": 150000, - "trace-cpu-arguments": 150000, - "lessThanEqualsByteString-cpu-arguments-intercept": 103599, - "encodeUtf8-cpu-arguments-slope": 1000, - "equalsString-cpu-arguments-constant": 1000, - "blake2b-cpu-arguments-slope": 29175, - "consByteString-memory-arguments-intercept": 0, - "headList-cpu-arguments": 150000, - "listData-cpu-arguments": 150000, - "divideInteger-cpu-arguments-model-arguments-slope": 118, - "divideInteger-memory-arguments-slope": 1, - "bData-cpu-arguments": 150000, + "cekForceCost-exBudgetCPU": 23000, + "cekForceCost-exBudgetMemory": 100, + "cekLamCost-exBudgetCPU": 23000, + "cekLamCost-exBudgetMemory": 100, + "cekStartupCost-exBudgetCPU": 100, + "cekStartupCost-exBudgetMemory": 100, + "cekVarCost-exBudgetCPU": 23000, + "cekVarCost-exBudgetMemory": 100, + "chooseData-cpu-arguments": 19537, "chooseData-memory-arguments": 32, - "cekBuiltinCost-exBudgetCPU": 29773, - "mkNilData-memory-arguments": 32, - "equalsInteger-cpu-arguments-intercept": 136542, - "lengthOfByteString-cpu-arguments": 150000, - "subtractInteger-cpu-arguments-slope": 0, - "unIData-cpu-arguments": 150000, - "sliceByteString-cpu-arguments-slope": 5000, - "unMapData-cpu-arguments": 150000, - "modInteger-cpu-arguments-model-arguments-slope": 118, - "lessThanInteger-cpu-arguments-intercept": 179690, - "appendString-memory-arguments-intercept": 0, - "mkCons-cpu-arguments": 150000, - "sha3_256-cpu-arguments-slope": 82363, - "ifThenElse-cpu-arguments": 1, - "mkNilPairData-cpu-arguments": 150000, - "constrData-memory-arguments": 32, - "lessThanEqualsInteger-cpu-arguments-intercept": 145276, - "addInteger-memory-arguments-slope": 1, + "chooseList-cpu-arguments": 175354, "chooseList-memory-arguments": 32, + "chooseUnit-cpu-arguments": 46417, + "chooseUnit-memory-arguments": 4, + "consByteString-cpu-arguments-intercept": 221973, + "consByteString-cpu-arguments-slope": 511, + "consByteString-memory-arguments-intercept": 0, + "consByteString-memory-arguments-slope": 1, + "constrData-cpu-arguments": 89141, + "constrData-memory-arguments": 32, + "decodeUtf8-cpu-arguments-intercept": 497525, + "decodeUtf8-cpu-arguments-slope": 14068, + "decodeUtf8-memory-arguments-intercept": 4, + "decodeUtf8-memory-arguments-slope": 2, + "divideInteger-cpu-arguments-constant": 196500, + "divideInteger-cpu-arguments-model-arguments-intercept": 453240, + "divideInteger-cpu-arguments-model-arguments-slope": 220, + "divideInteger-memory-arguments-intercept": 0, + "divideInteger-memory-arguments-minimum": 1, + "divideInteger-memory-arguments-slope": 1, + "encodeUtf8-cpu-arguments-intercept": 1000, + "encodeUtf8-cpu-arguments-slope": 28662, + "encodeUtf8-memory-arguments-intercept": 4, + "encodeUtf8-memory-arguments-slope": 2, + "equalsByteString-cpu-arguments-constant": 245000, + "equalsByteString-cpu-arguments-intercept": 216773, + "equalsByteString-cpu-arguments-slope": 62, + "equalsByteString-memory-arguments": 1, + "equalsData-cpu-arguments-intercept": 1060367, + "equalsData-cpu-arguments-slope": 12586, "equalsData-memory-arguments": 1, - "decodeUtf8-cpu-arguments-intercept": 150000, - "bData-memory-arguments": 32, - "lessThanByteString-cpu-arguments-slope": 248, - "listData-memory-arguments": 32, - "consByteString-cpu-arguments-intercept": 150000, + "equalsInteger-cpu-arguments-intercept": 208512, + "equalsInteger-cpu-arguments-slope": 421, + "equalsInteger-memory-arguments": 1, + "equalsString-cpu-arguments-constant": 187000, + "equalsString-cpu-arguments-intercept": 1000, + "equalsString-cpu-arguments-slope": 52998, + "equalsString-memory-arguments": 1, + "fstPair-cpu-arguments": 80436, + "fstPair-memory-arguments": 32, + "headList-cpu-arguments": 43249, "headList-memory-arguments": 32, - "subtractInteger-memory-arguments-slope": 1, - "appendByteString-memory-arguments-intercept": 0, - "unIData-memory-arguments": 32, + "iData-cpu-arguments": 1000, + "iData-memory-arguments": 32, + "ifThenElse-cpu-arguments": 80556, + "ifThenElse-memory-arguments": 1, + "indexByteString-cpu-arguments": 57667, + "indexByteString-memory-arguments": 4, + "lengthOfByteString-cpu-arguments": 1000, + "lengthOfByteString-memory-arguments": 10, + "lessThanByteString-cpu-arguments-intercept": 197145, + "lessThanByteString-cpu-arguments-slope": 156, + "lessThanByteString-memory-arguments": 1, + "lessThanEqualsByteString-cpu-arguments-intercept": 197145, + "lessThanEqualsByteString-cpu-arguments-slope": 156, + "lessThanEqualsByteString-memory-arguments": 1, + "lessThanEqualsInteger-cpu-arguments-intercept": 204924, + "lessThanEqualsInteger-cpu-arguments-slope": 473, + "lessThanEqualsInteger-memory-arguments": 1, + "lessThanInteger-cpu-arguments-intercept": 208896, + "lessThanInteger-cpu-arguments-slope": 511, + "lessThanInteger-memory-arguments": 1, + "listData-cpu-arguments": 52467, + "listData-memory-arguments": 32, + "mapData-cpu-arguments": 64832, + "mapData-memory-arguments": 32, + "mkCons-cpu-arguments": 65493, + "mkCons-memory-arguments": 32, + "mkNilData-cpu-arguments": 22558, + "mkNilData-memory-arguments": 32, + "mkNilPairData-cpu-arguments": 16563, + "mkNilPairData-memory-arguments": 32, + "mkPairData-cpu-arguments": 76511, + "mkPairData-memory-arguments": 32, + "modInteger-cpu-arguments-constant": 196500, + "modInteger-cpu-arguments-model-arguments-intercept": 453240, + "modInteger-cpu-arguments-model-arguments-slope": 220, + "modInteger-memory-arguments-intercept": 0, + "modInteger-memory-arguments-minimum": 1, + "modInteger-memory-arguments-slope": 1, + "multiplyInteger-cpu-arguments-intercept": 69522, + "multiplyInteger-cpu-arguments-slope": 11687, + "multiplyInteger-memory-arguments-intercept": 0, + "multiplyInteger-memory-arguments-slope": 1, + "nullList-cpu-arguments": 60091, + "nullList-memory-arguments": 32, + "quotientInteger-cpu-arguments-constant": 196500, + "quotientInteger-cpu-arguments-model-arguments-intercept": 453240, + "quotientInteger-cpu-arguments-model-arguments-slope": 220, + "quotientInteger-memory-arguments-intercept": 0, + "quotientInteger-memory-arguments-minimum": 1, + "quotientInteger-memory-arguments-slope": 1, + "remainderInteger-cpu-arguments-constant": 196500, + "remainderInteger-cpu-arguments-model-arguments-intercept": 453240, + "remainderInteger-cpu-arguments-model-arguments-slope": 220, + "remainderInteger-memory-arguments-intercept": 0, "remainderInteger-memory-arguments-minimum": 1, - "lengthOfByteString-memory-arguments": 4, - "encodeUtf8-memory-arguments-intercept": 0, - "cekStartupCost-exBudgetCPU": 100, "remainderInteger-memory-arguments-slope": 1, - "multiplyInteger-memory-arguments-intercept": 0, - "cekForceCost-exBudgetCPU": 29773, + "sha2_256-cpu-arguments-intercept": 806990, + "sha2_256-cpu-arguments-slope": 30482, + "sha2_256-memory-arguments": 4, + "sha3_256-cpu-arguments-intercept": 1927926, + "sha3_256-cpu-arguments-slope": 82523, + "sha3_256-memory-arguments": 4, + "sliceByteString-cpu-arguments-intercept": 265318, + "sliceByteString-cpu-arguments-slope": 0, + "sliceByteString-memory-arguments-intercept": 4, + "sliceByteString-memory-arguments-slope": 0, + "sndPair-cpu-arguments": 85931, + "sndPair-memory-arguments": 32, + "subtractInteger-cpu-arguments-intercept": 205665, + "subtractInteger-cpu-arguments-slope": 812, + "subtractInteger-memory-arguments-intercept": 1, + "subtractInteger-memory-arguments-slope": 1, + "tailList-cpu-arguments": 41182, + "tailList-memory-arguments": 32, + "trace-cpu-arguments": 212342, + "trace-memory-arguments": 32, + "unBData-cpu-arguments": 31220, + "unBData-memory-arguments": 32, + "unConstrData-cpu-arguments": 32696, + "unConstrData-memory-arguments": 32, + "unIData-cpu-arguments": 43357, + "unIData-memory-arguments": 32, + "unListData-cpu-arguments": 32247, "unListData-memory-arguments": 32, - "sha2_256-cpu-arguments-slope": 29175, - "indexByteString-memory-arguments": 1, - "equalsInteger-memory-arguments": 1, - "remainderInteger-cpu-arguments-model-arguments-slope": 118, - "cekVarCost-exBudgetCPU": 29773, - "lessThanEqualsInteger-cpu-arguments-slope": 1366, + "unMapData-cpu-arguments": 38314, + "unMapData-memory-arguments": 32, + "verifyEd25519Signature-cpu-arguments-intercept": 9462713, + "verifyEd25519Signature-cpu-arguments-slope": 1021, + "verifyEd25519Signature-memory-arguments": 10 + }, + "PlutusScriptV2": { + "addInteger-cpu-arguments-intercept": 205665, + "addInteger-cpu-arguments-slope": 812, "addInteger-memory-arguments-intercept": 1, - "sndPair-cpu-arguments": 150000, - "lessThanInteger-memory-arguments": 1, - "cekLamCost-exBudgetCPU": 29773, - "chooseUnit-cpu-arguments": 150000, - "decodeUtf8-cpu-arguments-slope": 1000, - "fstPair-cpu-arguments": 150000, - "quotientInteger-memory-arguments-minimum": 1, - "lessThanEqualsInteger-memory-arguments": 1, - "chooseUnit-memory-arguments": 32, - "fstPair-memory-arguments": 32, - "quotientInteger-cpu-arguments-constant": 148000, - "mapData-cpu-arguments": 150000, - "unConstrData-cpu-arguments": 150000, - "mkPairData-cpu-arguments": 150000, - "sndPair-memory-arguments": 32, - "decodeUtf8-memory-arguments-slope": 8, - "equalsData-cpu-arguments-intercept": 150000, - "addInteger-cpu-arguments-intercept": 197209, - "modInteger-memory-arguments-intercept": 0, + "addInteger-memory-arguments-slope": 1, + "appendByteString-cpu-arguments-intercept": 1000, + "appendByteString-cpu-arguments-slope": 571, + "appendByteString-memory-arguments-intercept": 0, + "appendByteString-memory-arguments-slope": 1, + "appendString-cpu-arguments-intercept": 1000, + "appendString-cpu-arguments-slope": 24177, + "appendString-memory-arguments-intercept": 4, + "appendString-memory-arguments-slope": 1, + "bData-cpu-arguments": 1000, + "bData-memory-arguments": 32, + "blake2b_256-cpu-arguments-intercept": 117366, + "blake2b_256-cpu-arguments-slope": 10475, + "blake2b_256-memory-arguments": 4, + "cekApplyCost-exBudgetCPU": 23000, + "cekApplyCost-exBudgetMemory": 100, + "cekBuiltinCost-exBudgetCPU": 23000, + "cekBuiltinCost-exBudgetMemory": 100, + "cekConstCost-exBudgetCPU": 23000, + "cekConstCost-exBudgetMemory": 100, + "cekDelayCost-exBudgetCPU": 23000, + "cekDelayCost-exBudgetMemory": 100, + "cekForceCost-exBudgetCPU": 23000, + "cekForceCost-exBudgetMemory": 100, + "cekLamCost-exBudgetCPU": 23000, + "cekLamCost-exBudgetMemory": 100, + "cekStartupCost-exBudgetCPU": 100, "cekStartupCost-exBudgetMemory": 100, - "divideInteger-cpu-arguments-model-arguments-intercept": 425507, - "divideInteger-memory-arguments-intercept": 0, + "cekVarCost-exBudgetCPU": 23000, "cekVarCost-exBudgetMemory": 100, + "chooseData-cpu-arguments": 19537, + "chooseData-memory-arguments": 32, + "chooseList-cpu-arguments": 175354, + "chooseList-memory-arguments": 32, + "chooseUnit-cpu-arguments": 46417, + "chooseUnit-memory-arguments": 4, + "consByteString-cpu-arguments-intercept": 221973, + "consByteString-cpu-arguments-slope": 511, + "consByteString-memory-arguments-intercept": 0, "consByteString-memory-arguments-slope": 1, - "cekForceCost-exBudgetMemory": 100, - "unListData-cpu-arguments": 150000, - "subtractInteger-cpu-arguments-intercept": 197209, - "indexByteString-cpu-arguments": 150000, - "equalsInteger-cpu-arguments-slope": 1326, - "lessThanByteString-memory-arguments": 1, - "blake2b-cpu-arguments-intercept": 2477736, - "encodeUtf8-cpu-arguments-intercept": 150000, - "multiplyInteger-cpu-arguments-slope": 11218, - "tailList-cpu-arguments": 150000, - "appendByteString-cpu-arguments-intercept": 396231, - "equalsString-cpu-arguments-slope": 1000, - "lessThanEqualsByteString-cpu-arguments-slope": 248, - "remainderInteger-cpu-arguments-constant": 148000, - "chooseList-cpu-arguments": 150000, + "constrData-cpu-arguments": 89141, + "constrData-memory-arguments": 32, + "decodeUtf8-cpu-arguments-intercept": 497525, + "decodeUtf8-cpu-arguments-slope": 14068, + "decodeUtf8-memory-arguments-intercept": 4, + "decodeUtf8-memory-arguments-slope": 2, + "divideInteger-cpu-arguments-constant": 196500, + "divideInteger-cpu-arguments-model-arguments-intercept": 453240, + "divideInteger-cpu-arguments-model-arguments-slope": 220, + "divideInteger-memory-arguments-intercept": 0, + "divideInteger-memory-arguments-minimum": 1, + "divideInteger-memory-arguments-slope": 1, + "encodeUtf8-cpu-arguments-intercept": 1000, + "encodeUtf8-cpu-arguments-slope": 28662, + "encodeUtf8-memory-arguments-intercept": 4, + "encodeUtf8-memory-arguments-slope": 2, + "equalsByteString-cpu-arguments-constant": 245000, + "equalsByteString-cpu-arguments-intercept": 216773, + "equalsByteString-cpu-arguments-slope": 62, "equalsByteString-memory-arguments": 1, - "constrData-cpu-arguments": 150000, - "cekApplyCost-exBudgetCPU": 29773, - "equalsData-cpu-arguments-slope": 10000, - "decodeUtf8-memory-arguments-intercept": 0, - "modInteger-memory-arguments-slope": 1, - "addInteger-cpu-arguments-slope": 0, - "appendString-cpu-arguments-intercept": 150000, - "quotientInteger-cpu-arguments-model-arguments-slope": 118, - "unMapData-memory-arguments": 32, - "cekApplyCost-exBudgetMemory": 100, - "quotientInteger-memory-arguments-slope": 1, - "mkNilPairData-memory-arguments": 32, + "equalsData-cpu-arguments-intercept": 1060367, + "equalsData-cpu-arguments-slope": 12586, + "equalsData-memory-arguments": 1, + "equalsInteger-cpu-arguments-intercept": 208512, + "equalsInteger-cpu-arguments-slope": 421, + "equalsInteger-memory-arguments": 1, + "equalsString-cpu-arguments-constant": 187000, + "equalsString-cpu-arguments-intercept": 1000, + "equalsString-cpu-arguments-slope": 52998, + "equalsString-memory-arguments": 1, + "fstPair-cpu-arguments": 80436, + "fstPair-memory-arguments": 32, + "headList-cpu-arguments": 43249, + "headList-memory-arguments": 32, + "iData-cpu-arguments": 1000, + "iData-memory-arguments": 32, + "ifThenElse-cpu-arguments": 80556, "ifThenElse-memory-arguments": 1, - "equalsByteString-cpu-arguments-slope": 247, - "sliceByteString-memory-arguments-slope": 1, - "sha3_256-memory-arguments": 4, - "mkCons-memory-arguments": 32, - "verifySignature-cpu-arguments-intercept": 3345831, - "cekBuiltinCost-exBudgetMemory": 100, - "remainderInteger-memory-arguments-intercept": 0, + "indexByteString-cpu-arguments": 57667, + "indexByteString-memory-arguments": 4, + "lengthOfByteString-cpu-arguments": 1000, + "lengthOfByteString-memory-arguments": 10, + "lessThanByteString-cpu-arguments-intercept": 197145, + "lessThanByteString-cpu-arguments-slope": 156, + "lessThanByteString-memory-arguments": 1, + "lessThanEqualsByteString-cpu-arguments-intercept": 197145, + "lessThanEqualsByteString-cpu-arguments-slope": 156, "lessThanEqualsByteString-memory-arguments": 1, - "mkNilData-cpu-arguments": 150000, - "equalsString-memory-arguments": 1, - "chooseData-cpu-arguments": 150000, - "remainderInteger-cpu-arguments-model-arguments-intercept": 425507, - "tailList-memory-arguments": 32, - "sha2_256-cpu-arguments-intercept": 2477736, + "lessThanEqualsInteger-cpu-arguments-intercept": 204924, + "lessThanEqualsInteger-cpu-arguments-slope": 473, + "lessThanEqualsInteger-memory-arguments": 1, + "lessThanInteger-cpu-arguments-intercept": 208896, + "lessThanInteger-cpu-arguments-slope": 511, + "lessThanInteger-memory-arguments": 1, + "listData-cpu-arguments": 52467, + "listData-memory-arguments": 32, + "mapData-cpu-arguments": 64832, + "mapData-memory-arguments": 32, + "mkCons-cpu-arguments": 65493, + "mkCons-memory-arguments": 32, + "mkNilData-cpu-arguments": 22558, + "mkNilData-memory-arguments": 32, + "mkNilPairData-cpu-arguments": 16563, + "mkNilPairData-memory-arguments": 32, + "mkPairData-cpu-arguments": 76511, + "mkPairData-memory-arguments": 32, + "modInteger-cpu-arguments-constant": 196500, + "modInteger-cpu-arguments-model-arguments-intercept": 453240, + "modInteger-cpu-arguments-model-arguments-slope": 220, + "modInteger-memory-arguments-intercept": 0, + "modInteger-memory-arguments-minimum": 1, + "modInteger-memory-arguments-slope": 1, + "multiplyInteger-cpu-arguments-intercept": 69522, + "multiplyInteger-cpu-arguments-slope": 11687, + "multiplyInteger-memory-arguments-intercept": 0, "multiplyInteger-memory-arguments-slope": 1, - "iData-memory-arguments": 32, - "divideInteger-cpu-arguments-constant": 148000, - "cekDelayCost-exBudgetCPU": 29773, - "encodeUtf8-memory-arguments-slope": 8, - "subtractInteger-memory-arguments-intercept": 1, + "nullList-cpu-arguments": 60091, "nullList-memory-arguments": 32, - "lessThanByteString-cpu-arguments-intercept": 103599, - "appendByteString-memory-arguments-slope": 1, - "blake2b-memory-arguments": 4, - "unBData-memory-arguments": 32, - "cekConstCost-exBudgetCPU": 29773, - "consByteString-cpu-arguments-slope": 1000, - "trace-memory-arguments": 32, + "quotientInteger-cpu-arguments-constant": 196500, + "quotientInteger-cpu-arguments-model-arguments-intercept": 453240, + "quotientInteger-cpu-arguments-model-arguments-slope": 220, "quotientInteger-memory-arguments-intercept": 0, - "mapData-memory-arguments": 32, - "verifySignature-cpu-arguments-slope": 1, - "quotientInteger-cpu-arguments-model-arguments-intercept": 425507, - "modInteger-cpu-arguments-constant": 148000, - "appendString-cpu-arguments-slope": 1000, + "quotientInteger-memory-arguments-minimum": 1, + "quotientInteger-memory-arguments-slope": 1, + "remainderInteger-cpu-arguments-constant": 196500, + "remainderInteger-cpu-arguments-model-arguments-intercept": 453240, + "remainderInteger-cpu-arguments-model-arguments-slope": 220, + "remainderInteger-memory-arguments-intercept": 0, + "remainderInteger-memory-arguments-minimum": 1, + "remainderInteger-memory-arguments-slope": 1, + "serialiseData-cpu-arguments-intercept": 1159724, + "serialiseData-cpu-arguments-slope": 392670, + "serialiseData-memory-arguments-intercept": 0, + "serialiseData-memory-arguments-slope": 2, + "sha2_256-cpu-arguments-intercept": 806990, + "sha2_256-cpu-arguments-slope": 30482, + "sha2_256-memory-arguments": 4, + "sha3_256-cpu-arguments-intercept": 1927926, + "sha3_256-cpu-arguments-slope": 82523, + "sha3_256-memory-arguments": 4, + "sliceByteString-cpu-arguments-intercept": 265318, + "sliceByteString-cpu-arguments-slope": 0, + "sliceByteString-memory-arguments-intercept": 4, + "sliceByteString-memory-arguments-slope": 0, + "sndPair-cpu-arguments": 85931, + "sndPair-memory-arguments": 32, + "subtractInteger-cpu-arguments-intercept": 205665, + "subtractInteger-cpu-arguments-slope": 812, + "subtractInteger-memory-arguments-intercept": 1, + "subtractInteger-memory-arguments-slope": 1, + "tailList-cpu-arguments": 41182, + "tailList-memory-arguments": 32, + "trace-cpu-arguments": 212342, + "trace-memory-arguments": 32, + "unBData-cpu-arguments": 31220, + "unBData-memory-arguments": 32, + "unConstrData-cpu-arguments": 32696, "unConstrData-memory-arguments": 32, - "mkPairData-memory-arguments": 32, - "equalsByteString-cpu-arguments-constant": 150000, - "equalsByteString-cpu-arguments-intercept": 112536, - "sliceByteString-memory-arguments-intercept": 0, - "lessThanInteger-cpu-arguments-slope": 497, - "verifySignature-memory-arguments": 1, - "cekLamCost-exBudgetMemory": 100, - "sliceByteString-cpu-arguments-intercept": 150000, - "modInteger-cpu-arguments-model-arguments-intercept": 425507, - "modInteger-memory-arguments-minimum": 1, - "appendString-memory-arguments-slope": 1, - "sha3_256-cpu-arguments-intercept": 0 + "unIData-cpu-arguments": 43357, + "unIData-memory-arguments": 32, + "unListData-cpu-arguments": 32247, + "unListData-memory-arguments": 32, + "unMapData-cpu-arguments": 38314, + "unMapData-memory-arguments": 32, + "verifyEcdsaSecp256k1Signature-cpu-arguments": 35892428, + "verifyEcdsaSecp256k1Signature-memory-arguments": 10, + "verifyEd25519Signature-cpu-arguments-intercept": 9462713, + "verifyEd25519Signature-cpu-arguments-slope": 1021, + "verifyEd25519Signature-memory-arguments": 10, + "verifySchnorrSecp256k1Signature-cpu-arguments-intercept": 38887044, + "verifySchnorrSecp256k1Signature-cpu-arguments-slope": 32947, + "verifySchnorrSecp256k1Signature-memory-arguments": 10 } }, + "decentralization": null, + "executionUnitPrices": { + "priceMemory": 5.77e-2, + "priceSteps": 7.21e-5 + }, + "extraPraosEntropy": null, + "maxBlockBodySize": 65536, + "maxBlockExecutionUnits": { + "memory": 50000000, + "steps": 40000000000 + }, + "maxBlockHeaderSize": 1100, + "maxCollateralInputs": 3, + "maxTxExecutionUnits": { + "memory": 10000000, + "steps": 10000000000 + }, + "maxTxSize": 16384, + "maxValueSize": 5000, + "minPoolCost": 0, + "minUTxOValue": null, + "monetaryExpansion": 1.78650067e-3, + "poolPledgeInfluence": 0.1, + "poolRetireMaxEpoch": 18, "protocolVersion": { - "minor": 0, - "major": 5 + "major": 7, + "minor": 0 }, + "stakeAddressDeposit": 400000, + "stakePoolDeposit": 500000000, + "stakePoolTargetNum": 50, + "treasuryCut": 0.1, "txFeeFixed": 155381, - "stakeAddressDeposit": 0, - "monetaryExpansion": 0.1, - "poolPledgeInfluence": 0, - "executionUnitPrices": { - "priceSteps": 7.21e-5, - "priceMemory": 5.77e-2 - } + "txFeePerByte": 44, + "utxoCostPerWord": 34480 } \ No newline at end of file diff --git a/flake.lock b/flake.lock index d8ccfacb..8113866f 100644 --- a/flake.lock +++ b/flake.lock @@ -87,34 +87,34 @@ "cardano-addresses": { "flake": false, "locked": { - "lastModified": 1646738686, - "narHash": "sha256-WeDcoZ2tKT9OJiVNm4bbxjcf0ybnC+/iTH8val+o9Es=", + "lastModified": 1660105670, + "narHash": "sha256-91F9+ckA3lBCE4dAVLDnMSpwRLa7zRUEEBYEHv0sOYk=", "owner": "input-output-hk", "repo": "cardano-addresses", - "rev": "8bf98905b903455196495e231b23613ad2264cb0", + "rev": "b7273a5d3c21f1a003595ebf1e1f79c28cd72513", "type": "github" }, "original": { "owner": "input-output-hk", "repo": "cardano-addresses", - "rev": "8bf98905b903455196495e231b23613ad2264cb0", + "rev": "b7273a5d3c21f1a003595ebf1e1f79c28cd72513", "type": "github" } }, "cardano-base": { "flake": false, "locked": { - "lastModified": 1635841753, - "narHash": "sha256-OXKsJ1UTj5kJ9xaThM54ZmxFAiFINTPKd4JQa4dPmEU=", + "lastModified": 1654537609, + "narHash": "sha256-4b0keLjRaVSdEwfBXB1iT3QPlsutdxSltGfBufT4Clw=", "owner": "input-output-hk", "repo": "cardano-base", - "rev": "41545ba3ac6b3095966316a99883d678b5ab8da8", + "rev": "0f3a867493059e650cda69e20a5cbf1ace289a57", "type": "github" }, "original": { "owner": "input-output-hk", "repo": "cardano-base", - "rev": "41545ba3ac6b3095966316a99883d678b5ab8da8", + "rev": "0f3a867493059e650cda69e20a5cbf1ace289a57", "type": "github" } }, @@ -155,34 +155,34 @@ "cardano-ledger": { "flake": false, "locked": { - "lastModified": 1639498285, - "narHash": "sha256-lRNfkGMHnpPO0T19FZY5BnuRkr0zTRZIkxZVgHH0fys=", + "lastModified": 1659038626, + "narHash": "sha256-zTQbMOGPD1Oodv6VUsfF6NUiXkbN8SWI98W3Atv4wbI=", "owner": "input-output-hk", "repo": "cardano-ledger", - "rev": "1a9ec4ae9e0b09d54e49b2a40c4ead37edadcce5", + "rev": "c7c63dabdb215ebdaed8b63274965966f2bf408f", "type": "github" }, "original": { "owner": "input-output-hk", "repo": "cardano-ledger", - "rev": "1a9ec4ae9e0b09d54e49b2a40c4ead37edadcce5", + "rev": "c7c63dabdb215ebdaed8b63274965966f2bf408f", "type": "github" } }, "cardano-node": { "flake": false, "locked": { - "lastModified": 1646407906, - "narHash": "sha256-e4k1vCsZqUB/I3uPRDIKP9pZ81E/zosJn8kXySAfBcI=", + "lastModified": 1659625017, + "narHash": "sha256-4IrheFeoWfvkZQndEk4fGUkOiOjcVhcyXZ6IqmvkDgg=", "owner": "input-output-hk", "repo": "cardano-node", - "rev": "73f9a746362695dc2cb63ba757fbcabb81733d23", + "rev": "950c4e222086fed5ca53564e642434ce9307b0b9", "type": "github" }, "original": { "owner": "input-output-hk", + "ref": "1.35.3", "repo": "cardano-node", - "rev": "73f9a746362695dc2cb63ba757fbcabb81733d23", "type": "github" } }, @@ -222,17 +222,17 @@ "cardano-wallet": { "flake": false, "locked": { - "lastModified": 1646775085, - "narHash": "sha256-zqKpxHkhZCGPgDQptGSxxM9+GhKJSVWFyltPsgPQ3B8=", + "lastModified": 1660141505, + "narHash": "sha256-3Rnj/g3KLzOW5YSieqsUa9IF1Td22Eskk5KuVsOFgEQ=", "owner": "input-output-hk", "repo": "cardano-wallet", - "rev": "769d3f8e5543f784222c6b5d0ba3ea6c3ccdd7b0", + "rev": "18a931648550246695c790578d4a55ee2f10463e", "type": "github" }, "original": { "owner": "input-output-hk", "repo": "cardano-wallet", - "rev": "769d3f8e5543f784222c6b5d0ba3ea6c3ccdd7b0", + "rev": "18a931648550246695c790578d4a55ee2f10463e", "type": "github" } }, @@ -253,6 +253,23 @@ "type": "github" } }, + "ekg-json": { + "flake": false, + "locked": { + "lastModified": 1642583945, + "narHash": "sha256-VT8Ur585TCn03P2TVi6t92v2Z6tl8vKijICjse6ocv8=", + "owner": "vshabanov", + "repo": "ekg-json", + "rev": "00ebe7211c981686e65730b7144fbf5350462608", + "type": "github" + }, + "original": { + "owner": "vshabanov", + "repo": "ekg-json", + "rev": "00ebe7211c981686e65730b7144fbf5350462608", + "type": "github" + } + }, "flake-compat": { "flake": false, "locked": { @@ -289,13 +306,13 @@ "locked": { "lastModified": 1628771504, "narHash": "sha256-lRFND+ZnZvAph6ZYkr9wl9VAx41pb3uSFP8Wc7idP9M=", - "owner": "input-output-hk", + "owner": "Quid2", "repo": "flat", "rev": "ee59880f47ab835dbd73bea0847dab7869fc20d8", "type": "github" }, "original": { - "owner": "input-output-hk", + "owner": "Quid2", "repo": "flat", "rev": "ee59880f47ab835dbd73bea0847dab7869fc20d8", "type": "github" @@ -338,11 +355,11 @@ "hackage": { "flake": false, "locked": { - "lastModified": 1652663624, - "narHash": "sha256-WeZYALZ6wjXJaMi0ZiSLq5A/ybvES8vN3zPozUgzkFs=", + "lastModified": 1653441966, + "narHash": "sha256-aJFK0wDzoOrtb7ucZzKh5J+S2pThpwNCofl74s1olXU=", "owner": "input-output-hk", "repo": "hackage.nix", - "rev": "70c6780e617190a1ecc26bd004ece9ea67dcc260", + "rev": "f7fe6ef8de52c43a9efa6fd4ac4902e5957dc573", "type": "github" }, "original": { @@ -376,11 +393,11 @@ "stackage": "stackage" }, "locked": { - "lastModified": 1652698457, - "narHash": "sha256-o9UvhU9QwdzXTFOnRB+MTQ0+fP5DblInxHoXqN6DplA=", + "lastModified": 1653486569, + "narHash": "sha256-342b0LPX6kaBuEX8KZV40FwCCFre1lCtjdTQIDEt9kw=", "owner": "mlabs-haskell", "repo": "haskell.nix", - "rev": "269936645c92aa74b8b0695e96a1c92fd108f8aa", + "rev": "220f8a9cd166e726aea62843bdafa7ecded3375c", "type": "github" }, "original": { @@ -389,6 +406,23 @@ "type": "github" } }, + "hedgehog-extras": { + "flake": false, + "locked": { + "lastModified": 1656051321, + "narHash": "sha256-6KQFEzb9g2a0soVvwLKESEbA+a8ygpROcMr6bkatROE=", + "owner": "input-output-hk", + "repo": "hedgehog-extras", + "rev": "714ee03a5a786a05fc57ac5d2f1c2edce4660d85", + "type": "github" + }, + "original": { + "owner": "input-output-hk", + "repo": "hedgehog-extras", + "rev": "714ee03a5a786a05fc57ac5d2f1c2edce4660d85", + "type": "github" + } + }, "hpc-coveralls": { "flake": false, "locked": { @@ -405,6 +439,23 @@ "type": "github" } }, + "hw-aeson": { + "flake": false, + "locked": { + "lastModified": 1660113261, + "narHash": "sha256-v0SyVxeVBTtW1tuej4P+Kf4roO/rr2tBI7RthTlInbc=", + "owner": "haskell-works", + "repo": "hw-aeson", + "rev": "b5ef03a7d7443fcd6217ed88c335f0c411a05408", + "type": "github" + }, + "original": { + "owner": "haskell-works", + "repo": "hw-aeson", + "rev": "b5ef03a7d7443fcd6217ed88c335f0c411a05408", + "type": "github" + } + }, "hydra": { "inputs": { "nix": "nix", @@ -428,31 +479,65 @@ "type": "indirect" } }, + "hysterical-screams": { + "flake": false, + "locked": { + "lastModified": 1654007733, + "narHash": "sha256-d4N3rUzg45BUs5Lx/kK7vXYsLMNoO15dlzo7t8lGIXA=", + "owner": "raduom", + "repo": "hysterical-screams", + "rev": "4c523469e9efd3f0d10d17da3304923b7b0e0674", + "type": "github" + }, + "original": { + "owner": "raduom", + "repo": "hysterical-screams", + "rev": "4c523469e9efd3f0d10d17da3304923b7b0e0674", + "type": "github" + } + }, + "io-sim": { + "flake": false, + "locked": { + "lastModified": 1654253725, + "narHash": "sha256-TviSvCBEYtlKEo9qJmE8pCE25nMjDi8HeIAFniunaM8=", + "owner": "input-output-hk", + "repo": "io-sim", + "rev": "57e888b1894829056cb00b7b5785fdf6a74c3271", + "type": "github" + }, + "original": { + "owner": "input-output-hk", + "repo": "io-sim", + "rev": "57e888b1894829056cb00b7b5785fdf6a74c3271", + "type": "github" + } + }, "iohk-monitoring-framework": { "flake": false, "locked": { - "lastModified": 1618904084, - "narHash": "sha256-v0L0pcyO2rP7/HCoGwFgHEMUOPBGwaRV0r+/JOhtKAk=", + "lastModified": 1653619339, + "narHash": "sha256-0ia5UflYEmBYepj2gkJy9msknklI0UPtUavMEGwk3Wg=", "owner": "input-output-hk", "repo": "iohk-monitoring-framework", - "rev": "808724ff8a19a33d0ed06f9ef59fbd900b08553c", + "rev": "066f7002aac5a0efc20e49643fea45454f226caa", "type": "github" }, "original": { "owner": "input-output-hk", "repo": "iohk-monitoring-framework", - "rev": "808724ff8a19a33d0ed06f9ef59fbd900b08553c", + "rev": "066f7002aac5a0efc20e49643fea45454f226caa", "type": "github" } }, "iohk-nix": { "flake": false, "locked": { - "lastModified": 1649070135, - "narHash": "sha256-UFKqcOSdPWk3TYUCPHF22p1zf7aXQpCmmgf7UMg7fWA=", + "lastModified": 1658222743, + "narHash": "sha256-yFH01psqx30y5Ws4dBElLkxYpIxxqZx4G+jCVhsXpnA=", "owner": "input-output-hk", "repo": "iohk-nix", - "rev": "cecab9c71d1064f05f1615eead56ac0b9196bc20", + "rev": "9a604d01bd4420ab7f396f14d1947fbe2ce7db8b", "type": "github" }, "original": { @@ -645,51 +730,51 @@ "ouroboros-network": { "flake": false, "locked": { - "lastModified": 1643202846, - "narHash": "sha256-Cy29MHrYTkN7s3Vvog5/pOzbo7jiqTeDz6OmrNvag6w=", + "lastModified": 1658339771, + "narHash": "sha256-3ElbHM1B5u1QD0aes1KbaX2FxKJzU05H0OzJ36em1Bg=", "owner": "input-output-hk", "repo": "ouroboros-network", - "rev": "4fac197b6f0d2ff60dc3486c593b68dc00969fbf", + "rev": "cb9eba406ceb2df338d8384b35c8addfe2067201", "type": "github" }, "original": { "owner": "input-output-hk", "repo": "ouroboros-network", - "rev": "4fac197b6f0d2ff60dc3486c593b68dc00969fbf", + "rev": "cb9eba406ceb2df338d8384b35c8addfe2067201", "type": "github" } }, "plutus": { "flake": false, "locked": { - "lastModified": 1646406347, - "narHash": "sha256-F3qhDJYisd3IapOskQMMccqK+iyKS3rB6vlzW8cEdA0=", - "owner": "mlabs-haskell", + "lastModified": 1659046871, + "narHash": "sha256-coD/Kpl7tutwXb6ukQCH5XojBjquYkW7ob0BWZtdpok=", + "owner": "input-output-hk", "repo": "plutus", - "rev": "1a3c3a761cf048371c52a34b004f8b3fcf0dab43", + "rev": "a56c96598b4b25c9e28215214d25189331087244", "type": "github" }, "original": { - "owner": "mlabs-haskell", + "owner": "input-output-hk", "repo": "plutus", - "rev": "1a3c3a761cf048371c52a34b004f8b3fcf0dab43", + "rev": "a56c96598b4b25c9e28215214d25189331087244", "type": "github" } }, "plutus-apps": { "flake": false, "locked": { - "lastModified": 1647352219, - "narHash": "sha256-quJeOzNGT1Ath7zjc1VHdEiJwZaSSXyn0sdVZwVofwI=", + "lastModified": 1661246964, + "narHash": "sha256-NuSwD6mjUEgBay2sIKRo6DUBualMQUDKfHQlsbYzKuk=", "owner": "mlabs-haskell", "repo": "plutus-apps", - "rev": "82c0725c4d05398ae76d71927cc60aa23db1a11d", + "rev": "31bfd4c7fff5158c9f2618b76b68dbbae410221d", "type": "github" }, "original": { "owner": "mlabs-haskell", "repo": "plutus-apps", - "rev": "82c0725c4d05398ae76d71927cc60aa23db1a11d", + "rev": "31bfd4c7fff5158c9f2618b76b68dbbae410221d", "type": "github" } }, @@ -710,6 +795,23 @@ "type": "github" } }, + "quickcheck-dynamic": { + "flake": false, + "locked": { + "lastModified": 1656927450, + "narHash": "sha256-TioJQASNrQX6B3n2Cv43X2olyT67//CFQqcpvNW7N60=", + "owner": "input-output-hk", + "repo": "quickcheck-dynamic", + "rev": "c272906361471d684440f76c297e29ab760f6a1e", + "type": "github" + }, + "original": { + "owner": "input-output-hk", + "repo": "quickcheck-dynamic", + "rev": "c272906361471d684440f76c297e29ab760f6a1e", + "type": "github" + } + }, "root": { "inputs": { "Win32-network": "Win32-network", @@ -722,10 +824,15 @@ "cardano-prelude": "cardano-prelude", "cardano-wallet": "cardano-wallet", "ekg-forward": "ekg-forward", + "ekg-json": "ekg-json", "flake-compat": "flake-compat", "flat": "flat", "goblins": "goblins", "haskell-nix": "haskell-nix", + "hedgehog-extras": "hedgehog-extras", + "hw-aeson": "hw-aeson", + "hysterical-screams": "hysterical-screams", + "io-sim": "io-sim", "iohk-monitoring-framework": "iohk-monitoring-framework", "iohk-nix": "iohk-nix", "nixpkgs": [ @@ -737,7 +844,9 @@ "plutus": "plutus", "plutus-apps": "plutus-apps", "purescript-bridge": "purescript-bridge", - "servant-purescript": "servant-purescript" + "quickcheck-dynamic": "quickcheck-dynamic", + "servant-purescript": "servant-purescript", + "typed-protocols": "typed-protocols" } }, "servant-purescript": { @@ -760,11 +869,11 @@ "stackage": { "flake": false, "locked": { - "lastModified": 1652577319, - "narHash": "sha256-zZxCo7vIdyjZueJD3VoR7YImsS54dRhqqVRcsLqUBP0=", + "lastModified": 1653355076, + "narHash": "sha256-mQdOgAyFkLUJBPrVDZmZQ2JRtgHKOQkil//SDdcjP1U=", "owner": "input-output-hk", "repo": "stackage.nix", - "rev": "49dfbc9cbf38cbf8180a432fcd6d390326c74fba", + "rev": "71b16ca68d6acd639121db43238896357fe53f54", "type": "github" }, "original": { @@ -772,6 +881,23 @@ "repo": "stackage.nix", "type": "github" } + }, + "typed-protocols": { + "flake": false, + "locked": { + "lastModified": 1653046676, + "narHash": "sha256-5Wof5yTKb12EPY6B8LfapX18xNZZpF+rvhnQ88U6KdM=", + "owner": "input-output-hk", + "repo": "typed-protocols", + "rev": "181601bc3d9e9d21a671ce01e0b481348b3ca104", + "type": "github" + }, + "original": { + "owner": "input-output-hk", + "repo": "typed-protocols", + "rev": "181601bc3d9e9d21a671ce01e0b481348b3ca104", + "type": "github" + } } }, "root": "root", diff --git a/flake.nix b/flake.nix index 8017cc67..3b9e0cb8 100644 --- a/flake.nix +++ b/flake.nix @@ -17,12 +17,12 @@ # all inputs below here are for pinning with haskell.nix cardano-addresses = { url = - "github:input-output-hk/cardano-addresses/8bf98905b903455196495e231b23613ad2264cb0"; + "github:input-output-hk/cardano-addresses/b7273a5d3c21f1a003595ebf1e1f79c28cd72513"; flake = false; }; cardano-base = { url = - "github:input-output-hk/cardano-base/41545ba3ac6b3095966316a99883d678b5ab8da8"; + "github:input-output-hk/cardano-base/0f3a867493059e650cda69e20a5cbf1ace289a57"; flake = false; }; cardano-config = { @@ -37,13 +37,13 @@ }; cardano-ledger = { url = - "github:input-output-hk/cardano-ledger/1a9ec4ae9e0b09d54e49b2a40c4ead37edadcce5"; + "github:input-output-hk/cardano-ledger/c7c63dabdb215ebdaed8b63274965966f2bf408f"; flake = false; }; cardano-node = { url = - "github:input-output-hk/cardano-node/73f9a746362695dc2cb63ba757fbcabb81733d23"; - flake = false; + "github:input-output-hk/cardano-node?ref=1.35.3"; + flake = false; # we need it to be available in shell }; cardano-prelude = { url = @@ -51,19 +51,21 @@ flake = false; }; cardano-wallet = { - url = - "github:input-output-hk/cardano-wallet/769d3f8e5543f784222c6b5d0ba3ea6c3ccdd7b0"; + url = "github:input-output-hk/cardano-wallet/18a931648550246695c790578d4a55ee2f10463e"; flake = false; }; - # We don't actually need this. Removing this might make caching worse? - flat = { - url = - "github:input-output-hk/flat/ee59880f47ab835dbd73bea0847dab7869fc20d8"; + ekg-forward = { + url = "github:input-output-hk/ekg-forward/297cd9db5074339a2fb2e5ae7d0780debb670c63"; flake = false; }; - ekg-forward = { + ekg-json = { + url = "github:vshabanov/ekg-json/00ebe7211c981686e65730b7144fbf5350462608"; + flake = false; + }; + # We don't actually need this. Removing this might make caching worse? + flat = { url = - "github:input-output-hk/ekg-forward/297cd9db5074339a2fb2e5ae7d0780debb670c63"; + "github:Quid2/flat/ee59880f47ab835dbd73bea0847dab7869fc20d8"; flake = false; }; goblins = { @@ -71,9 +73,26 @@ "github:input-output-hk/goblins/cde90a2b27f79187ca8310b6549331e59595e7ba"; flake = false; }; + hedgehog-extras = { + url = "github:input-output-hk/hedgehog-extras/714ee03a5a786a05fc57ac5d2f1c2edce4660d85"; + flake = false; + }; + hysterical-screams = { + url = "github:raduom/hysterical-screams/4c523469e9efd3f0d10d17da3304923b7b0e0674"; + flake = false; + }; + hw-aeson = { + url = "github:haskell-works/hw-aeson/b5ef03a7d7443fcd6217ed88c335f0c411a05408"; + flake = false; + }; iohk-monitoring-framework = { url = - "github:input-output-hk/iohk-monitoring-framework/808724ff8a19a33d0ed06f9ef59fbd900b08553c"; + "github:input-output-hk/iohk-monitoring-framework/066f7002aac5a0efc20e49643fea45454f226caa"; + flake = false; + }; + io-sim = { + url = + "github:input-output-hk/io-sim/57e888b1894829056cb00b7b5785fdf6a74c3271"; flake = false; }; optparse-applicative = { @@ -83,20 +102,17 @@ }; ouroboros-network = { url = - "github:input-output-hk/ouroboros-network/4fac197b6f0d2ff60dc3486c593b68dc00969fbf"; + "github:input-output-hk/ouroboros-network/cb9eba406ceb2df338d8384b35c8addfe2067201"; flake = false; }; - # Patched plutus for metadata support. We need this until `plutus-apps` will update `plutus`, - # rewrite of `plutus-ledger-constraints`, and possibly some bpi adjustments afterwards. - # tldr: Dependency hell plutus = { url = - "github:mlabs-haskell/plutus/1a3c3a761cf048371c52a34b004f8b3fcf0dab43"; + "github:input-output-hk/plutus/a56c96598b4b25c9e28215214d25189331087244"; flake = false; }; plutus-apps = { url = - "github:mlabs-haskell/plutus-apps/82c0725c4d05398ae76d71927cc60aa23db1a11d"; + "github:mlabs-haskell/plutus-apps/31bfd4c7fff5158c9f2618b76b68dbbae410221d"; flake = false; }; purescript-bridge = { @@ -104,11 +120,20 @@ "github:input-output-hk/purescript-bridge/47a1f11825a0f9445e0f98792f79172efef66c00"; flake = false; }; + quickcheck-dynamic = { + url = "github:input-output-hk/quickcheck-dynamic/c272906361471d684440f76c297e29ab760f6a1e"; + flake = false; + }; servant-purescript = { url = "github:input-output-hk/servant-purescript/44e7cacf109f84984cd99cd3faf185d161826963"; flake = false; }; + typed-protocols = { + url = + "github:input-output-hk/typed-protocols/181601bc3d9e9d21a671ce01e0b481348b3ca104"; + flake = false; + }; Win32-network = { url = "github:input-output-hk/Win32-network/3825d3abf75f83f406c1f7161883c438dac7277d"; @@ -131,9 +156,8 @@ nixpkgsFor' = system: import nixpkgs { inherit system; }; cabalProjectLocal = '' - allow-newer: size-based:template-haskell - - constraints: hedgehog >= 1.0.4, hedgehog < 1.1 + allow-newer: *:aeson, size-based:template-haskell + constraints: aeson >= 2, hedgehog >= 1.1 ''; haskellModules = [ @@ -143,6 +167,7 @@ marlowe.flags.defer-plugin-errors = true; plutus-use-cases.flags.defer-plugin-errors = true; plutus-ledger.flags.defer-plugin-errors = true; + plutus-script-utils.flags.defer-plugin-errors = true; plutus-contract.flags.defer-plugin-errors = true; cardano-crypto-praos.components.library.pkgconfig = pkgs.lib.mkForce [ [ pkgs.libsodium-vrf ] ]; cardano-crypto-class.components.library.pkgconfig = pkgs.lib.mkForce [ [ pkgs.libsodium-vrf ] ]; @@ -185,6 +210,8 @@ src = inputs.cardano-ledger; subdirs = [ "eras/alonzo/impl" + "eras/alonzo/test-suite" + "eras/babbage/impl" "eras/byron/chain/executable-spec" "eras/byron/crypto" "eras/byron/crypto/test" @@ -192,13 +219,14 @@ "eras/byron/ledger/impl" "eras/byron/ledger/impl/test" "eras/shelley/impl" - "eras/shelley-ma/impl" "eras/shelley/test-suite" + "eras/shelley-ma/impl" + "eras/shelley-ma/test-suite" "libs/cardano-data" "libs/cardano-ledger-core" "libs/cardano-ledger-pretty" "libs/cardano-protocol-tpraos" - "libs/compact-map" + "libs/vector-map" "libs/non-integral" "libs/set-algebra" "libs/small-steps" @@ -209,12 +237,14 @@ src = inputs.cardano-node; subdirs = [ "cardano-api" - "cardano-node" "cardano-cli" "cardano-git-rev" - "trace-resources" - "trace-forward" + "cardano-node" + "cardano-submit-api" + "cardano-testnet" "trace-dispatcher" + "trace-forward" + "trace-resources" ]; } { @@ -244,6 +274,10 @@ src = inputs.ekg-forward; subdirs = [ "." ]; } + { + src = inputs.ekg-json; + subdirs = [ "." ]; + } { src = inputs.flat; subdirs = [ "." ]; @@ -252,17 +286,36 @@ src = inputs.goblins; subdirs = [ "." ]; } + { + src = inputs.hedgehog-extras; + subdirs = [ "." ]; + } + { + src = inputs.hysterical-screams; + subdirs = [ "." ]; + } + { + src = inputs.hw-aeson; + subdirs = [ "." ]; + } { src = inputs.iohk-monitoring-framework; subdirs = [ + "contra-tracer" "iohk-monitoring" "tracer-transformers" - "contra-tracer" - "plugins/backend-aggregation" "plugins/backend-ekg" + "plugins/backend-aggregation" "plugins/backend-monitoring" "plugins/backend-trace-forwarder" - "plugins/scribe-systemd" + ]; + } + { + src = inputs.io-sim; + subdirs = [ + "io-classes" + "io-sim" + "strict-stm" ]; } { @@ -272,9 +325,6 @@ { src = inputs.ouroboros-network; subdirs = [ - "io-classes" - "io-sim" - "strict-stm" "monoidal-synchronisation" "network-mux" "ntp-client" @@ -286,9 +336,6 @@ "ouroboros-network" "ouroboros-network-framework" "ouroboros-network-testing" - "typed-protocols" - "typed-protocols-cborg" - "typed-protocols-examples" ]; } { @@ -311,13 +358,17 @@ "playground-common" "plutus-chain-index" "plutus-chain-index-core" + "plutus-hysterical-screams" "plutus-contract" + "plutus-contract-certification" "plutus-ledger" "plutus-ledger-constraints" "plutus-pab" "plutus-playground-server" + "plutus-script-utils" + "plutus-streaming" + "plutus-tx-constraints" "plutus-use-cases" - "quickcheck-dynamic" "web-ghc" ]; } @@ -325,10 +376,22 @@ src = inputs.purescript-bridge; subdirs = [ "." ]; } + { + src = inputs.quickcheck-dynamic; + subdirs = [ "." ]; + } { src = inputs.servant-purescript; subdirs = [ "." ]; } + { + src = inputs.typed-protocols; + subdirs = [ + "typed-protocols" + "typed-protocols-cborg" + "typed-protocols-examples" + ]; + } { src = inputs.Win32-network; subdirs = [ "." ]; diff --git a/src/BotPlutusInterface/Balance.hs b/src/BotPlutusInterface/Balance.hs index fc215358..d2af7882 100644 --- a/src/BotPlutusInterface/Balance.hs +++ b/src/BotPlutusInterface/Balance.hs @@ -13,14 +13,17 @@ module BotPlutusInterface.Balance ( import BotPlutusInterface.BodyBuilder qualified as BodyBuilder import BotPlutusInterface.CardanoCLI qualified as CardanoCLI +import BotPlutusInterface.CardanoNode.Effects (NodeQuery (UtxosAt)) import BotPlutusInterface.CoinSelection (selectTxIns) import BotPlutusInterface.Collateral (removeCollateralFromMap) import BotPlutusInterface.Effects ( PABEffect, createDirectoryIfMissingCLI, getInMemCollateral, + minUtxo, posixTimeRangeToContainedSlotRange, printBpiLog, + queryNode, ) import BotPlutusInterface.Files (DummyPrivKey, unDummyPrivateKey) import BotPlutusInterface.Files qualified as Files @@ -33,15 +36,15 @@ import BotPlutusInterface.Types ( ) import Cardano.Api (ExecutionUnitPrices (ExecutionUnitPrices)) import Cardano.Api.Shelley (ProtocolParameters (protocolParamPrices)) -import Control.Monad (foldM, void, zipWithM) +import Control.Lens (folded, to, (&), (.~), (^.), (^..)) +import Control.Monad (foldM, void) import Control.Monad.Freer (Eff, Member) import Control.Monad.Trans.Class (lift) -import Control.Monad.Trans.Either (EitherT, hoistEither, newEitherT, runEitherT) +import Control.Monad.Trans.Either (EitherT, firstEitherT, hoistEither, newEitherT, runEitherT) import Control.Monad.Trans.Except (throwE) import Data.Bifunctor (bimap) import Data.Coerce (coerce) import Data.Kind (Type) -import Data.List ((\\)) import Data.List qualified as List import Data.Map (Map) import Data.Map qualified as Map @@ -61,7 +64,6 @@ import Ledger.Interval ( LowerBound (LowerBound), UpperBound (UpperBound), ) -import Ledger.Scripts (Datum, DatumHash) import Ledger.Time (POSIXTimeRange) import Ledger.Tx ( Tx (..), @@ -71,12 +73,15 @@ import Ledger.Tx ( TxOutRef (..), ) import Ledger.Tx qualified as Tx +import Ledger.Tx.CardanoAPI (CardanoBuildTx) import Ledger.Value (Value) import Ledger.Value qualified as Value import Plutus.V1.Ledger.Api ( CurrencySymbol (..), TokenName (..), ) + +import Ledger.Constraints.OffChain qualified as Constraints import Prettyprinter (pretty, viaShow, (<+>)) import Prelude @@ -113,17 +118,33 @@ balanceTxIO' :: PubKeyHash -> UnbalancedTx -> Eff effs (Either Text Tx) -balanceTxIO' balanceCfg pabConf ownPkh unbalancedTx = +balanceTxIO' balanceCfg pabConf ownPkh unbalancedTx' = runEitherT $ do - (utxos, mcollateral) <- newEitherT $ utxosAndCollateralAtAddress @w balanceCfg pabConf changeAddr + updatedOuts <- + firstEitherT (Text.pack . show) $ + newEitherT $ + sequence <$> traverse (minUtxo @w) (unbalancedTx' ^. Constraints.tx . Tx.outputs) + + let unbalancedTx = unbalancedTx' & (Constraints.tx . Tx.outputs .~ updatedOuts) + + (utxos, mcollateral) <- + newEitherT $ + utxosAndCollateralAtAddress + @w + balanceCfg + pabConf + changeAddr + privKeys <- newEitherT $ Files.readPrivateKeys @w pabConf let utxoIndex :: Map TxOutRef TxOut utxoIndex = fmap Tx.toTxOut utxos <> unBalancedTxUtxoIndex unbalancedTx requiredSigs :: [PubKeyHash] - requiredSigs = map Ledger.unPaymentPubKeyHash $ Map.keys (unBalancedTxRequiredSignatories unbalancedTx) + requiredSigs = + unBalancedTxRequiredSignatories unbalancedTx + ^.. folded . to Ledger.unPaymentPubKeyHash lift $ printBpiLog @w (Debug [TxBalancingLog]) $ viaShow utxoIndex @@ -148,11 +169,12 @@ balanceTxIO' balanceCfg pabConf ownPkh unbalancedTx = else hoistEither $ addSignatories ownPkh privKeys requiredSigs tx -- Balance the tx - (balancedTx, minUtxos) <- balanceTxLoop utxoIndex privKeys [] preBalancedTx + balancedTx <- balanceTxLoop utxoIndex privKeys preBalancedTx + changeTxOutWithMinAmt <- newEitherT $ addOutput @w changeAddr balancedTx -- Get current Ada change let adaChange = getAdaChange utxoIndex balancedTx - bTx = fst <$> balanceTxLoop utxoIndex privKeys minUtxos (addOutput changeAddr balancedTx) + bTx = balanceTxLoop utxoIndex privKeys changeTxOutWithMinAmt -- Checks if there's ada change left, if there is then we check -- if `bcSeparateChange` is true, if this is the case then we create a new UTxO at @@ -182,27 +204,22 @@ balanceTxIO' balanceCfg pabConf ownPkh unbalancedTx = hoistEither $ addSignatories ownPkh privKeys requiredSigs fullyBalancedTx where changeAddr :: Address - changeAddr = Ledger.pubKeyHashAddress (Ledger.PaymentPubKeyHash ownPkh) pabConf.pcOwnStakePubKeyHash + changeAddr = + Ledger.pubKeyHashAddress + (Ledger.PaymentPubKeyHash ownPkh) + pabConf.pcOwnStakePubKeyHash balanceTxLoop :: Map TxOutRef TxOut -> Map PubKeyHash DummyPrivKey -> - [(TxOut, Integer)] -> Tx -> - EitherT Text (Eff effs) (Tx, [(TxOut, Integer)]) - balanceTxLoop utxoIndex privKeys prevMinUtxos tx = do + EitherT Text (Eff effs) Tx + balanceTxLoop utxoIndex privKeys tx = do void $ lift $ Files.writeAll @w pabConf tx - nextMinUtxos <- - newEitherT $ - calculateMinUtxos @w pabConf (Tx.txData tx) $ Tx.txOutputs tx \\ map fst prevMinUtxos - - let minUtxos = prevMinUtxos ++ nextMinUtxos - - lift $ printBpiLog @w (Debug [TxBalancingLog]) $ "Min utxos:" <+> pretty minUtxos -- Calculate fees by pre-balancing the tx, building it, and running the CLI on result txWithoutFees <- - newEitherT $ balanceTxStep @w balanceCfg minUtxos utxoIndex changeAddr $ tx `withFee` 0 + newEitherT $ balanceTxStep @w balanceCfg utxoIndex changeAddr $ tx `withFee` 0 exBudget <- newEitherT $ BodyBuilder.buildAndEstimateBudget @w pabConf privKeys txWithoutFees @@ -213,11 +230,11 @@ balanceTxIO' balanceCfg pabConf ownPkh unbalancedTx = lift $ printBpiLog @w (Debug [TxBalancingLog]) $ "Fees:" <+> pretty fees -- Rebalance the initial tx with the above fees - balancedTx <- newEitherT $ balanceTxStep @w balanceCfg minUtxos utxoIndex changeAddr $ tx `withFee` fees + balancedTx <- newEitherT $ balanceTxStep @w balanceCfg utxoIndex changeAddr $ tx `withFee` fees if balancedTx == tx - then pure (balancedTx, minUtxos) - else balanceTxLoop utxoIndex privKeys minUtxos balancedTx + then pure balancedTx + else balanceTxLoop utxoIndex privKeys balancedTx -- `utxosAndCollateralAtAddress` returns all the utxos that can be used as an input of a `Tx`, -- i.e. we filter out `CollateralUtxo` present at the user's address, so it can't be used as input of a `Tx`. @@ -228,9 +245,9 @@ utxosAndCollateralAtAddress :: PABConfig -> Address -> Eff effs (Either Text (Map TxOutRef Tx.ChainIndexTxOut, Maybe CollateralUtxo)) -utxosAndCollateralAtAddress balanceCfg pabConf changeAddr = +utxosAndCollateralAtAddress balanceCfg _pabConf changeAddr = runEitherT $ do - utxos <- newEitherT $ CardanoCLI.utxosAt @w pabConf changeAddr + utxos <- firstEitherT (Text.pack . show) $ newEitherT $ queryNode @w (UtxosAt changeAddr) inMemCollateral <- lift $ getInMemCollateral @w -- check if `bcHasScripts` is true, if this is the case then we search of @@ -255,7 +272,9 @@ hasChangeUTxO changeAddr tx = Tx.txOutAddress txOut == changeAddr getExecutionUnitPrices :: PABConfig -> ExecutionUnitPrices -getExecutionUnitPrices pabConf = fromMaybe (ExecutionUnitPrices 0 0) $ protocolParamPrices pabConf.pcProtocolParams +getExecutionUnitPrices pabConf = + fromMaybe (ExecutionUnitPrices 0 0) $ + pabConf.pcProtocolParams >>= protocolParamPrices getBudgetPrice :: ExecutionUnitPrices -> Ledger.ExBudget -> Integer getBudgetPrice (ExecutionUnitPrices cpuPrice memPrice) (Ledger.ExBudget cpuUsed memUsed) = @@ -270,35 +289,24 @@ multRational (num :% denom) s = (s * num) :% denom withFee :: Tx -> Integer -> Tx withFee tx fee = tx {txFee = Ada.lovelaceValueOf fee} -calculateMinUtxos :: - forall (w :: Type) (effs :: [Type -> Type]). - Member (PABEffect w) effs => - PABConfig -> - Map DatumHash Datum -> - [TxOut] -> - Eff effs (Either Text [(TxOut, Integer)]) -calculateMinUtxos pabConf datums txOuts = - zipWithM (fmap . (,)) txOuts <$> mapM (CardanoCLI.calculateMinUtxo @w pabConf datums) txOuts - balanceTxStep :: forall (w :: Type) (effs :: [Type -> Type]). Member (PABEffect w) effs => BalanceConfig -> - [(TxOut, Integer)] -> Map TxOutRef TxOut -> Address -> Tx -> Eff effs (Either Text Tx) -balanceTxStep balanceCfg minUtxos utxos changeAddr tx = +balanceTxStep balanceCfg utxos changeAddr tx = runEitherT $ - (newEitherT . balanceTxIns @w utxos) (addLovelaces minUtxos tx) - >>= hoistEither . handleNonAdaChange balanceCfg changeAddr utxos + (newEitherT . balanceTxIns @w utxos) tx + >>= newEitherT . handleNonAdaChange @w balanceCfg changeAddr utxos -- | Get change value of a transaction, taking inputs, outputs, mint and fees into account getChange :: Map TxOutRef TxOut -> Tx -> Value getChange utxos tx = let fees = lovelaceValue $ txFee tx - txInRefs = map Tx.txInRef $ Set.toList $ txInputs tx + txInRefs = map Tx.txInRef $ txInputs tx inputValue = mconcat $ map Tx.txOutValue $ mapMaybe (`Map.lookup` utxos) txInRefs outputValue = mconcat $ map Tx.txOutValue $ txOutputs tx nonMintedOutputValue = outputValue `minus` txMint tx @@ -320,23 +328,6 @@ hasDatum = isJust . txOutDatumHash hasNoDatum :: TxOut -> Bool hasNoDatum = not . hasDatum --- | Add min lovelaces to each tx output -addLovelaces :: [(TxOut, Integer)] -> Tx -> Tx -addLovelaces minLovelaces tx = - let lovelacesAdded = - map - ( \txOut -> - let outValue = txOutValue txOut - lovelaces = Ada.getLovelace $ Ada.fromValue outValue - minUtxo = fromMaybe 0 $ lookup txOut minLovelaces - in txOut - { txOutValue = - outValue <> Ada.lovelaceValueOf (max 0 (minUtxo - lovelaces)) - } - ) - $ txOutputs tx - in tx {txOutputs = lovelacesAdded} - balanceTxIns :: forall (w :: Type) (effs :: [Type -> Type]). Member (PABEffect w) effs => @@ -352,13 +343,17 @@ balanceTxIns utxos tx = do [ txFee tx , nonMintedValue ] - txIns <- newEitherT $ selectTxIns @w (txInputs tx) utxos minSpending - pure $ tx {txInputs = txIns <> txInputs tx} + txIns <- newEitherT $ selectTxIns @w (Set.fromList $ txInputs tx) utxos minSpending + -- constantly adding inputs and running balance loop forever + pure $ + tx + { txInputs = Set.fromList (txInputs tx) ^.. to (<> txIns) . folded + } -- | Set collateral or fail in case it's required but not available addTxCollaterals :: CollateralUtxo -> Tx -> Tx addTxCollaterals cOut tx - | txUsesScripts tx = tx {txCollateral = Set.singleton (Tx.pubKeyTxIn (collateralTxOutRef cOut))} + | txUsesScripts tx = tx {txCollateral = [Tx.pubKeyTxIn (collateralTxOutRef cOut)]} | otherwise = tx txUsesScripts :: Tx -> Bool @@ -366,12 +361,22 @@ txUsesScripts Tx {txInputs, txMintScripts} = not (null txMintScripts) || any (\TxIn {txInType} -> case txInType of Just ConsumeScriptAddress {} -> True; _ -> False) - (Set.toList txInputs) + txInputs -- | Ensures all non ada change goes back to user -handleNonAdaChange :: BalanceConfig -> Address -> Map TxOutRef TxOut -> Tx -> Either Text Tx -handleNonAdaChange balanceCfg changeAddr utxos tx = - let nonAdaChange = getNonAdaChange utxos tx +handleNonAdaChange :: + forall (w :: Type) (effs :: [Type -> Type]). + Member (PABEffect w) effs => + BalanceConfig -> + Address -> + Map TxOutRef TxOut -> + Tx -> + Eff effs (Either Text Tx) +handleNonAdaChange balanceCfg changeAddr utxos tx = runEitherT $ do + let nonAdaChange :: Value + nonAdaChange = getNonAdaChange utxos tx + + predicate :: TxOut -> Bool predicate = if bcSeparateChange balanceCfg then @@ -379,22 +384,32 @@ handleNonAdaChange balanceCfg changeAddr utxos tx = Tx.txOutAddress txout == changeAddr && not (justLovelace $ Tx.txOutValue txout) && hasNoDatum txout + -- && hasNoDatum txout ) else (\txout -> Tx.txOutAddress txout == changeAddr && hasNoDatum txout) + + newOutput :: TxOut newOutput = TxOut { txOutAddress = changeAddr - , txOutValue = nonAdaChange + , txOutValue = nonAdaChange <> Ada.lovelaceValueOf 1 , txOutDatumHash = Nothing } + + newOutputWithMinAmt <- + firstEitherT (Text.pack . show) $ + newEitherT $ minUtxo @w newOutput + + let outputs :: [TxOut] outputs = modifyFirst predicate - (Just . maybe newOutput (addValueToTxOut nonAdaChange)) + (Just . maybe newOutputWithMinAmt (addValueToTxOut nonAdaChange)) (txOutputs tx) - in if isValueNat nonAdaChange - then Right $ if Value.isZero nonAdaChange then tx else tx {txOutputs = outputs} - else Left "Not enough inputs to balance tokens." + + if isValueNat nonAdaChange + then return $ if Value.isZero nonAdaChange then tx else tx {txOutputs = outputs} + else throwE "Not enough inputs to balance tokens." {- | `addAdaChange` checks if `bcSeparateChange` is true, if it is then we add the ada change to seperate `TxOut` at changeAddr that contains only ada, @@ -408,7 +423,11 @@ addAdaChange balanceCfg changeAddr change tx { txOutputs = List.reverse $ modifyFirst - (\txout -> Tx.txOutAddress txout == changeAddr && justLovelace (txOutValue txout) && hasNoDatum txout) + ( \txout -> + Tx.txOutAddress txout == changeAddr + && justLovelace (txOutValue txout) + && hasNoDatum txout + ) (fmap $ addValueToTxOut $ Ada.lovelaceValueOf change) (List.reverse $ txOutputs tx) } @@ -424,16 +443,29 @@ addAdaChange balanceCfg changeAddr change tx addValueToTxOut :: Value -> TxOut -> TxOut addValueToTxOut val txOut = txOut {txOutValue = txOutValue txOut <> val} --- | Adds a 1 lovelace output to a transaction -addOutput :: Address -> Tx -> Tx -addOutput changeAddr tx = tx {txOutputs = txOutputs tx ++ [changeTxOut]} - where - changeTxOut = - TxOut - { txOutAddress = changeAddr - , txOutValue = Ada.lovelaceValueOf 1 - , txOutDatumHash = Nothing - } +-- | creates a Tx output with min lovelace. +addOutput :: + forall (w :: Type) (effs :: [Type -> Type]). + Member (PABEffect w) effs => + Address -> + Tx -> + Eff effs (Either Text Tx) +addOutput changeAddr tx = + runEitherT $ do + let changeTxOut :: TxOut + changeTxOut = + TxOut + { txOutAddress = changeAddr + , txOutValue = Ada.lovelaceValueOf 1 + , txOutDatumHash = Nothing + } + + changeTxOutWithMinAmt <- + firstEitherT (Text.pack . show) $ + newEitherT $ + minUtxo @w changeTxOut + + return $ tx {txOutputs = txOutputs tx ++ [changeTxOutWithMinAmt]} {- | Add the required signatories to the transaction. Be aware the the signature itself is invalid, and will be ignored. Only the pub key hashes are used, mapped to signing key files on disk. @@ -453,9 +485,10 @@ addValidRange :: forall (w :: Type) (effs :: [Type -> Type]). Member (PABEffect w) effs => POSIXTimeRange -> - Tx -> + Either CardanoBuildTx Tx -> Eff effs (Either Text Tx) -addValidRange timeRange tx = +addValidRange _ (Left _) = pure $ Left "BPI is not using CardanoBuildTx" +addValidRange timeRange (Right tx) = if validateRange timeRange then bimap (Text.pack . show) (setRange tx) @@ -478,7 +511,8 @@ modifyFirst :: forall (a :: Type). -- | Predicate for value to update (a -> Bool) -> - -- | Modifier, input Maybe representing existing value (or Nothing if missing), output value representing new value (or Nothing to remove) + -- | Modifier, input Maybe representing existing value (or Nothing if missing), + -- output value representing new value (or Nothing to remove) (Maybe a -> Maybe a) -> [a] -> [a] diff --git a/src/BotPlutusInterface/CardanoAPI.hs b/src/BotPlutusInterface/CardanoAPI.hs new file mode 100644 index 00000000..e600632c --- /dev/null +++ b/src/BotPlutusInterface/CardanoAPI.hs @@ -0,0 +1,101 @@ +module BotPlutusInterface.CardanoAPI ( + fromCardanoTxOut, + fromCardanoTxOutDatum, + addressInEraToAny, + toCardanoSlotNo, + fromCardanoSlotNo, + fromCardanoEpochInfo, + posixTimeToSlot, +) where + +import Cardano.Api qualified as CApi +import Cardano.Ledger.Slot (EpochInfo) +import Cardano.Prelude (maybeToEither) +import Cardano.Slotting.EpochInfo (hoistEpochInfo) +import Cardano.Slotting.Time (SystemStart, toRelativeTime) +import Control.Monad.Trans.Except (runExcept) +import Data.Bifunctor (first) +import Data.Text (Text) +import Data.Text qualified as Text +import Data.Time (UTCTime, secondsToNominalDiffTime) +import Data.Time.Clock.POSIX (posixSecondsToUTCTime) +import Ledger qualified +import Ledger.Tx (ChainIndexTxOut (..)) +import Ledger.Tx.CardanoAPI qualified as TxApi +import Ouroboros.Consensus.HardFork.History qualified as Consensus +import Ouroboros.Consensus.HardFork.History.Qry qualified as HF +import Plutus.Script.Utils.Scripts qualified as ScriptUtils +import Plutus.V1.Ledger.Api (Credential (..)) +import Plutus.V2.Ledger.Tx qualified as V2 +import PlutusTx.Prelude qualified as PlutusTx +import Prelude + +fromCardanoTxOut :: CApi.TxOut CApi.CtxUTxO CApi.BabbageEra -> Either TxApi.FromCardanoError ChainIndexTxOut +fromCardanoTxOut (CApi.TxOut caddr val cdatum _refScript) = do + addr <- TxApi.fromCardanoAddressInEra caddr + + case Ledger.addressCredential addr of + ScriptCredential valHash -> do + dat <- maybeToEither TxApi.SimpleScriptsNotSupported $ convertOutputDatum (fromCardanoTxOutDatum cdatum) + return $ + ScriptChainIndexTxOut + addr + (TxApi.fromCardanoValue $ CApi.txOutValueToValue val) + dat + Nothing + (valHash, Nothing) + PubKeyCredential _ -> do + return $ + PublicKeyChainIndexTxOut + addr + (TxApi.fromCardanoValue $ CApi.txOutValueToValue val) + (convertOutputDatum $ fromCardanoTxOutDatum cdatum) + Nothing + +fromCardanoTxOutDatum :: CApi.TxOutDatum CApi.CtxUTxO CApi.BabbageEra -> V2.OutputDatum +fromCardanoTxOutDatum CApi.TxOutDatumNone = V2.NoOutputDatum +fromCardanoTxOutDatum (CApi.TxOutDatumHash _ h) = V2.OutputDatumHash $ Ledger.DatumHash $ PlutusTx.toBuiltin (CApi.serialiseToRawBytes h) +fromCardanoTxOutDatum (CApi.TxOutDatumInline _ d) = V2.OutputDatum $ Ledger.Datum $ TxApi.fromCardanoScriptData d + +addressInEraToAny :: CApi.AddressInEra CApi.BabbageEra -> CApi.AddressAny +addressInEraToAny (CApi.AddressInEra CApi.ByronAddressInAnyEra a) = CApi.AddressByron a +addressInEraToAny (CApi.AddressInEra (CApi.ShelleyAddressInEra _) a) = CApi.AddressShelley a + +toCardanoSlotNo :: Ledger.Slot -> CApi.SlotNo +toCardanoSlotNo (Ledger.Slot s) = CApi.SlotNo $ fromInteger s + +fromCardanoSlotNo :: CApi.SlotNo -> Ledger.Slot +fromCardanoSlotNo (CApi.SlotNo s) = Ledger.Slot (toInteger s) + +fromCardanoEpochInfo :: + CApi.EraHistory mode -> + EpochInfo (Either Text) +fromCardanoEpochInfo (CApi.EraHistory _ interpreter) = + hoistEpochInfo (first (Text.pack . show) . runExcept) $ + Consensus.interpreterToEpochInfo interpreter + +posixTimeToSlot :: + SystemStart -> + CApi.EraHistory CApi.CardanoMode -> + Ledger.POSIXTime -> + Either HF.PastHorizonException Ledger.Slot +posixTimeToSlot sysStart eraHist pTime = do + -- toRelativeTime checks that pTime >= sysStart via `Control.Exception.assert` + let relativeTime = toRelativeTime sysStart (toUtc pTime) + (CApi.EraHistory _ int) = eraHist + query = HF.wallclockToSlot relativeTime + + (sn, _, _) <- HF.interpretQuery int query + pure (fromCardanoSlotNo sn) + where + toUtc :: Ledger.POSIXTime -> UTCTime + toUtc (Ledger.POSIXTime milliseconds) = + posixSecondsToUTCTime + . secondsToNominalDiffTime + $ fromInteger milliseconds / 1000 + +convertOutputDatum :: V2.OutputDatum -> Maybe (Ledger.DatumHash, Maybe Ledger.Datum) +convertOutputDatum = \case + V2.NoOutputDatum -> Nothing + V2.OutputDatumHash dh -> Just (dh, Nothing) + V2.OutputDatum d -> Just (ScriptUtils.datumHash d, Just d) diff --git a/src/BotPlutusInterface/CardanoCLI.hs b/src/BotPlutusInterface/CardanoCLI.hs index 4e66b65a..b8cf0c46 100644 --- a/src/BotPlutusInterface/CardanoCLI.hs +++ b/src/BotPlutusInterface/CardanoCLI.hs @@ -3,14 +3,12 @@ module BotPlutusInterface.CardanoCLI ( submitTx, - calculateMinUtxo, calculateMinFee, buildTx, signTx, validatorScriptFilePath, unsafeSerialiseAddress, policyScriptFilePath, - utxosAt, queryTip, ) where @@ -18,7 +16,8 @@ import BotPlutusInterface.Effects (PABEffect, ShellArgs (..), callCommand) import BotPlutusInterface.Files ( DummyPrivKey (FromSKey, FromVKey), datumJsonFilePath, - metadataFilePath, + -- TODO: Removed for now, as the main iohk branch doesn't support metadata yet + -- metadataFilePath, policyScriptFilePath, redeemerJsonFilePath, signingKeyFilePath, @@ -35,7 +34,11 @@ import BotPlutusInterface.Types ( spendBudgets, ) import BotPlutusInterface.UtxoParser qualified as UtxoParser -import Cardano.Api.Shelley (NetworkId (Mainnet, Testnet), NetworkMagic (..), serialiseAddress) +import Cardano.Api.Shelley ( + NetworkId (Mainnet, Testnet), + NetworkMagic (NetworkMagic), + serialiseAddress, + ) import Control.Monad (join) import Control.Monad.Freer (Eff, Member) import Data.Aeson qualified as JSON @@ -44,7 +47,6 @@ import Data.Attoparsec.Text (parseOnly) import Data.Bifunctor (first) import Data.Bool (bool) import Data.ByteString.Lazy.Char8 qualified as Char8 -import Data.Either (fromRight) import Data.Either.Combinators (mapLeft) import Data.Hex (hex) import Data.Kind (Type) @@ -52,13 +54,12 @@ import Data.List (sort) import Data.Map (Map) import Data.Map qualified as Map import Data.Maybe (fromMaybe) -import Data.Set (Set) -import Data.Set qualified as Set import Data.Text (Text) import Data.Text qualified as Text import Data.Text.Encoding (decodeUtf8) -import Ledger (Slot (Slot), SlotRange) +import Ledger (Slot (Slot), SlotRange, TxInType (ConsumeScriptAddress)) import Ledger qualified +import Ledger.Ada (fromValue, getLovelace) import Ledger.Ada qualified as Ada import Ledger.Address (Address (..)) import Ledger.Crypto (PubKey, PubKeyHash (getPubKeyHash)) @@ -71,30 +72,40 @@ import Ledger.Interval ( import Ledger.Scripts (Datum, DatumHash (..)) import Ledger.Scripts qualified as Scripts import Ledger.Tx ( - ChainIndexTxOut, - RedeemerPtr (..), + RedeemerPtr (RedeemerPtr), Redeemers, - ScriptTag (..), - Tx (..), - TxIn (..), - TxInType (..), - TxOut (..), - TxOutRef (..), + ScriptTag (Mint), + Tx ( + txCollateral, + txData, + txFee, + txInputs, + txMint, + txMintScripts, + txOutputs, + txRedeemers, + txSignatures, + txValidRange + ), + TxId (TxId), + TxIn (TxIn), + TxInType (ConsumePublicKeyAddress, ConsumeSimpleScriptAddress), + TxOut (TxOut), + TxOutRef (TxOutRef), txId, ) -import Ledger.TxId (TxId (..)) +import Ledger.Tx.CardanoAPI (toCardanoAddressInEra) import Ledger.Value (Value) import Ledger.Value qualified as Value -import Plutus.Contract.CardanoAPI (toCardanoAddress) -import Plutus.V1.Ledger.Ada (fromValue, getLovelace) +import Plutus.Script.Utils.Scripts qualified as ScriptUtils import Plutus.V1.Ledger.Api ( - CurrencySymbol (..), - ExBudget (..), - ExCPU (..), - ExMemory (..), - TokenName (..), + CurrencySymbol (unCurrencySymbol), + ExBudget (ExBudget), + ExCPU (ExCPU), + ExMemory (ExMemory), + TokenName (unTokenName), ) -import PlutusTx.Builtins (BuiltinByteString, fromBuiltin) +import PlutusTx.Builtins (fromBuiltin) import Prelude -- | Getting information of the latest block @@ -111,51 +122,6 @@ queryTip config = , cmdOutParser = fromMaybe (error "Couldn't parse chain tip") . JSON.decode . Char8.pack } --- | Getting all available UTXOs at an address (all utxos are assumed to be PublicKeyChainIndexTxOut) -utxosAt :: - forall (w :: Type) (effs :: [Type -> Type]). - Member (PABEffect w) effs => - PABConfig -> - Address -> - Eff effs (Either Text (Map TxOutRef ChainIndexTxOut)) -utxosAt pabConf address = - callCommand @w - ShellArgs - { cmdName = "cardano-cli" - , cmdArgs = - mconcat - [ ["query", "utxo"] - , ["--address", unsafeSerialiseAddress pabConf.pcNetwork address] - , networkOpt pabConf - ] - , cmdOutParser = - Map.fromList - . fromRight [] - . parseOnly (UtxoParser.utxoMapParser address) - . Text.pack - } - -calculateMinUtxo :: - forall (w :: Type) (effs :: [Type -> Type]). - Member (PABEffect w) effs => - PABConfig -> - Map DatumHash Datum -> - TxOut -> - Eff effs (Either Text Integer) -calculateMinUtxo pabConf datums txOut = - join - <$> callCommand @w - ShellArgs - { cmdName = "cardano-cli" - , cmdArgs = - mconcat - [ ["transaction", "calculate-min-required-utxo", "--alonzo-era"] - , txOutOpts pabConf datums [txOut] - , ["--protocol-params-file", pabConf.pcProtocolParamsFile] - ] - , cmdOutParser = mapLeft Text.pack . parseOnly UtxoParser.feeParser . Text.pack - } - -- | Calculating fee for an unbalanced transaction calculateMinFee :: forall (w :: Type) (effs :: [Type -> Type]). @@ -210,14 +176,15 @@ buildTx pabConf privKeys txBudget tx = do (Map.keys (Ledger.txSignatures tx)) opts ins mints = mconcat - [ ["transaction", "build-raw", "--alonzo-era"] + [ ["transaction", "build-raw", "--babbage-era"] , ins , txInCollateralOpts (txCollateral tx) , txOutOpts pabConf (txData tx) (txOutputs tx) , mints , validRangeOpts (txValidRange tx) - , metadataOpts pabConf (txMetadata tx) - , requiredSigners + , -- TODO: Removed for now, as the main iohk branch doesn't support metadata yet + -- , metadataOpts pabConf (txMetadata tx) + requiredSigners , ["--fee", showText . getLovelace . fromValue $ txFee tx] , mconcat [ ["--protocol-params-file", pabConf.pcProtocolParamsFile] @@ -268,7 +235,7 @@ submitTx pabConf tx = ) (const ()) -txInOpts :: SpendBudgets -> PABConfig -> Set TxIn -> ([Text], ExBudget) +txInOpts :: SpendBudgets -> PABConfig -> [TxIn] -> ([Text], ExBudget) txInOpts spendIndex pabConf = foldMap ( \(TxIn txOutRef txInType) -> @@ -282,25 +249,24 @@ txInOpts spendIndex pabConf = , opts ] ) - . Set.toList where scriptInputs :: Maybe TxInType -> ExBudget -> ([Text], ExBudget) scriptInputs txInType exBudget = case txInType of - Just (ConsumeScriptAddress validator redeemer datum) -> + Just (ConsumeScriptAddress _lang validator redeemer datum) -> (,exBudget) $ mconcat [ [ "--tx-in-script-file" - , validatorScriptFilePath pabConf (Ledger.validatorHash validator) + , validatorScriptFilePath pabConf (Scripts.validatorHash validator) ] , [ "--tx-in-datum-file" - , datumJsonFilePath pabConf (Ledger.datumHash datum) + , datumJsonFilePath pabConf (ScriptUtils.datumHash datum) ] , [ "--tx-in-redeemer-file" - , redeemerJsonFilePath pabConf (Ledger.redeemerHash redeemer) + , redeemerJsonFilePath pabConf (ScriptUtils.redeemerHash redeemer) ] , [ "--tx-in-execution-units" @@ -311,12 +277,18 @@ txInOpts spendIndex pabConf = Just ConsumeSimpleScriptAddress -> mempty Nothing -> mempty -txInCollateralOpts :: Set TxIn -> [Text] +txInCollateralOpts :: [TxIn] -> [Text] txInCollateralOpts = - concatMap (\(TxIn txOutRef _) -> ["--tx-in-collateral", txOutRefToCliArg txOutRef]) . Set.toList + concatMap (\(TxIn txOutRef _) -> ["--tx-in-collateral", txOutRefToCliArg txOutRef]) -- Minting options -mintOpts :: MintBudgets -> PABConfig -> Set Scripts.MintingPolicy -> Redeemers -> Value -> ([Text], ExBudget) +mintOpts :: + MintBudgets -> + PABConfig -> + Map Ledger.MintingPolicyHash Ledger.MintingPolicy -> + Redeemers -> + Value -> + ([Text], ExBudget) mintOpts mintIndex pabConf mintingPolicies redeemers mintValue = let scriptOpts = foldMap @@ -333,12 +305,12 @@ mintOpts mintIndex pabConf mintingPolicies redeemers mintValue = (,exBudget) $ mconcat [ ["--mint-script-file", policyScriptFilePath pabConf curSymbol] - , ["--mint-redeemer-file", redeemerJsonFilePath pabConf (Ledger.redeemerHash r)] + , ["--mint-redeemer-file", redeemerJsonFilePath pabConf (ScriptUtils.redeemerHash r)] , ["--mint-execution-units", exBudgetToCliArg exBudget] ] in orMempty $ fmap toOpts redeemer ) - $ zip [0 ..] $ Set.toList mintingPolicies + $ zip [0 ..] $ Map.elems mintingPolicies mintOpt = if not (Value.isZero mintValue) then ["--mint", valueToCliArg mintValue] @@ -409,7 +381,7 @@ valueToCliArg val = unsafeSerialiseAddress :: NetworkId -> Address -> Text unsafeSerialiseAddress network address = - case serialiseAddress <$> toCardanoAddress network address of + case serialiseAddress <$> toCardanoAddressInEra network address of Right a -> a Left _ -> error "Couldn't create address" @@ -420,12 +392,8 @@ exBudgetToCliArg (ExBudget (ExCPU steps) (ExMemory memory)) = showText :: forall (a :: Type). Show a => a -> Text showText = Text.pack . show --- -- TODO: There is some issue with this function, the generated wallet key is incorrect --- toWalletKey :: Wallet -> Text --- toWalletKey = --- decodeUtf8 . convertToBase Base16 . hash @ByteString @Blake2b_160 . unXPub . walletXPub - -metadataOpts :: PABConfig -> Maybe BuiltinByteString -> [Text] -metadataOpts _ Nothing = mempty -metadataOpts pabConf (Just meta) = - ["--metadata-json-file", metadataFilePath pabConf meta] +-- TODO: Removed for now, as the main iohk branch doesn't support metadata yet +-- metadataOpts :: PABConfig -> Maybe BuiltinByteString -> [Text] +-- metadataOpts _ Nothing = mempty +-- metadataOpts pabConf (Just meta) = +-- ["--metadata-json-file", metadataFilePath pabConf meta] diff --git a/src/BotPlutusInterface/CardanoNode/Effects.hs b/src/BotPlutusInterface/CardanoNode/Effects.hs new file mode 100644 index 00000000..4856d4a9 --- /dev/null +++ b/src/BotPlutusInterface/CardanoNode/Effects.hs @@ -0,0 +1,117 @@ +{-# LANGUAGE RankNTypes #-} + +{- This is ongoing effort on replacing `cardano-cli` calls with `Cardano.Api` queries, see issues + https://github.com/mlabs-haskell/bot-plutus-interface/issues/109 + https://github.com/mlabs-haskell/bot-plutus-interface/issues/101 + We decided to provide single replacement for `BotPlutusInterface.CardanoCLI.utxosAt` + early on to enable inline Datum support from one side and avoid extending + `cardano-cli` output parser from the other side. + See https://github.com/mlabs-haskell/bot-plutus-interface/issues/145 +-} +module BotPlutusInterface.CardanoNode.Effects ( + utxosAt, + pparams, + handleNodeQuery, + runNodeQuery, + NodeQuery (..), +) where + +import BotPlutusInterface.CardanoNode.Query ( + NodeConn, + NodeQueryError, + QueryConstraint, + connectionInfo, + queryBabbageEra, + toQueryError, + ) + +import BotPlutusInterface.CardanoAPI ( + addressInEraToAny, + fromCardanoTxOut, + ) + +import BotPlutusInterface.Types (PABConfig) +import Cardano.Api (LocalNodeConnectInfo (..)) +import Cardano.Api qualified as CApi +import Cardano.Api.Shelley qualified as CApi.S +import Control.Lens (folded, to, (^..)) +import Control.Monad.Freer (Eff, Members, interpret, runM, send, type (~>)) +import Control.Monad.Freer.Reader (Reader, ask, runReader) +import Control.Monad.Trans.Class (lift) +import Control.Monad.Trans.Either (firstEitherT, hoistEither, newEitherT, runEitherT) +import Data.Map (Map) +import Data.Map qualified as Map +import Data.Set qualified as Set +import Ledger.Address (Address) +import Ledger.Tx (ChainIndexTxOut (..)) +import Ledger.Tx.CardanoAPI qualified as TxApi +import Plutus.V2.Ledger.Tx qualified as V2 +import Prelude + +{- | 'NodeQuery' effect is used to query local node, + this is achieved by using 'Cardano.Api'. +-} +data NodeQuery a where + -- | 'UtxosAt' queries local node to get all the utxos at particular address. + UtxosAt :: Address -> NodeQuery (Either NodeQueryError (Map V2.TxOutRef ChainIndexTxOut)) + -- | 'PParams' queries local node to get it's 'ProtocolParameters'. + PParams :: NodeQuery (Either NodeQueryError CApi.S.ProtocolParameters) + +utxosAt :: + forall effs. + Members '[NodeQuery] effs => + Address -> + Eff effs (Either NodeQueryError (Map V2.TxOutRef ChainIndexTxOut)) +utxosAt = send . UtxosAt + +pparams :: + forall effs. + Members '[NodeQuery] effs => + Eff effs (Either NodeQueryError CApi.S.ProtocolParameters) +pparams = send PParams + +handleNodeQuery :: + forall effs. + QueryConstraint effs => + Eff (NodeQuery ': effs) ~> Eff effs +handleNodeQuery = + interpret $ \case + UtxosAt addr -> handleUtxosAt addr + PParams -> queryBabbageEra CApi.QueryProtocolParameters + +handleUtxosAt :: + forall effs. + QueryConstraint effs => + Address -> + Eff effs (Either NodeQueryError (Map V2.TxOutRef ChainIndexTxOut)) +handleUtxosAt addr = runEitherT $ do + conn <- lift $ ask @NodeConn + + caddr <- + firstEitherT toQueryError $ + hoistEither $ + TxApi.toCardanoAddressInEra (localNodeNetworkId conn) addr + + let query :: CApi.QueryInShelleyBasedEra era (CApi.UTxO era) + query = CApi.QueryUTxO $ CApi.QueryUTxOByAddress $ Set.singleton $ addressInEraToAny caddr + + (CApi.UTxO result) <- newEitherT $ queryBabbageEra query + + chainIndexTxOuts <- + firstEitherT toQueryError $ + hoistEither $ + sequenceA $ + result ^.. folded . to fromCardanoTxOut + + let txOutRefs :: [V2.TxOutRef] + txOutRefs = TxApi.fromCardanoTxIn <$> Map.keys result + + return $ Map.fromList $ zip txOutRefs chainIndexTxOuts + +-- | 'runNodeQuery' runs executes the 'NodeQuery' effects. +runNodeQuery :: PABConfig -> Eff '[NodeQuery, Reader NodeConn, IO] ~> IO +runNodeQuery conf effs = do + conn <- connectionInfo conf + runM $ + runReader conn $ + handleNodeQuery effs diff --git a/src/BotPlutusInterface/CardanoNode/Query.hs b/src/BotPlutusInterface/CardanoNode/Query.hs new file mode 100644 index 00000000..ba57be6d --- /dev/null +++ b/src/BotPlutusInterface/CardanoNode/Query.hs @@ -0,0 +1,91 @@ +-- | Several query functions to query local node +module BotPlutusInterface.CardanoNode.Query ( + NodeQueryError (..), + NodeConn, + QueryConstraint, + queryInCardanoMode, + queryBabbageEra, + toQueryError, + connectionInfo, +) where + +import BotPlutusInterface.Types (PABConfig (..)) +import Cardano.Api qualified as CApi +import Control.Monad.Freer (Eff, LastMember, Member, send) +import Control.Monad.Freer.Reader (Reader, ask) +import Control.Monad.Trans.Class +import Control.Monad.Trans.Either +import Control.Monad.Trans.Except (throwE) +import Data.Text (Text) +import Data.Text qualified as Text +import System.Environment (getEnv) +import Prelude + +{- | Error returned in case any error happened querying local node + (wraps whatever received in `Text`) +-} +data NodeQueryError + = NodeQueryError Text + deriving stock (Eq, Show) + +-- | Represents the connection to the local node. +type NodeConn = CApi.LocalNodeConnectInfo CApi.CardanoMode + +-- | Constraints that are required to query local node. +type QueryConstraint effs = (Member (Reader NodeConn) effs, LastMember IO effs) + +{- | 'queryInCardanoMode' establishes connection with local node and execute a single query. + The Query has a type of 'QueryInMode CardanoMode a', hence we don't need any information + about current era of the local node to execute certain queries, unlike `queryBabbageEra`. +-} +queryInCardanoMode :: + forall effs a. + (QueryConstraint effs) => + CApi.QueryInMode CApi.CardanoMode a -> + Eff effs (Either NodeQueryError a) +queryInCardanoMode query = + runEitherT $ do + conn <- lift $ ask @NodeConn + firstEitherT (NodeQueryError . Text.pack . show) $ + newEitherT $ + send $ + CApi.queryNodeLocalState conn Nothing query + +{- | 'queryBabbageEra' expects that every query must be in 'BabbageEra' and + it expects that the local node's current era should be 'BabbageEra'. +-} +queryBabbageEra :: + forall effs a. + (QueryConstraint effs) => + CApi.QueryInShelleyBasedEra CApi.BabbageEra a -> + Eff effs (Either NodeQueryError a) +queryBabbageEra query = + runEitherT $ do + result <- + newEitherT $ + queryInCardanoMode $ + CApi.QueryInEra CApi.BabbageEraInCardanoMode $ + CApi.QueryInShelleyBasedEra CApi.ShelleyBasedEraBabbage query + case result of + Right a -> return a + Left e -> throwE $ toQueryError e + +{- | create connection info from 'PABConfig', this function excepts that there's + "CARDANO_NODE_SOCKET_PATH" environment variable present in the shell and has a + value that contains path for local node's socket. +-} +connectionInfo :: PABConfig -> IO NodeConn +connectionInfo pabConf = + CApi.LocalNodeConnectInfo + (CApi.CardanoModeParams epochSlots) + (pcNetwork pabConf) + <$> getEnv "CARDANO_NODE_SOCKET_PATH" + where + -- This parameter needed only for the Byron era. Since the Byron + -- era is over and the parameter has never changed it is ok to + -- hardcode this. See comment on `Cardano.Api.ConsensusModeParams` in + -- cardano-node. + epochSlots = CApi.EpochSlots 21600 + +toQueryError :: Show e => e -> NodeQueryError +toQueryError = NodeQueryError . Text.pack . show diff --git a/src/BotPlutusInterface/ChainIndex.hs b/src/BotPlutusInterface/ChainIndex.hs index 9e85d878..05ac6c46 100644 --- a/src/BotPlutusInterface/ChainIndex.hs +++ b/src/BotPlutusInterface/ChainIndex.hs @@ -19,6 +19,7 @@ import Network.HTTP.Client ( ) import Network.HTTP.Types (Status (statusCode)) import Plutus.ChainIndex.Api ( + QueryAtAddressRequest (QueryAtAddressRequest), TxoAtAddressRequest (TxoAtAddressRequest), TxosResponse (TxosResponse), UtxoAtAddressRequest (UtxoAtAddressRequest), @@ -55,6 +56,13 @@ handleChainIndexReq contractEnv@ContractEnvironment {cePABConfig} = -- pure $ RedeemerHashResponse (Maybe Redeemer) TxOutFromRef txOutRef -> TxOutRefResponse <$> chainIndexQueryOne cePABConfig (ChainIndexClient.getTxOut txOutRef) + UnspentTxOutFromRef txOutRef -> + UnspentTxOutResponse <$> chainIndexQueryOne cePABConfig (ChainIndexClient.getUnspentTxOut txOutRef) + UnspentTxOutSetAtAddress page credential -> + UnspentTxOutsAtResponse + <$> chainIndexQueryMany + cePABConfig + (ChainIndexClient.getUnspentTxOutsAtAddress (QueryAtAddressRequest (Just page) credential)) TxFromTxId txId -> TxIdResponse <$> chainIndexQueryOne cePABConfig (ChainIndexClient.getTx txId) UtxoSetMembership txOutRef -> diff --git a/src/BotPlutusInterface/Config.hs b/src/BotPlutusInterface/Config.hs index 7d515016..6088a72f 100644 --- a/src/BotPlutusInterface/Config.hs +++ b/src/BotPlutusInterface/Config.hs @@ -48,9 +48,7 @@ import PlutusConfig.Base ( portSpec, ) import PlutusConfig.Cardano.Api () -import PlutusConfig.Cardano.Api.Shelley ( - readProtocolParametersJSON, - ) +import PlutusConfig.Cardano.Api.Shelley (readProtocolParametersJSON) import PlutusConfig.Ledger () import PlutusConfig.Types ( ToValue (toValue), @@ -180,7 +178,7 @@ pabConfigSpec = sectionsSpec "PABConfig" $ do -- pcProtocolParamsFile .json file -- pcProtocolParams <- -- sectionWithDefault (pcProtocolParams def) "protocolParams" "" - let pcProtocolParams = def + let pcProtocolParams = Nothing pcScriptFileDir <- sectionWithDefault' @@ -317,8 +315,8 @@ loadPABConfig fn = do Left errPParams -> pure $ Left $ Text.unpack errPParams Right _ -> loadPABConfig fn | otherwise -> - pure $ pparamsError pcProtocolParamsFile err - Right pcProtocolParams -> pure $ Right conf {pcProtocolParams} + return $ pparamsError pcProtocolParamsFile err + Right pparams -> return $ Right conf {pcProtocolParams = Just pparams} where pparamsError f e = Left $ "protocolParamsFile: " <> toString f <> ": " <> e diff --git a/src/BotPlutusInterface/Contract.hs b/src/BotPlutusInterface/Contract.hs index 37567103..c6f3073a 100644 --- a/src/BotPlutusInterface/Contract.hs +++ b/src/BotPlutusInterface/Contract.hs @@ -7,6 +7,7 @@ module BotPlutusInterface.Contract (runContract, handleContract) where import BotPlutusInterface.Balance qualified as Balance import BotPlutusInterface.BodyBuilder qualified as BodyBuilder import BotPlutusInterface.CardanoCLI qualified as CardanoCLI +import BotPlutusInterface.CardanoNode.Effects (NodeQuery (UtxosAt)) import BotPlutusInterface.Collateral qualified as Collateral import BotPlutusInterface.Effects ( PABEffect, @@ -18,10 +19,12 @@ import BotPlutusInterface.Effects ( handleContractLog, handlePABEffect, logToContract, + minUtxo, posixTimeRangeToContainedSlotRange, posixTimeToSlot, printBpiLog, queryChainIndex, + queryNode, readFileTextEnvelope, saveBudget, setInMemCollateral, @@ -40,8 +43,13 @@ import BotPlutusInterface.Types ( TxFile (Signed), collateralValue, ) -import Cardano.Api (AsType (..), EraInMode (..), Tx (Tx)) -import Control.Lens (preview, (^.)) +import Cardano.Api ( + AsType (..), + EraInMode (..), + Tx (Tx), + ) +import Cardano.Prelude (liftA2) +import Control.Lens (preview, (.~), (^.)) import Control.Monad (join, void, when) import Control.Monad.Freer (Eff, Member, interpret, reinterpret, runM, subsume, type (~>)) import Control.Monad.Freer.Error (runError) @@ -52,22 +60,22 @@ import Control.Monad.Trans.Either (EitherT, eitherT, firstEitherT, hoistEither, import Control.Monad.Trans.Except (ExceptT, throwE) import Data.Aeson (ToJSON, Value (Array, Bool, Null, Number, Object, String)) import Data.Aeson.Extras (encodeByteString) +import Data.Aeson.KeyMap qualified as KeyMap import Data.Either.Combinators (maybeToLeft, swapEither) -import Data.Function (fix) -import Data.HashMap.Strict qualified as HM +import Data.Function (fix, (&)) import Data.Kind (Type) +import Data.List.NonEmpty (NonEmpty ((:|))) import Data.Map qualified as Map import Data.Row (Row) import Data.Text (Text) -import Data.Text qualified as T import Data.Text qualified as Text import Data.Vector qualified as V import Ledger (POSIXTime, getCardanoTxId) import Ledger qualified import Ledger.Address (PaymentPubKeyHash (PaymentPubKeyHash)) -import Ledger.Constraints.OffChain (UnbalancedTx (..)) +import Ledger.Constraints.OffChain (UnbalancedTx (..), tx) import Ledger.Slot (Slot (Slot)) -import Ledger.Tx (CardanoTx) +import Ledger.Tx (CardanoTx (CardanoApiTx, EmulatorTx), outputs) import Ledger.Tx qualified as Tx import Plutus.ChainIndex.TxIdState (fromTx, transactionStatus) import Plutus.ChainIndex.Types (RollbackState (..), TxIdState, TxStatus) @@ -124,11 +132,11 @@ instance Pretty Value where ( \(k, v) -> PP.hang 2 $ PP.sep - [ pretty k <+> ": " + [ pretty (show k) <+> ": " , pretty v ] ) - $ HM.toList obj + $ KeyMap.toList obj pretty Null = "null" handleWriter :: @@ -180,38 +188,56 @@ handlePABReq contractEnv req = do ---------------------- -- Handled requests -- ---------------------- - OwnPaymentPublicKeyHashReq -> - pure $ OwnPaymentPublicKeyHashResp $ PaymentPubKeyHash contractEnv.cePABConfig.pcOwnPubKeyHash + OwnAddressesReq -> + pure + . OwnAddressesResp + . nonEmptySingleton + $ Ledger.pubKeyHashAddress + (PaymentPubKeyHash contractEnv.cePABConfig.pcOwnPubKeyHash) + contractEnv.cePABConfig.pcOwnStakePubKeyHash OwnContractInstanceIdReq -> pure $ OwnContractInstanceIdResp (ceContractInstanceId contractEnv) ChainIndexQueryReq query -> ChainIndexQueryResp <$> queryChainIndex @w query BalanceTxReq unbalancedTx -> BalanceTxResp <$> balanceTx @w contractEnv unbalancedTx - WriteBalancedTxReq tx -> - WriteBalancedTxResp <$> writeBalancedTx @w contractEnv tx + WriteBalancedTxReq tx' -> + WriteBalancedTxResp <$> writeBalancedTx @w contractEnv tx' AwaitSlotReq s -> AwaitSlotResp <$> awaitSlot @w contractEnv s AwaitTimeReq t -> AwaitTimeResp <$> awaitTime @w contractEnv t - CurrentSlotReq -> CurrentSlotResp <$> currentSlot @w contractEnv + CurrentPABSlotReq -> CurrentPABSlotResp <$> currentSlot @w contractEnv CurrentTimeReq -> CurrentTimeResp <$> currentTime @w contractEnv PosixTimeRangeToContainedSlotRangeReq posixTimeRange -> either (error . show) (PosixTimeRangeToContainedSlotRangeResp . Right) <$> posixTimeRangeToContainedSlotRange @w posixTimeRange AwaitTxStatusChangeReq txId -> AwaitTxStatusChangeResp txId <$> awaitTxStatusChange @w contractEnv txId + AdjustUnbalancedTxReq unbalancedTx -> AdjustUnbalancedTxResp <$> adjustUnbalancedTx' @w @effs unbalancedTx ------------------------ -- Unhandled requests -- ------------------------ - -- AwaitTimeReq t -> pure $ AwaitTimeResp t - -- AwaitUtxoSpentReq txOutRef -> pure $ AwaitUtxoSpentResp ChainIndexTx - -- AwaitUtxoProducedReq Address -> pure $ AwaitUtxoProducedResp (NonEmpty ChainIndexTx) - -- AwaitTxOutStatusChangeReq TxOutRef - -- ExposeEndpointReq ActiveEndpoint -> ExposeEndpointResp EndpointDescription (EndpointValue JSON.Value) - -- YieldUnbalancedTxReq UnbalancedTx - unsupported -> error ("Unsupported PAB effect: " ++ show unsupported) + AwaitUtxoSpentReq _ -> error ("Unsupported PAB effect: " ++ show req) + AwaitUtxoProducedReq _ -> error ("Unsupported PAB effect: " ++ show req) + AwaitTxOutStatusChangeReq _ -> error ("Unsupported PAB effect: " ++ show req) + ExposeEndpointReq _ -> error ("Unsupported PAB effect: " ++ show req) + YieldUnbalancedTxReq _ -> error ("Unsupported PAB effect: " ++ show req) + CurrentChainIndexSlotReq -> error ("Unsupported PAB effect: " ++ show req) printBpiLog @w (Debug [PABLog]) $ pretty resp pure resp +adjustUnbalancedTx' :: + forall (w :: Type) (effs :: [Type -> Type]). + Member (PABEffect w) effs => + UnbalancedTx -> + Eff effs (Either Tx.ToCardanoError UnbalancedTx) +adjustUnbalancedTx' unbalancedTx = runEitherT $ do + updatedOuts <- + firstEitherT (Tx.TxBodyError . show) $ + newEitherT $ + sequence <$> traverse (minUtxo @w) (unbalancedTx ^. tx . outputs) + + return $ unbalancedTx & (tx . outputs .~ updatedOuts) + {- | Await till transaction status change to something from `Unknown`. Uses `chain-index` to query transaction by id. Important notes: @@ -236,7 +262,13 @@ awaitTxStatusChange contractEnv txId = do cutOffBlock = checkStartedBlock + fromIntegral pollTimeout fix $ \loop -> do - currBlock <- currentBlock contractEnv + (currBlock, currSlot) <- currentTip contractEnv + + helperLog $ + "Current block: " ++ show currBlock + ++ ", current slot: " + ++ show currSlot + txStatus <- getStatus case (txStatus, currBlock > cutOffBlock) of (status, True) -> do @@ -272,12 +304,12 @@ awaitTxStatusChange contractEnv txId = do queryChainIndexForTxState = do mTx <- join . preview _TxIdResponse <$> (queryChainIndex @w $ TxFromTxId txId) case mTx of - Just tx -> do + Just tx' -> do blk <- fromInteger <$> currentBlock contractEnv - pure . Just $ fromTx blk tx + pure . Just $ fromTx blk tx' Nothing -> pure Nothing - helperLog = printBpiLog @w (Debug [CollateralLog]) . pretty + helperLog = printBpiLog @w (Debug [PABLog]) . pretty -- | This will FULLY balance a transaction balanceTx :: @@ -286,7 +318,8 @@ balanceTx :: ContractEnvironment w -> UnbalancedTx -> Eff effs BalanceTxResponse -balanceTx contractEnv unbalancedTx = do +balanceTx _ (UnbalancedTx (Left _) _ _ _) = pure $ BalanceTxFailed $ OtherError "CardanoBuildTx is not supported" +balanceTx contractEnv unbalancedTx@(UnbalancedTx (Right tx') _ _ _) = do let pabConf = contractEnv.cePABConfig result <- handleCollateral @w contractEnv @@ -298,13 +331,18 @@ balanceTx contractEnv unbalancedTx = do eitherBalancedTx <- Balance.balanceTxIO' @w Balance.defaultBalanceConfig - { Balance.bcHasScripts = Balance.txUsesScripts (unBalancedTxTx unbalancedTx) + { Balance.bcHasScripts = Balance.txUsesScripts tx' } pabConf pabConf.pcOwnPubKeyHash unbalancedTx - pure $ either (BalanceTxFailed . InsufficientFunds) (BalanceTxSuccess . Right) eitherBalancedTx + pure $ either (BalanceTxFailed . OtherError) (BalanceTxSuccess . EmulatorTx) eitherBalancedTx + +fromCardanoTx :: CardanoTx -> Tx.Tx +fromCardanoTx (CardanoApiTx _) = error "Cannot handle cardano api tx" +fromCardanoTx (EmulatorTx tx') = tx' +fromCardanoTx (Tx.Both tx' _) = tx' -- | This step would build tx files, write them to disk and submit them to the chain writeBalancedTx :: @@ -313,53 +351,53 @@ writeBalancedTx :: ContractEnvironment w -> CardanoTx -> Eff effs WriteBalancedTxResponse -writeBalancedTx _ (Left _) = error "Cannot handle cardano api tx" -writeBalancedTx contractEnv (Right tx) = do +writeBalancedTx contractEnv cardanoTx = do let pabConf = contractEnv.cePABConfig + tx' = fromCardanoTx cardanoTx uploadDir @w pabConf.pcSigningKeyFileDir createDirectoryIfMissing @w False (Text.unpack pabConf.pcScriptFileDir) - eitherT (pure . WriteBalancedTxFailed . OtherError) (pure . WriteBalancedTxSuccess . Left) $ do - void $ firstEitherT (Text.pack . show) $ newEitherT $ Files.writeAll @w pabConf tx + eitherT (pure . WriteBalancedTxFailed . OtherError) (pure . WriteBalancedTxSuccess . CardanoApiTx) $ do + void $ firstEitherT (Text.pack . show) $ newEitherT $ Files.writeAll @w pabConf tx' lift $ uploadDir @w pabConf.pcScriptFileDir privKeys <- newEitherT $ Files.readPrivateKeys @w pabConf - let requiredSigners = Map.keys $ tx ^. Tx.signatures + let requiredSigners = Map.keys $ tx' ^. Tx.signatures skeys = Map.filter (\case FromSKey _ -> True; FromVKey _ -> False) privKeys signable = all ((`Map.member` skeys) . Ledger.pubKeyHash) requiredSigners - void $ newEitherT $ BodyBuilder.buildAndEstimateBudget @w pabConf privKeys tx + void $ newEitherT $ BodyBuilder.buildAndEstimateBudget @w pabConf privKeys tx' -- TODO: This whole part is hacky and we should remove it. - let path = Text.unpack $ Files.txFilePath pabConf "raw" (Tx.txId tx) + let path = Text.unpack $ Files.txFilePath pabConf "raw" (Tx.txId tx') -- We read back the tx from file as tx currently has the wrong id (but the one we create with cardano-cli is correct) - alonzoBody <- firstEitherT (Text.pack . show) $ newEitherT $ readFileTextEnvelope @w (AsTxBody AsAlonzoEra) path - let cardanoTx = Tx.SomeTx (Tx alonzoBody []) AlonzoEraInCardanoMode + babbageBody <- firstEitherT (Text.pack . show) $ newEitherT $ readFileTextEnvelope @w (AsTxBody AsBabbageEra) path + let cardanoApiTx = Tx.SomeTx (Tx babbageBody []) BabbageEraInCardanoMode if signable - then newEitherT $ CardanoCLI.signTx @w pabConf tx requiredSigners + then newEitherT $ CardanoCLI.signTx @w pabConf tx' requiredSigners else lift . printBpiLog @w (Warn [PABLog]) . PP.vsep $ [ "Not all required signatures have signing key files. Please sign and submit the tx manually:" - , "Tx file:" <+> pretty (Files.txFilePath pabConf "raw" (Tx.txId tx)) + , "Tx file:" <+> pretty (Files.txFilePath pabConf "raw" (Tx.txId tx')) , "Signatories (pkh):" <+> pretty (Text.unwords (map pkhToText requiredSigners)) ] when (pabConf.pcCollectStats && signable) $ - collectBudgetStats (Tx.txId tx) pabConf + collectBudgetStats (Tx.txId tx') pabConf when (not pabConf.pcDryRun && signable) $ do - newEitherT $ CardanoCLI.submitTx @w pabConf tx + newEitherT $ CardanoCLI.submitTx @w pabConf tx' -- We need to replace the outfile we created at the previous step, as it currently still has the old (incorrect) id - let cardanoTxId = Ledger.getCardanoTxId $ Left cardanoTx - signedSrcPath = Files.txFilePath pabConf "signed" (Tx.txId tx) + let cardanoTxId = Ledger.getCardanoTxId $ Tx.CardanoApiTx cardanoApiTx + signedSrcPath = Files.txFilePath pabConf "signed" (Tx.txId tx') signedDstPath = Files.txFilePath pabConf "signed" cardanoTxId - mvFiles (Files.txFilePath pabConf "raw" (Tx.txId tx)) (Files.txFilePath pabConf "raw" cardanoTxId) + mvFiles (Files.txFilePath pabConf "raw" (Tx.txId tx')) (Files.txFilePath pabConf "raw" cardanoTxId) when signable $ mvFiles signedSrcPath signedDstPath - pure cardanoTx + pure cardanoApiTx where mvFiles :: Text -> Text -> EitherT Text (Eff effs) () mvFiles src dst = @@ -372,7 +410,7 @@ writeBalancedTx contractEnv (Right tx) = do } collectBudgetStats txId pabConf = do - let path = Text.unpack (Files.txFilePath pabConf "signed" (Tx.txId tx)) + let path = Text.unpack (Files.txFilePath pabConf "signed" txId) txBudget <- firstEitherT toBudgetSaveError $ newEitherT $ estimateBudget @w (Signed path) @@ -419,21 +457,32 @@ awaitTime ce pTime = do where rightOrErr = either (error . show) id +type Block = Integer + +currentTip :: + forall (w :: Type) (effs :: [Type -> Type]). + Member (PABEffect w) effs => + ContractEnvironment w -> + Eff effs (Block, Slot) +currentTip contractEnv = do + tip <- + either (error . Text.unpack) id + <$> CardanoCLI.queryTip @w contractEnv.cePABConfig + pure $ liftA2 (,) block (Slot . slot) tip + currentSlot :: forall (w :: Type) (effs :: [Type -> Type]). Member (PABEffect w) effs => ContractEnvironment w -> Eff effs Slot -currentSlot contractEnv = - Slot . slot . either (error . Text.unpack) id <$> CardanoCLI.queryTip @w contractEnv.cePABConfig +currentSlot = fmap snd . currentTip currentBlock :: forall (w :: Type) (effs :: [Type -> Type]). Member (PABEffect w) effs => ContractEnvironment w -> - Eff effs Integer -currentBlock contractEnv = - block . either (error . Text.unpack) id <$> CardanoCLI.queryTip @w contractEnv.cePABConfig + Eff effs Block +currentBlock = fmap fst . currentTip currentTime :: forall (w :: Type) (effs :: [Type -> Type]). @@ -454,6 +503,9 @@ handleCollateral :: handleCollateral cEnv = do result <- (fmap swapEither . runEitherT) $ do + let helperLog :: PP.Doc () -> ExceptT CollateralUtxo (Eff effs) () + helperLog msg = newEitherT $ Right <$> printBpiLog @w (Debug [CollateralLog]) msg + collateralNotInMem <- newEitherT $ maybeToLeft "Collateral UTxO not found in contract env." @@ -480,10 +532,6 @@ handleCollateral cEnv = do setInMemCollateral @w collteralUtxo >> Right <$> printBpiLog @w (Debug [CollateralLog]) "successfully set the collateral utxo in env." Left err -> pure $ Left $ "Failed to make collateral: " <> err - where - -- - helperLog :: PP.Doc () -> ExceptT CollateralUtxo (Eff effs) () - helperLog msg = newEitherT $ Right <$> printBpiLog @w (Debug [CollateralLog]) msg {- | Create collateral UTxO by submitting Tx. Then try to find created UTxO at own PKH address. @@ -498,7 +546,7 @@ makeCollateral cEnv = runEitherT $ do let pabConf = cEnv.cePABConfig unbalancedTx <- - firstEitherT (T.pack . show) $ + firstEitherT (Text.pack . show) $ hoistEither $ Collateral.mkCollateralTx pabConf balancedTx <- @@ -508,9 +556,9 @@ makeCollateral cEnv = runEitherT $ do pabConf pabConf.pcOwnPubKeyHash unbalancedTx - wbr <- lift $ writeBalancedTx cEnv (Right balancedTx) + wbr <- lift $ writeBalancedTx cEnv (EmulatorTx balancedTx) case wbr of - WriteBalancedTxFailed e -> throwE . T.pack $ "Failed to create collateral output: " <> show e + WriteBalancedTxFailed e -> throwE . Text.pack $ "Failed to create collateral output: " <> show e WriteBalancedTxSuccess cTx -> do status <- lift $ awaitTxStatusChange cEnv (getCardanoTxId cTx) lift $ printBpiLog @w (Notice [CollateralLog]) $ "Collateral Tx Status: " <> pretty status @@ -531,10 +579,18 @@ findCollateralAtOwnPKH cEnv = (PaymentPubKeyHash pabConf.pcOwnPubKeyHash) pabConf.pcOwnStakePubKeyHash - r <- newEitherT $ CardanoCLI.utxosAt @w pabConf changeAddr + r <- + firstEitherT (Text.pack . show) $ + newEitherT $ queryNode @w (UtxosAt changeAddr) let refsAndOuts = Map.toList $ Tx.toTxOut <$> r hoistEither $ case filter check refsAndOuts of [] -> Left "Couldn't find collateral UTxO" ((oref, _) : _) -> Right oref where check (_, txOut) = Tx.txOutValue txOut == collateralValue (cePABConfig cEnv) + +{- | Construct a 'NonEmpty' list from a single element. + Should be replaced by NonEmpty.singleton after updating to base 4.15 +-} +nonEmptySingleton :: a -> NonEmpty a +nonEmptySingleton = (:| []) diff --git a/src/BotPlutusInterface/Effects.hs b/src/BotPlutusInterface/Effects.hs index ff5a015e..21591129 100644 --- a/src/BotPlutusInterface/Effects.hs +++ b/src/BotPlutusInterface/Effects.hs @@ -30,8 +30,12 @@ module BotPlutusInterface.Effects ( posixTimeRangeToContainedSlotRange, getInMemCollateral, setInMemCollateral, + queryNode, + minUtxo, + calcMinUtxo, ) where +import BotPlutusInterface.CardanoNode.Effects (NodeQuery, runNodeQuery) import BotPlutusInterface.ChainIndex (handleChainIndexReq) import BotPlutusInterface.Collateral qualified as Collateral import BotPlutusInterface.ExBudget qualified as ExBudget @@ -40,13 +44,14 @@ import BotPlutusInterface.Types ( BudgetEstimationError, CLILocation (..), CollateralUtxo, - ContractEnvironment, + ContractEnvironment (..), ContractState (ContractState), LogContext (BpiLog, ContractLog), LogLevel (..), LogLine (..), LogType (..), LogsList (LogsList), + PABConfig (..), TxBudget, TxFile, addBudget, @@ -54,6 +59,12 @@ import BotPlutusInterface.Types ( ) import Cardano.Api (AsType, FileError (FileIOError), HasTextEnvelope, TextEnvelopeDescr, TextEnvelopeError) import Cardano.Api qualified +import Cardano.Api qualified as CApi +import Cardano.Api.Shelley qualified as CApi.S +import Cardano.Ledger.Shelley.API.Wallet ( + CLI (evaluateMinLovelaceOutput), + ) +import Cardano.Prelude (maybeToEither) import Control.Concurrent qualified as Concurrent import Control.Concurrent.STM (TVar, atomically, modifyTVar, modifyTVar') import Control.Lens ((^.)) @@ -66,12 +77,16 @@ import Data.Aeson (ToJSON) import Data.Aeson qualified as JSON import Data.Bifunctor (second) import Data.ByteString qualified as ByteString +import Data.Either.Combinators (mapLeft) import Data.Kind (Type) import Data.Maybe (catMaybes) import Data.String (IsString, fromString) import Data.Text (Text) import Data.Text qualified as Text import Ledger qualified +import Ledger.Ada qualified as Ada +import Ledger.Tx.CardanoAPI qualified as TxApi +import Ledger.Validation (Coin (Coin)) import Plutus.Contract.Effects (ChainIndexQuery, ChainIndexResponse) import Plutus.PAB.Core.ContractInstance.STM (Activity) import PlutusTx.Builtins.Internal (BuiltinByteString (BuiltinByteString)) @@ -117,6 +132,7 @@ data PABEffect (w :: Type) (r :: Type) where ListDirectory :: FilePath -> PABEffect w [FilePath] UploadDir :: Text -> PABEffect w () QueryChainIndex :: ChainIndexQuery -> PABEffect w ChainIndexResponse + QueryNode :: NodeQuery a -> PABEffect w a EstimateBudget :: TxFile -> PABEffect w (Either BudgetEstimationError TxBudget) SaveBudget :: Ledger.TxId -> TxBudget -> PABEffect w () SlotToPOSIXTime :: @@ -128,6 +144,7 @@ data PABEffect (w :: Type) (r :: Type) where PABEffect w (Either TimeSlot.TimeSlotConversionError Ledger.SlotRange) GetInMemCollateral :: PABEffect w (Maybe CollateralUtxo) SetInMemCollateral :: CollateralUtxo -> PABEffect w () + MinUtxo :: Ledger.TxOut -> PABEffect w (Either Text Ledger.TxOut) handlePABEffect :: forall (w :: Type) (effs :: [Type -> Type]). @@ -178,6 +195,7 @@ handlePABEffect contractEnv = void $ readProcess "scp" ["-r", Text.unpack dir, Text.unpack $ ipAddr <> ":$HOME"] "" QueryChainIndex query -> handleChainIndexReq contractEnv query + QueryNode query -> runNodeQuery contractEnv.cePABConfig (send query) EstimateBudget txPath -> ExBudget.estimateBudget contractEnv.cePABConfig txPath SaveBudget txId exBudget -> saveBudgetImpl contractEnv txId exBudget @@ -189,6 +207,7 @@ handlePABEffect contractEnv = TimeSlot.posixTimeRangeToContainedSlotRangeIO contractEnv.cePABConfig pTimeRange GetInMemCollateral -> Collateral.getInMemCollateral contractEnv SetInMemCollateral c -> Collateral.setInMemCollateral contractEnv c + MinUtxo utxo -> return $ calcMinUtxo contractEnv.cePABConfig utxo ) printLog' :: LogLevel -> LogLine -> IO () @@ -261,6 +280,27 @@ saveBudgetImpl contractEnv txId budget = atomically $ modifyTVar' contractEnv.ceContractStats (addBudget txId budget) +calcMinUtxo :: PABConfig -> Ledger.TxOut -> Either Text Ledger.TxOut +calcMinUtxo pabconf txout = do + params <- maybeToEither "Expected protocol parameters." $ pcProtocolParams pabconf + + let pparamsInEra = CApi.toLedgerPParams CApi.ShelleyBasedEraBabbage params + netId = pcNetwork pabconf + + ctxout <- + mapLeft (Text.pack . show) $ + TxApi.toCardanoTxOut netId TxApi.toCardanoTxOutDatumHash txout + + let (Coin minTxOut) = + evaluateMinLovelaceOutput pparamsInEra $ + CApi.S.toShelleyTxOut CApi.ShelleyBasedEraBabbage ctxout + + missingLovelace = Ada.lovelaceOf minTxOut - Ada.fromValue (Ledger.txOutValue txout) + + if missingLovelace > 0 + then calcMinUtxo pabconf (txout {Ledger.txOutValue = Ledger.txOutValue txout <> Ada.toValue missingLovelace}) + else return txout + -- Couldn't use the template haskell makeEffect here, because it caused an OverlappingInstances problem. -- For some reason, we need to manually propagate the @w@ type variable to @send@ @@ -419,3 +459,17 @@ setInMemCollateral :: CollateralUtxo -> Eff effs () setInMemCollateral = send @(PABEffect w) . SetInMemCollateral + +queryNode :: + forall (w :: Type) (a :: Type) (effs :: [Type -> Type]). + Member (PABEffect w) effs => + NodeQuery a -> + Eff effs a +queryNode = send @(PABEffect w) . QueryNode + +minUtxo :: + forall (w :: Type) (effs :: [Type -> Type]). + Member (PABEffect w) effs => + Ledger.TxOut -> + Eff effs (Either Text Ledger.TxOut) +minUtxo = send @(PABEffect w) . MinUtxo diff --git a/src/BotPlutusInterface/ExBudget.hs b/src/BotPlutusInterface/ExBudget.hs index 6f52d36e..7cae1861 100644 --- a/src/BotPlutusInterface/ExBudget.hs +++ b/src/BotPlutusInterface/ExBudget.hs @@ -3,29 +3,35 @@ module BotPlutusInterface.ExBudget ( estimateBudget, ) where -import BotPlutusInterface.QueryNode (NodeInfo (NodeInfo)) -import BotPlutusInterface.QueryNode qualified as QueryNode +import BotPlutusInterface.CardanoNode.Query ( + QueryConstraint, + connectionInfo, + queryBabbageEra, + queryInCardanoMode, + ) import BotPlutusInterface.Types ( BudgetEstimationError (..), MintBudgets, - PABConfig (pcNetwork), + PABConfig, SpendBudgets, TxBudget (TxBudget), TxFile (..), ) -import Cardano.Api qualified as CAPI +import Cardano.Api qualified as CApi import Cardano.Api.Shelley (ProtocolParameters (protocolParamMaxTxExUnits)) import Cardano.Prelude (maybeToEither) import Control.Arrow (left) +import Control.Monad.Freer (Eff, runM) +import Control.Monad.Freer.Reader (runReader) import Data.Either (rights) import Data.List (sort) import Data.Map (Map) import Data.Map qualified as Map +import Data.Set qualified as Set import Data.Text qualified as Text import GHC.Natural (Natural) import Ledger (ExBudget (ExBudget), ExCPU (ExCPU), ExMemory (ExMemory), MintingPolicyHash, TxOutRef) import Ledger.Tx.CardanoAPI (fromCardanoPolicyId, fromCardanoTxIn) -import System.Directory.Internal.Prelude (getEnv) import Prelude {- | Estimate budget of transaction. @@ -35,23 +41,27 @@ import Prelude -} estimateBudget :: PABConfig -> TxFile -> IO (Either BudgetEstimationError TxBudget) estimateBudget pabConf txFile = do - sock <- getEnv "CARDANO_NODE_SOCKET_PATH" - let debugNodeInf = NodeInfo (pcNetwork pabConf) sock txBody <- case txFile of Raw rp -> deserialiseRaw rp - Signed sp -> fmap CAPI.getTxBody <$> deserialiseSigned sp + Signed sp -> fmap CApi.getTxBody <$> deserialiseSigned sp budgetRes <- either (pure . Left) - (getExUnits debugNodeInf) + (getExUnits pabConf) txBody pure $ do body <- txBody budget <- budgetRes - maxUnits <- maybeToEither (BudgetEstimationError "Missing max units in parameters") $ protocolParamMaxTxExUnits pabConf.pcProtocolParams + pparams <- + maybeToEither + (BudgetEstimationError "No protocol params found") + pabConf.pcProtocolParams + maxUnits <- + maybeToEither (BudgetEstimationError "Missing max units in parameters") $ + protocolParamMaxTxExUnits pparams scaledBudget <- getScaledBudget maxUnits pabConf.pcBudgetMultiplier budget @@ -60,7 +70,7 @@ estimateBudget pabConf txFile = do Right $ TxBudget spendingBudgets policyBudgets -- | Scale the budget clamping the total to the parameter limits -getScaledBudget :: CAPI.ExecutionUnits -> Rational -> ExUnitsMap -> Either BudgetEstimationError ExUnitsMap +getScaledBudget :: CApi.ExecutionUnits -> Rational -> ExUnitsMap -> Either BudgetEstimationError ExUnitsMap getScaledBudget maxUnits scaler budget = if fst scalers >= 1 && snd scalers >= 1 then Right $ fmap (fmap $ scaleBudget scalers) budget @@ -70,10 +80,10 @@ getScaledBudget maxUnits scaler budget = Text.pack $ "Exceeded global transaction budget\nCalculated: " ++ show budgetSum ++ "\nLimit: " ++ show maxUnits where - budgetSum = foldr addBudgets (CAPI.ExecutionUnits 0 0) $ rights $ Map.elems budget + budgetSum = foldr addBudgets (CApi.ExecutionUnits 0 0) $ rights $ Map.elems budget scalers = - ( clampedScaler (CAPI.executionSteps budgetSum) (CAPI.executionSteps maxUnits) scaler - , clampedScaler (CAPI.executionMemory budgetSum) (CAPI.executionMemory maxUnits) scaler + ( clampedScaler (CApi.executionSteps budgetSum) (CApi.executionSteps maxUnits) scaler + , clampedScaler (CApi.executionMemory budgetSum) (CApi.executionMemory maxUnits) scaler ) clampedScaler :: Natural -> Natural -> Rational -> Rational @@ -81,69 +91,77 @@ clampedScaler 0 _ scaler = scaler clampedScaler val maxVal scaler = min scaler (toRational maxVal / toRational val) -- | Scale the budget by the multipliers in config -scaleBudget :: (Rational, Rational) -> CAPI.ExecutionUnits -> CAPI.ExecutionUnits -scaleBudget (stepsScaler, memScaler) (CAPI.ExecutionUnits steps mem) = CAPI.ExecutionUnits (scale steps stepsScaler) (scale mem memScaler) +scaleBudget :: (Rational, Rational) -> CApi.ExecutionUnits -> CApi.ExecutionUnits +scaleBudget (stepsScaler, memScaler) (CApi.ExecutionUnits steps mem) = CApi.ExecutionUnits (scale steps stepsScaler) (scale mem memScaler) where scale x scaler = round $ toRational x * scaler -addBudgets :: CAPI.ExecutionUnits -> CAPI.ExecutionUnits -> CAPI.ExecutionUnits -addBudgets (CAPI.ExecutionUnits steps mem) (CAPI.ExecutionUnits steps' mem') = CAPI.ExecutionUnits (steps + steps') (mem + mem') +addBudgets :: CApi.ExecutionUnits -> CApi.ExecutionUnits -> CApi.ExecutionUnits +addBudgets (CApi.ExecutionUnits steps mem) (CApi.ExecutionUnits steps' mem') = CApi.ExecutionUnits (steps + steps') (mem + mem') -- | Deserialize transaction body from ".signed" file -deserialiseSigned :: FilePath -> IO (Either BudgetEstimationError (CAPI.Tx CAPI.AlonzoEra)) +deserialiseSigned :: FilePath -> IO (Either BudgetEstimationError (CApi.Tx CApi.BabbageEra)) deserialiseSigned txFile = do envlp <- readEnvelope pure $ envlp >>= parseTx where readEnvelope = left toBudgetError - <$> CAPI.readTextEnvelopeFromFile txFile + <$> CApi.readTextEnvelopeFromFile txFile parseTx = left toBudgetError - . CAPI.deserialiseFromTextEnvelope CAPI.AsAlonzoTx + . CApi.deserialiseFromTextEnvelope (CApi.AsTx CApi.AsBabbageEra) -- | Deserialize transaction body from ".raw" file -deserialiseRaw :: FilePath -> IO (Either BudgetEstimationError (CAPI.TxBody CAPI.AlonzoEra)) +deserialiseRaw :: FilePath -> IO (Either BudgetEstimationError (CApi.TxBody CApi.BabbageEra)) deserialiseRaw txFile = do envlp <- readEnvelope pure $ envlp >>= parseTx where readEnvelope = left toBudgetError - <$> CAPI.readTextEnvelopeFromFile txFile + <$> CApi.readTextEnvelopeFromFile txFile parseTx = left toBudgetError - . CAPI.deserialiseFromTextEnvelope (CAPI.AsTxBody CAPI.AsAlonzoEra) + . CApi.deserialiseFromTextEnvelope (CApi.AsTxBody CApi.AsBabbageEra) -- | Shorthand alias type ExUnitsMap = - Map CAPI.ScriptWitnessIndex (Either CAPI.ScriptExecutionError CAPI.ExecutionUnits) + Map CApi.ScriptWitnessIndex (Either CApi.ScriptExecutionError CApi.ExecutionUnits) -- | Calculate execution units using `Cardano.Api`` getExUnits :: - NodeInfo -> - CAPI.TxBody CAPI.AlonzoEra -> + PABConfig -> + CApi.TxBody CApi.BabbageEra -> IO (Either BudgetEstimationError ExUnitsMap) -getExUnits nodeInf txBody = do - sysStart <- QueryNode.querySystemStart nodeInf - eraHist <- QueryNode.queryEraHistory nodeInf - pparams <- QueryNode.queryProtocolParams nodeInf - utxo <- QueryNode.queryOutsByInputs nodeInf capiIns +getExUnits pabConf txBody = do + conn <- connectionInfo pabConf + runM $ runReader conn (getExUnits' txBody) + +getExUnits' :: + QueryConstraint effs => + CApi.TxBody CApi.BabbageEra -> + Eff effs (Either BudgetEstimationError ExUnitsMap) +getExUnits' txBody = do + sysStart <- queryInCardanoMode CApi.QuerySystemStart + eraHistory <- queryInCardanoMode (CApi.QueryEraHistory CApi.CardanoModeIsMultiEra) + pparams <- queryBabbageEra CApi.QueryProtocolParameters + utxo <- queryBabbageEra $ CApi.QueryUTxO (CApi.QueryUTxOByTxIn $ Set.fromList capiIns) pure $ flattenEvalResult $ - CAPI.evaluateTransactionExecutionUnits CAPI.AlonzoEraInCardanoMode + CApi.evaluateTransactionExecutionUnits CApi.BabbageEraInCardanoMode <$> sysStart - <*> eraHist + <*> eraHistory <*> pparams <*> utxo <*> pure txBody where - capiIns :: [CAPI.TxIn] + capiIns :: [CApi.TxIn] capiIns = - let (CAPI.TxBody txbc) = txBody - in fst <$> CAPI.txIns txbc + let (CApi.TxBody txbc) = txBody + in fst <$> CApi.txIns txbc flattenEvalResult = \case Right (Right res) -> Right res @@ -154,10 +172,10 @@ getExUnits nodeInf txBody = do -} mkBudgetMaps :: ExUnitsMap -> - CAPI.TxBody CAPI.AlonzoEra -> + CApi.TxBody CApi.BabbageEra -> Either BudgetEstimationError (SpendBudgets, MintBudgets) mkBudgetMaps exUnitsMap txBody = do - let (CAPI.TxBody txbc) = txBody + let (CApi.TxBody txbc) = txBody insIx = mkInputsIndex txbc policiesIx = mkPoliciesIndex txbc @@ -182,19 +200,19 @@ mkBudgetMaps exUnitsMap txBody = do -} . sort . map fst -- get only `TxIn`'s from `TxIns` (which is list of tuples) - . CAPI.txIns + . CApi.txIns mkPoliciesIndex txbc = - case CAPI.txMintValue txbc of - CAPI.TxMintValue _ value _ -> + case CApi.txMintValue txbc of + CApi.TxMintValue _ value _ -> {- The minting policies are indexed in policy id order in the value reference: https://github.com/input-output-hk/cardano-node/blob/e31455eaeca98530ce561b79687a8e465ebb3fdd/cardano-api/src/Cardano/Api/TxBody.hs#L2881 -} - let CAPI.ValueNestedRep bundle = CAPI.valueToNestedRep value + let CApi.ValueNestedRep bundle = CApi.valueToNestedRep value in Map.fromList [ (ix, policyId) - | (ix, CAPI.ValueNestedBundle policyId _) <- zip [0 ..] bundle + | (ix, CApi.ValueNestedBundle policyId _) <- zip [0 ..] bundle ] _ -> mempty @@ -204,28 +222,28 @@ mkBudgetMaps exUnitsMap txBody = do and map to corresponding `TxOutRef` or `MintingPolicyHash` -} f :: - Map Integer CAPI.TxIn -> - Map Integer CAPI.PolicyId -> - (CAPI.ScriptWitnessIndex, CAPI.ExecutionUnits) -> + Map Integer CApi.TxIn -> + Map Integer CApi.PolicyId -> + (CApi.ScriptWitnessIndex, CApi.ExecutionUnits) -> Either BudgetEstimationError (Map TxOutRef ExBudget, Map MintingPolicyHash ExBudget) f insIx policiesIx budgetItem - | (CAPI.ScriptWitnessIndexTxIn ix, eu) <- budgetItem = + | (CApi.ScriptWitnessIndexTxIn ix, eu) <- budgetItem = case Map.lookup (toInteger ix) insIx of - Nothing -> Left $ BudgetNotFound (CAPI.ScriptWitnessIndexTxIn ix) + Nothing -> Left $ BudgetNotFound (CApi.ScriptWitnessIndexTxIn ix) Just inp -> Right . (,mempty) $ Map.singleton (fromCardanoTxIn inp) (unitsToBudget eu) - | (CAPI.ScriptWitnessIndexMint ix, eu) <- budgetItem = + | (CApi.ScriptWitnessIndexMint ix, eu) <- budgetItem = case Map.lookup (toInteger ix) policiesIx of - Nothing -> Left $ BudgetNotFound (CAPI.ScriptWitnessIndexTxIn ix) + Nothing -> Left $ BudgetNotFound (CApi.ScriptWitnessIndexTxIn ix) Just pId -> Right . (mempty,) $ Map.singleton (fromCardanoPolicyId pId) (unitsToBudget eu) | otherwise = Right mempty -- | Cardano to Plutus budget converter -unitsToBudget :: CAPI.ExecutionUnits -> ExBudget -unitsToBudget (CAPI.ExecutionUnits cpu mem) = +unitsToBudget :: CApi.ExecutionUnits -> ExBudget +unitsToBudget (CApi.ExecutionUnits cpu mem) = ExBudget (ExCPU $ cast cpu) (ExMemory $ cast mem) where cast = fromInteger . toInteger diff --git a/src/BotPlutusInterface/Files.hs b/src/BotPlutusInterface/Files.hs index 31705fb5..8a33f636 100644 --- a/src/BotPlutusInterface/Files.hs +++ b/src/BotPlutusInterface/Files.hs @@ -10,7 +10,8 @@ module BotPlutusInterface.Files ( txFilePath, txFileName, txIdToText, - metadataFilePath, + -- TODO: Removed for now, as the main iohk branch doesn't support metadata yet + -- metadataFilePath, writeAll, writePolicyScriptFile, redeemerJsonFilePath, @@ -29,7 +30,6 @@ import BotPlutusInterface.Effects ( listDirectory, readFileTextEnvelope, writeFileJSON, - writeFileRaw, writeFileTextEnvelope, ) import BotPlutusInterface.Types (PABConfig) @@ -50,30 +50,28 @@ import Cardano.Api.Shelley ( scriptDataToJson, ) import Cardano.Crypto.Wallet qualified as Crypto -import Cardano.Prelude ((<<$>>)) import Codec.Serialise qualified as Codec import Control.Monad.Freer (Eff, Member) import Data.Aeson qualified as JSON import Data.Aeson.Extras (encodeByteString) import Data.ByteString qualified as ByteString -import Data.ByteString.Hash (blake2b) import Data.ByteString.Lazy qualified as LazyByteString import Data.ByteString.Short qualified as ShortByteString import Data.Either.Combinators (mapLeft) import Data.Kind (Type) -import Data.List (sortOn) +import Data.List (sortOn, unzip4) import Data.Map (Map) import Data.Map qualified as Map -import Data.Maybe (catMaybes, mapMaybe, maybeToList) -import Data.Set qualified as Set +import Data.Maybe (catMaybes, mapMaybe) import Data.Text (Text) import Data.Text qualified as Text -import Ledger qualified -import Ledger.Crypto (PrivateKey, PubKey (PubKey), PubKeyHash (PubKeyHash)) +import Ledger.Crypto (PubKey (PubKey), PubKeyHash (PubKeyHash)) +import Ledger.Crypto qualified as Crypto import Ledger.Tx (Tx) import Ledger.Tx qualified as Tx -import Ledger.TxId qualified as TxId import Ledger.Value qualified as Value +import Plutus.Script.Utils.Scripts qualified as ScriptUtils +import Plutus.Script.Utils.V1.Scripts qualified as ScriptUtils import Plutus.V1.Ledger.Api ( CurrencySymbol, Datum (getDatum), @@ -87,9 +85,9 @@ import Plutus.V1.Ledger.Api ( ValidatorHash (..), toBuiltin, ) +import Plutus.V1.Ledger.Api qualified as Ledger import PlutusTx (ToData, toData) import PlutusTx.Builtins (fromBuiltin) -import PlutusTx.Builtins.Internal (BuiltinByteString (BuiltinByteString)) import System.FilePath (takeExtension, ()) import Prelude @@ -120,20 +118,23 @@ signingKeyFilePath pabConf (PubKeyHash pubKeyHash) = let h = encodeByteString $ fromBuiltin pubKeyHash in pabConf.pcSigningKeyFileDir <> "/signing-key-" <> h <> ".skey" -txFilePath :: PABConfig -> Text -> TxId.TxId -> Text +txFilePath :: PABConfig -> Text -> Tx.TxId -> Text txFilePath pabConf ext txId = pabConf.pcTxFileDir <> "/" <> txFileName txId ext -txFileName :: TxId.TxId -> Text -> Text +txFileName :: Tx.TxId -> Text -> Text txFileName txId ext = "tx-" <> txIdToText txId <> "." <> ext -txIdToText :: TxId.TxId -> Text -txIdToText = encodeByteString . fromBuiltin . TxId.getTxId +txIdToText :: Tx.TxId -> Text +txIdToText = encodeByteString . fromBuiltin . Tx.getTxId --- | Path of stored metadata files -metadataFilePath :: PABConfig -> BuiltinByteString -> Text -metadataFilePath pabConf (BuiltinByteString meta) = - let h = encodeByteString $ blake2b meta - in pabConf.pcMetadataDir <> "/metadata-" <> h <> ".json" +-- TODO: Removed for now, as the main iohk branch doesn't support metadata yet + +{- | Path of stored metadata files + metadataFilePath :: PABConfig -> BuiltinByteString -> Text + metadataFilePath pabConf (BuiltinByteString meta) = + let h = encodeByteString $ blake2b meta + in pabConf.pcMetadataDir <> "/metadata-" <> h <> ".json" +-} -- | Compiles and writes a script file under the given folder writePolicyScriptFile :: @@ -144,7 +145,7 @@ writePolicyScriptFile :: Eff effs (Either (FileError ()) Text) writePolicyScriptFile pabConf mintingPolicy = let script = serialiseScript $ Ledger.unMintingPolicyScript mintingPolicy - filepath = policyScriptFilePath pabConf (Ledger.scriptCurrencySymbol mintingPolicy) + filepath = policyScriptFilePath pabConf (ScriptUtils.scriptCurrencySymbol mintingPolicy) in fmap (const filepath) <$> writeFileTextEnvelope @w (Text.unpack filepath) Nothing script -- | Compiles and writes a script file under the given folder @@ -156,19 +157,20 @@ writeValidatorScriptFile :: Eff effs (Either (FileError ()) Text) writeValidatorScriptFile pabConf validatorScript = let script = serialiseScript $ Ledger.unValidatorScript validatorScript - filepath = validatorScriptFilePath pabConf (Ledger.validatorHash validatorScript) + filepath = validatorScriptFilePath pabConf (ScriptUtils.validatorHash validatorScript) in fmap (const filepath) <$> writeFileTextEnvelope @w (Text.unpack filepath) Nothing script --- | Writes metadata file under the given folder -writeMetadataFile :: - forall (w :: Type) (effs :: [Type -> Type]). - Member (PABEffect w) effs => - PABConfig -> - BuiltinByteString -> - Eff effs (Either (FileError ()) Text) -writeMetadataFile pabConf metadata = - let filepath = metadataFilePath pabConf metadata - in const filepath <<$>> writeFileRaw @w (Text.unpack filepath) metadata +-- TODO: Removed for now, as the main iohk branch doesn't support metadata yet +-- -- | Writes metadata file under the given folder +-- writeMetadataFile :: +-- forall (w :: Type) (effs :: [Type -> Type]). +-- Member (PABEffect w) effs => +-- PABConfig -> +-- BuiltinByteString -> +-- Eff effs (Either (FileError ()) Text) +-- writeMetadataFile pabConf metadata = +-- let filepath = metadataFilePath pabConf metadata +-- in const filepath <<$>> writeFileRaw @w (Text.unpack filepath) metadata -- | Write to disk all validator scripts, datums and redemeers appearing in the tx writeAll :: @@ -179,12 +181,13 @@ writeAll :: Eff effs (Either (FileError ()) [Text]) writeAll pabConf tx = do createDirectoryIfMissing @w False (Text.unpack pabConf.pcScriptFileDir) - createDirectoryIfMissing @w False (Text.unpack pabConf.pcMetadataDir) + -- TODO: Removed for now, as the main iohk branch doesn't support metadata yet + -- createDirectoryIfMissing @w False (Text.unpack pabConf.pcMetadataDir) - let (validatorScripts, redeemers, datums) = - unzip3 $ mapMaybe Tx.inScripts $ Set.toList $ Tx.txInputs tx + let (_, validatorScripts, redeemers, datums) = + unzip4 $ mapMaybe Tx.inScripts $ Tx.txInputs tx - policyScripts = Set.toList $ Ledger.txMintScripts tx + policyScripts = Map.elems $ Tx.txMintScripts tx allDatums = datums <> Map.elems (Tx.txData tx) allRedeemers = redeemers <> Map.elems (Tx.txRedeemers tx) @@ -195,7 +198,8 @@ writeAll pabConf tx = do , map (writeValidatorScriptFile @w pabConf) validatorScripts , map (writeDatumJsonFile @w pabConf) allDatums , map (writeRedeemerJsonFile @w pabConf) allRedeemers - , map (writeMetadataFile @w pabConf) (maybeToList $ Tx.txMetadata tx) + -- TODO: Removed for now, as the main iohk branch doesn't support metadata yet + -- , map (writeMetadataFile @w pabConf) (maybeToList $ Tx.txMetadata tx) ] pure $ sequence results @@ -226,7 +230,7 @@ readPrivateKeys pabConf = do toPrivKeyMap = foldl ( \pKeyMap pKey -> - let pkh = Ledger.pubKeyHash $ Ledger.toPublicKey $ unDummyPrivateKey pKey + let pkh = Crypto.pubKeyHash $ Crypto.toPublicKey $ unDummyPrivateKey pKey in Map.insert pkh pKey pKeyMap ) Map.empty @@ -237,10 +241,10 @@ readPrivateKeys pabConf = do keyPriority (FromVKey _) = 0 data DummyPrivKey - = FromSKey PrivateKey - | FromVKey PrivateKey + = FromSKey Crypto.XPrv + | FromVKey Crypto.XPrv -unDummyPrivateKey :: DummyPrivKey -> PrivateKey +unDummyPrivateKey :: DummyPrivKey -> Crypto.XPrv unDummyPrivateKey (FromSKey key) = key unDummyPrivateKey (FromVKey key) = key @@ -277,11 +281,11 @@ skeyToDummyPrivKey = This key's sole purpose is to be able to derive a public key from it, which is then used for mapping to a signing key file for the CLI -} -vkeyToDummyPrivKey' :: VerificationKey PaymentKey -> Either Text PrivateKey +vkeyToDummyPrivKey' :: VerificationKey PaymentKey -> Either Text Crypto.XPrv vkeyToDummyPrivKey' = mkDummyPrivateKey . PubKey . LedgerBytes . toBuiltin . serialiseToRawBytes -mkDummyPrivateKey :: PubKey -> Either Text PrivateKey +mkDummyPrivateKey :: PubKey -> Either Text Crypto.XPrv mkDummyPrivateKey (PubKey (LedgerBytes pubkey)) = let dummyPrivKey = ByteString.replicate 32 0 dummyPrivKeySuffix = ByteString.replicate 32 0 @@ -306,7 +310,7 @@ writeDatumJsonFile :: Eff effs (Either (FileError ()) Text) writeDatumJsonFile pabConf datum = let json = dataToJson $ getDatum datum - filepath = datumJsonFilePath pabConf (Ledger.datumHash datum) + filepath = datumJsonFilePath pabConf (ScriptUtils.datumHash datum) in fmap (const filepath) <$> writeFileJSON @w (Text.unpack filepath) json writeRedeemerJsonFile :: @@ -317,7 +321,7 @@ writeRedeemerJsonFile :: Eff effs (Either (FileError ()) Text) writeRedeemerJsonFile pabConf redeemer = let json = dataToJson $ getRedeemer redeemer - filepath = redeemerJsonFilePath pabConf (Ledger.redeemerHash redeemer) + filepath = redeemerJsonFilePath pabConf (ScriptUtils.redeemerHash redeemer) in fmap (const filepath) <$> writeFileJSON @w (Text.unpack filepath) json dataToJson :: forall (a :: Type). ToData a => a -> JSON.Value diff --git a/src/BotPlutusInterface/QueryNode.hs b/src/BotPlutusInterface/QueryNode.hs deleted file mode 100644 index 5429458c..00000000 --- a/src/BotPlutusInterface/QueryNode.hs +++ /dev/null @@ -1,92 +0,0 @@ -{-# LANGUAGE ViewPatterns #-} - --- | Several query functions to query local node -module BotPlutusInterface.QueryNode ( - NodeInfo (..), - NodeQueryError (..), - queryProtocolParams, - querySystemStart, - queryEraHistory, - queryOutsByInputs, -) where - -import Cardano.Api qualified as C -import Cardano.Api.ProtocolParameters (ProtocolParameters) -import Cardano.Slotting.Time (SystemStart) -import Control.Arrow (left) -import Data.Set qualified as Set -import Data.Text (Text, pack) -import Prelude - -{- | Error returned in case any error happened querying local node - (wraps whatever received in `Text`) --} -data NodeQueryError - = NodeQueryError Text - deriving stock (Eq, Show) - -data NodeInfo = NodeInfo - { niNetworkId :: C.NetworkId - , niSocket :: FilePath - } - -queryProtocolParams :: NodeInfo -> IO (Either NodeQueryError ProtocolParameters) -queryProtocolParams (connectionInfo -> cInfo) = - flattenQueryResult <$> C.queryNodeLocalState cInfo Nothing query - where - query = - C.QueryInEra C.AlonzoEraInCardanoMode $ - C.QueryInShelleyBasedEra C.ShelleyBasedEraAlonzo C.QueryProtocolParameters - -querySystemStart :: NodeInfo -> IO (Either NodeQueryError SystemStart) -querySystemStart (connectionInfo -> cInfo) = - left toQueryError - <$> C.queryNodeLocalState - cInfo - Nothing - C.QuerySystemStart - -queryEraHistory :: NodeInfo -> IO (Either NodeQueryError (C.EraHistory C.CardanoMode)) -queryEraHistory (connectionInfo -> cInfo) = - left toQueryError - <$> C.queryNodeLocalState - cInfo - Nothing - (C.QueryEraHistory C.CardanoModeIsMultiEra) - -queryOutsByInputs :: NodeInfo -> [C.TxIn] -> IO (Either NodeQueryError (C.UTxO C.AlonzoEra)) -queryOutsByInputs (connectionInfo -> cInfo) ins = - flattenQueryResult - <$> C.queryNodeLocalState - cInfo - Nothing - query - where - query = - C.QueryInEra C.AlonzoEraInCardanoMode $ - C.QueryInShelleyBasedEra C.ShelleyBasedEraAlonzo $ - C.QueryUTxO (C.QueryUTxOByTxIn (Set.fromList ins)) - -flattenQueryResult :: - (Show e1, Show e2, Show b) => - Either e1 (Either e2 b) -> - Either NodeQueryError b -flattenQueryResult = \case - Right (Right res) -> Right res - err -> Left $ NodeQueryError (pack $ show err) - -connectionInfo :: NodeInfo -> C.LocalNodeConnectInfo C.CardanoMode -connectionInfo (NodeInfo netId socket) = - C.LocalNodeConnectInfo - (C.CardanoModeParams epochSlots) - netId - socket - where - -- This parameter needed only for the Byron era. Since the Byron - -- era is over and the parameter has never changed it is ok to - -- hardcode this. See comment on `Cardano.Api.ConsensusModeParams` in - -- cardano-node. - epochSlots = C.EpochSlots 21600 - -toQueryError :: Show e => e -> NodeQueryError -toQueryError = NodeQueryError . pack . show diff --git a/src/BotPlutusInterface/Server.hs b/src/BotPlutusInterface/Server.hs index cc3f6889..6bddfc9b 100644 --- a/src/BotPlutusInterface/Server.hs +++ b/src/BotPlutusInterface/Server.hs @@ -39,7 +39,7 @@ import Data.String (fromString) import Data.Text (Text, pack, unpack) import Data.Text.Encoding (encodeUtf8) import Data.UUID.V4 qualified as UUID -import Ledger.TxId (TxId (TxId)) +import Ledger.Tx (TxId (TxId)) import Network.WebSockets ( Connection, PendingConnection, diff --git a/src/BotPlutusInterface/TimeSlot.hs b/src/BotPlutusInterface/TimeSlot.hs index 41b2ddff..a0b38935 100644 --- a/src/BotPlutusInterface/TimeSlot.hs +++ b/src/BotPlutusInterface/TimeSlot.hs @@ -11,27 +11,28 @@ module BotPlutusInterface.TimeSlot ( posixTimeRangeToContainedSlotRangeIO, ) where -import BotPlutusInterface.QueryNode ( - NodeInfo (NodeInfo), - queryEraHistory, - querySystemStart, +import BotPlutusInterface.CardanoNode.Query ( + QueryConstraint, + connectionInfo, + queryBabbageEra, + queryInCardanoMode, ) import BotPlutusInterface.Types ( PABConfig, - pcNetwork, - pcProtocolParams, ) import Cardano.Api (CardanoMode, EraHistory) -import Cardano.Api qualified as CAPI -import Cardano.Ledger.Alonzo (AlonzoEra) -import Cardano.Ledger.Alonzo.PParams (PParams, _protocolVersion) +import Cardano.Api qualified as CApi +import Control.Monad.Freer (Eff, runM) +import Control.Monad.Freer.Reader (runReader) + import Cardano.Ledger.Alonzo.TxInfo (slotToPOSIXTime) +import Cardano.Ledger.Babbage (BabbageEra) +import Cardano.Ledger.Babbage.PParams (PParams, _protocolVersion) import Cardano.Ledger.Crypto (StandardCrypto) import Cardano.Ledger.Slot (EpochInfo) import Cardano.Slotting.EpochInfo (hoistEpochInfo) import Cardano.Slotting.Time (SystemStart, toRelativeTime) import Control.Monad.Except (runExcept) -import Control.Monad.IO.Class (liftIO) import Control.Monad.Trans.Either ( EitherT, firstEitherT, @@ -53,7 +54,6 @@ import Ledger ( import Ledger qualified import Ouroboros.Consensus.HardFork.History qualified as Consensus import Ouroboros.Consensus.HardFork.History.Qry qualified as HF -import System.Environment (getEnv) import Prelude -- | Error returned by the functions of this module @@ -65,57 +65,69 @@ data TimeSlotConversionError -- | Convert `Slot` to `POSIXTime`. slotToPOSIXTimeIO :: PABConfig -> Ledger.Slot -> IO (Either TimeSlotConversionError Ledger.POSIXTime) -slotToPOSIXTimeIO pabConf lSlot = runEitherT $ do - nodeInfo <- liftIO $ mkNodeInfo pabConf - eraHistory <- newET (queryEraHistory nodeInfo) - sysStart <- newET $ querySystemStart nodeInfo +slotToPOSIXTimeIO pabConf slot = do + conn <- connectionInfo pabConf + runM $ runReader conn (slotToPOSIXTimeIO' slot) + +slotToPOSIXTimeIO' :: + QueryConstraint effs => + Ledger.Slot -> + Eff effs (Either TimeSlotConversionError Ledger.POSIXTime) +slotToPOSIXTimeIO' slot = runEitherT $ do + sysStart <- newET $ queryInCardanoMode CApi.QuerySystemStart + eraHistory <- newET $ queryInCardanoMode (CApi.QueryEraHistory CApi.CardanoModeIsMultiEra) + pparams <- newET $ queryBabbageEra CApi.QueryProtocolParameters let epochInfo = toLedgerEpochInfo eraHistory - pparams = - CAPI.toLedgerPParams - CAPI.ShelleyBasedEraAlonzo - (pcProtocolParams pabConf) + pparamsInEra = CApi.toLedgerPParams CApi.ShelleyBasedEraBabbage pparams firstEitherT toError . hoistEither $ - slotToPOSIXTime pparams epochInfo sysStart (toSlotNo lSlot) + slotToPOSIXTime pparamsInEra epochInfo sysStart (toSlotNo slot) -- | Convert `POSIXTime` to `Slot`. +posixTimeToSlotIO :: PABConfig -> Ledger.POSIXTime -> IO (Either TimeSlotConversionError Ledger.Slot) +posixTimeToSlotIO pabConf pTime = do + conn <- connectionInfo pabConf + runM $ runReader conn (posixTimeToSlot' pTime) --- Analogous to `posixTimeToEnclosingSlot` from plutus-ledger -posixTimeToSlotIO :: - PABConfig -> +posixTimeToSlot' :: + QueryConstraint effs => Ledger.POSIXTime -> - IO (Either TimeSlotConversionError Ledger.Slot) -posixTimeToSlotIO pabConf pTime = runEitherT $ do - nodeInfo <- liftIO $ mkNodeInfo pabConf - eraHist <- newET (queryEraHistory nodeInfo) - sysStart <- newET $ querySystemStart nodeInfo + Eff effs (Either TimeSlotConversionError Ledger.Slot) +posixTimeToSlot' pTime = runEitherT $ do + sysStart <- newET $ queryInCardanoMode CApi.QuerySystemStart + eraHistory <- newET $ queryInCardanoMode (CApi.QueryEraHistory CApi.CardanoModeIsMultiEra) firstEitherT toError . hoistEither $ - posixTimeToSlot sysStart eraHist pTime + posixTimeToSlot sysStart eraHistory pTime + +posixTimeRangeToContainedSlotRangeIO :: + PABConfig -> Ledger.POSIXTimeRange -> IO (Either TimeSlotConversionError Ledger.SlotRange) +posixTimeRangeToContainedSlotRangeIO pabConf ptr = do + conn <- connectionInfo pabConf + runM $ runReader conn (posixTimeRangeToContainedSlotRange' ptr) {- | Convert a `POSIXTimeRange` to `SlotRange`. Gives the biggest slot range that is entirely contained by the given time range. -} -- Analogous to `posixTimeRangeToContainedSlotRange` from plutus-ledger -posixTimeRangeToContainedSlotRangeIO :: - PABConfig -> +posixTimeRangeToContainedSlotRange' :: + QueryConstraint effs => Ledger.POSIXTimeRange -> - IO (Either TimeSlotConversionError Ledger.SlotRange) -posixTimeRangeToContainedSlotRangeIO - pabConf + Eff effs (Either TimeSlotConversionError Ledger.SlotRange) +posixTimeRangeToContainedSlotRange' ptr@(Interval (LowerBound start startIncl) (UpperBound end endIncl)) = runEitherT $ do -- getting required info from node - nodeInfo <- liftIO $ mkNodeInfo pabConf - sysStart <- newET $ querySystemStart nodeInfo - eraHistory <- newET $ queryEraHistory nodeInfo + + sysStart <- newET $ queryInCardanoMode CApi.QuerySystemStart + eraHistory <- newET $ queryInCardanoMode (CApi.QueryEraHistory CApi.CardanoModeIsMultiEra) + let epochInfo = toLedgerEpochInfo eraHistory - pparams = - CAPI.toLedgerPParams - CAPI.ShelleyBasedEraAlonzo - (pcProtocolParams pabConf) - let extTimeToExtSlot = convertExtended sysStart eraHistory - getClosure = getExtClosure pparams epochInfo sysStart + pparams <- newET $ queryBabbageEra CApi.QueryProtocolParameters + + let pparamsInEra = CApi.toLedgerPParams CApi.ShelleyBasedEraBabbage pparams + extTimeToExtSlot = convertExtended sysStart eraHistory + getClosure = getExtClosure pparamsInEra epochInfo sysStart -- conversions startSlot <- extTimeToExtSlot start @@ -152,12 +164,13 @@ posixTimeRangeToContainedSlotRangeIO -- if bound is not `NegInf` or `PosInf`, then `Closure` need to be calculated -- https://github.com/input-output-hk/plutus-apps/blob/e51f57fa99f4cc0942ba6476b0689e43f0948eb3/plutus-ledger/src/Ledger/TimeSlot.hs#L125-L130 getExtClosure :: - PParams (AlonzoEra StandardCrypto) -> - EpochInfo (Either CAPI.TransactionValidityError) -> + Monad m => + PParams (BabbageEra StandardCrypto) -> + EpochInfo (Either Text) -> SystemStart -> Extended Ledger.Slot -> Bool -> -- current `Closure` of lower or upper bound of `Ledger.POSIXTimeRange` - EitherT TimeSlotConversionError IO Bool + EitherT TimeSlotConversionError m Bool getExtClosure pparams epochInfo sysStart exSlot currentClosure = firstEitherT toError . hoistEither $ case exSlot of @@ -176,7 +189,7 @@ posixTimeToSlot :: posixTimeToSlot sysStart eraHist pTime = do -- toRelativeTime checks that pTime >= sysStart via `Control.Exception.assert` let relativeTime = toRelativeTime sysStart (toUtc pTime) - (CAPI.EraHistory _ int) = eraHist + (CApi.EraHistory _ int) = eraHist query = HF.wallclockToSlot relativeTime (sn, _, _) <- HF.interpretQuery int query @@ -191,15 +204,15 @@ posixTimeToSlot sysStart eraHist pTime = do -- helper functions -- -- | Ledger Slot to "Cardano.Api" Slot conversion -toSlotNo :: Ledger.Slot -> CAPI.SlotNo -toSlotNo (Ledger.Slot s) = CAPI.SlotNo $ fromInteger s +toSlotNo :: Ledger.Slot -> CApi.SlotNo +toSlotNo (Ledger.Slot s) = CApi.SlotNo $ fromInteger s -- | Cardano.Api Slot to Ledger Slot conversion -fromSlotNo :: CAPI.SlotNo -> Ledger.Slot -fromSlotNo (CAPI.SlotNo s) = Ledger.Slot (toInteger s) +fromSlotNo :: CApi.SlotNo -> Ledger.Slot +fromSlotNo (CApi.SlotNo s) = Ledger.Slot (toInteger s) -- helpler to lift IO to EitherT with desired `TimeSlotConversionError` error type -newET :: Show e => IO (Either e a) -> EitherT TimeSlotConversionError IO a +newET :: (Show e, Monad m) => m (Either e a) -> EitherT TimeSlotConversionError m a newET = firstEitherT toError . newEitherT toError :: Show e => e -> TimeSlotConversionError @@ -210,13 +223,8 @@ toError = TimeSlotConversionError . Text.pack . show -- | Get Ledger `EpochInfo` from "Cardano.Api" `EraHistory`. toLedgerEpochInfo :: - CAPI.EraHistory mode -> - EpochInfo (Either CAPI.TransactionValidityError) -toLedgerEpochInfo (CAPI.EraHistory _ interpreter) = - hoistEpochInfo (first CAPI.TransactionValidityIntervalError . runExcept) $ + CApi.EraHistory mode -> + EpochInfo (Either Text) +toLedgerEpochInfo (CApi.EraHistory _ interpreter) = + hoistEpochInfo (first (Text.pack . show) . runExcept) $ Consensus.interpreterToEpochInfo interpreter - -mkNodeInfo :: PABConfig -> IO NodeInfo -mkNodeInfo pabConf = - NodeInfo (pcNetwork pabConf) - <$> getEnv "CARDANO_NODE_SOCKET_PATH" diff --git a/src/BotPlutusInterface/Types.hs b/src/BotPlutusInterface/Types.hs index 1f905255..2c3e7f27 100644 --- a/src/BotPlutusInterface/Types.hs +++ b/src/BotPlutusInterface/Types.hs @@ -36,7 +36,7 @@ module BotPlutusInterface.Types ( ) where import Cardano.Api (NetworkId (Testnet), NetworkMagic (..), ScriptExecutionError, ScriptWitnessIndex) -import Cardano.Api.ProtocolParameters (ProtocolParameters) +import Cardano.Api.Shelley (ProtocolParameters) import Control.Concurrent.STM (TVar, readTVarIO) import Data.Aeson (ToJSON) import Data.Aeson qualified as JSON @@ -58,6 +58,7 @@ import Ledger ( TxOutRef, ) import Ledger qualified +import Ledger.Ada qualified as Ada import Network.Wai.Handler.Warp (Port) import Numeric.Natural (Natural) import Plutus.PAB.Core.ContractInstance.STM (Activity) @@ -66,7 +67,6 @@ import Plutus.PAB.Effects.Contract.Builtin ( SomeBuiltin (SomeBuiltin), endpointsToSchemas, ) -import Plutus.V1.Ledger.Ada qualified as Ada import Prettyprinter (Pretty (pretty), (<+>)) import Prettyprinter qualified as PP import Servant.Client (BaseUrl (BaseUrl), Scheme (Http)) @@ -78,7 +78,7 @@ data PABConfig = PABConfig pcCliLocation :: !CLILocation , pcChainIndexUrl :: !BaseUrl , pcNetwork :: !NetworkId - , pcProtocolParams :: !ProtocolParameters + , pcProtocolParams :: !(Maybe ProtocolParameters) , -- | Directory name of the script and data files pcScriptFileDir :: !Text , -- | Directory name of the signing key files @@ -333,7 +333,7 @@ instance Default PABConfig where { pcCliLocation = Local , pcChainIndexUrl = BaseUrl Http "localhost" 9083 "" , pcNetwork = Testnet (NetworkMagic 42) - , pcProtocolParams = def + , pcProtocolParams = Nothing , pcTipPollingInterval = 10_000_000 , pcScriptFileDir = "./result-scripts" , pcSigningKeyFileDir = "./signing-keys" diff --git a/src/BotPlutusInterface/UtxoParser.hs b/src/BotPlutusInterface/UtxoParser.hs index 7375239e..f3070406 100644 --- a/src/BotPlutusInterface/UtxoParser.hs +++ b/src/BotPlutusInterface/UtxoParser.hs @@ -1,12 +1,9 @@ module BotPlutusInterface.UtxoParser ( - chainIndexTxOutParser, feeParser, - utxoParser, - utxoMapParser, tokenNameParser, ) where -import Control.Applicative (many, optional) +import Control.Applicative (optional) import Control.Monad (mzero, void) import Data.Aeson.Extras (tryDecode) import Data.Attoparsec.ByteString.Char8 (isSpace) @@ -14,94 +11,21 @@ import Data.Attoparsec.Text ( Parser, char, choice, - count, decimal, - inClass, - isEndOfLine, option, - sepBy, signed, skipSpace, - skipWhile, string, takeWhile, - (), ) import Data.Text (Text) -import Ledger (Address (addressCredential)) -import Ledger.Ada qualified as Ada -import Ledger.Scripts (DatumHash (..)) -import Ledger.Tx ( - ChainIndexTxOut (PublicKeyChainIndexTxOut, ScriptChainIndexTxOut), - TxOutRef (..), - ) -import Ledger.TxId (TxId (..)) -import Ledger.Value (AssetClass, Value) -import Ledger.Value qualified as Value import Plutus.V1.Ledger.Api ( BuiltinByteString, - Credential (PubKeyCredential, ScriptCredential), - CurrencySymbol (..), TokenName (..), ) import PlutusTx.Builtins (toBuiltin) import Prelude hiding (takeWhile) -utxoMapParser :: Address -> Parser [(TxOutRef, ChainIndexTxOut)] -utxoMapParser address = do - skipLine 2 - many (utxoParser address) - -skipLine :: Int -> Parser () -skipLine n = - void $ - count n $ do - skipWhile (not . isEndOfLine) - skipWhile isEndOfLine - -utxoParser :: Address -> Parser (TxOutRef, ChainIndexTxOut) -utxoParser address = - (,) <$> (txOutRefParser "TxOutRef") <* skipSpace - <*> (chainIndexTxOutParser address "ChainIndexTxOut") <* skipWhile isEndOfLine - -txOutRefParser :: Parser TxOutRef -txOutRefParser = do - txId <- TxId <$> decodeHash (takeWhile (/= ' ')) - - skipSpace - txIx <- decimal - pure $ TxOutRef txId txIx - -chainIndexTxOutParser :: Address -> Parser ChainIndexTxOut -chainIndexTxOutParser address = do - value <- mconcat <$> (valueParser "Value") `sepBy` " + " - void " + " - - case addressCredential address of - ScriptCredential validatorHash -> do - datumHash <- datumHashParser "DatumHash" - pure $ ScriptChainIndexTxOut address (Left validatorHash) (Left datumHash) value - PubKeyCredential _ -> do - datumHashNoneParser "DatumHash" - pure $ PublicKeyChainIndexTxOut address value - -valueParser :: Parser Value -valueParser = do - amt <- signed decimal - skipSpace - assetClass <- assetClassParser "AssetClass" - pure $ Value.assetClassValue assetClass amt - -assetClassParser :: Parser AssetClass -assetClassParser = - choice [adaAssetClass, otherAssetClass] - where - adaAssetClass = Value.assetClass Ada.adaSymbol Ada.adaToken <$ "lovelace" - otherAssetClass = do - curSymbol <- CurrencySymbol <$> decodeHash (takeWhile (not . inClass " .")) "CurrencySymbol" - tokenname <- tokenNameParser "TokenName" - pure $ Value.assetClass curSymbol tokenname - tokenNameParser :: Parser TokenName tokenNameParser = do option "" tokenName @@ -111,17 +35,6 @@ tokenNameParser = do void $ optional $ string "0x" TokenName <$> decodeHash (takeWhile (not . isSpace)) -datumHashNoneParser :: Parser () -datumHashNoneParser = "TxOutDatumNone" >> pure () - -datumHashParser :: Parser DatumHash -datumHashParser = do - void "TxOutDatumHash" - skipSpace - void "ScriptDataInAlonzoEra" - skipSpace - char '\"' *> (DatumHash <$> decodeHash (takeWhile (/= '\"'))) <* char '\"' - decodeHash :: Parser Text -> Parser BuiltinByteString decodeHash rawParser = rawParser >>= \parsed -> either (const mzero) (pure . toBuiltin) (tryDecode parsed) diff --git a/src/PlutusConfig/Cardano/Api/Shelley.hs b/src/PlutusConfig/Cardano/Api/Shelley.hs index 94e8f750..029dc0f3 100644 --- a/src/PlutusConfig/Cardano/Api/Shelley.hs +++ b/src/PlutusConfig/Cardano/Api/Shelley.hs @@ -1,5 +1,6 @@ {-# LANGUAGE ApplicativeDo #-} -{-# LANGUAGE RecordWildCards #-} + +-- {-# LANGUAGE RecordWildCards #-} {-# OPTIONS -fno-warn-orphans #-} @@ -9,275 +10,280 @@ module PlutusConfig.Cardano.Api.Shelley ( writeProtocolParametersJSON, ) where -import Cardano.Api.ProtocolParameters () import Cardano.Api.Shelley (ProtocolParameters (..)) -import Config (Section (Section), Value (List, Sections)) -import Config.Schema ( - HasSpec (anySpec), - ValueSpec, - customSpec, - listSpec, - naturalSpec, - sectionsSpec, - ) + +-- import Config (Section (Section), Value (List, Sections)) +-- import Config.Schema ( +-- HasSpec (anySpec), +-- ValueSpec, +-- customSpec, +-- listSpec, +-- naturalSpec, +-- sectionsSpec, +-- ) + import Control.Exception (IOException, catch) import Data.Aeson qualified as JSON import Data.ByteString.Lazy qualified as LazyByteString -import Data.Default (def) -import Data.Text qualified as Text -import Numeric.Natural (Natural) -import PlutusConfig.Base (customRationalSpec, maybeSpec) + +-- import Data.Default (def) +-- import Data.Text qualified as Text +-- import Numeric.Natural (Natural) +-- import PlutusConfig.Base (customRationalSpec, maybeSpec) import PlutusConfig.Cardano.Api () -import PlutusConfig.Types ( - ToValue (toValue), - sectionWithDefault, - sectionWithDefault', - ) + +-- import PlutusConfig.Types ( +-- ToValue (toValue), +-- sectionWithDefault, +-- sectionWithDefault', +-- ) import Prelude -instance ToValue (Natural, Natural) where - toValue (a, b) = List () [toValue a, toValue b] - -protocolVersionSpec :: ValueSpec (Natural, Natural) -protocolVersionSpec = - customSpec - "" - (listSpec naturalSpec) - ( \case - [major, minor] -> Right (major, minor) - _ -> Left $ Text.pack "[MAJOR, MINOR]" - ) - -{- ORMOLU_DISABLE -} -instance ToValue ProtocolParameters where - toValue - ( ProtocolParameters - protocolParamProtocolVersion - protocolParamDecentralization - protocolParamExtraPraosEntropy - protocolParamMaxBlockHeaderSize - protocolParamMaxBlockBodySize - protocolParamMaxTxSize - protocolParamTxFeeFixed - protocolParamTxFeePerByte - protocolParamMinUTxOValue - protocolParamStakeAddressDeposit - protocolParamStakePoolDeposit - protocolParamMinPoolCost - protocolParamPoolRetireMaxEpoch - protocolParamStakePoolTargetNum - protocolParamPoolPledgeInfluence - protocolParamMonetaryExpansion - protocolParamTreasuryCut - protocolParamUTxOCostPerWord - protocolParamCostModels - protocolParamPrices - protocolParamMaxTxExUnits - protocolParamMaxBlockExUnits - protocolParamMaxValueSize - protocolParamCollateralPercent - protocolParamMaxCollateralInputs - ) = - Sections - () - [ Section () "protocolVersion" $ toValue protocolParamProtocolVersion - , Section () "decentralization" $ toValue protocolParamDecentralization - , Section () "extraPraosEntropy" $ toValue protocolParamExtraPraosEntropy - , Section () "maxBlockHeaderSize" $ toValue protocolParamMaxBlockHeaderSize - , Section () "maxBlockBodySize" $ toValue protocolParamMaxBlockBodySize - , Section () "maxTxSize" $ toValue protocolParamMaxTxSize - , Section () "txFeeFixed" $ toValue protocolParamTxFeeFixed - , Section () "txFeePerByte" $ toValue protocolParamTxFeePerByte - , Section () "minUTxOValue" $ toValue protocolParamMinUTxOValue - , Section () "stakeAddressDeposit" $ toValue protocolParamStakeAddressDeposit - , Section () "stakePoolDeposit" $ toValue protocolParamStakePoolDeposit - , Section () "minPoolCost" $ toValue protocolParamMinPoolCost - , Section () "poolRetireMaxEpoch" $ toValue protocolParamPoolRetireMaxEpoch - , Section () "stakePoolTargetNum" $ toValue protocolParamStakePoolTargetNum - , Section () "poolPledgeInfluence" $ toValue protocolParamPoolPledgeInfluence - , Section () "monetaryExpansion" $ toValue protocolParamMonetaryExpansion - , Section () "treasuryCut" $ toValue protocolParamTreasuryCut - , Section () "UTxOCostPerWord" $ toValue protocolParamUTxOCostPerWord - , Section () "costModels" $ toValue protocolParamCostModels - , Section () "prices" $ toValue protocolParamPrices - , Section () "maxTxExUnits" $ toValue protocolParamMaxTxExUnits - , Section () "maxBlockExUnits" $ toValue protocolParamMaxBlockExUnits - , Section () "maxValueSize" $ toValue protocolParamMaxValueSize - , Section () "collateralPercent" $ toValue protocolParamCollateralPercent - , Section () "maxCollateralInputs" $ toValue protocolParamMaxCollateralInputs - ] -{- ORMOLU_ENABLE -} - -instance HasSpec ProtocolParameters where - anySpec = sectionsSpec "ProtocolParameters configuration" $ do - protocolParamProtocolVersion <- - sectionWithDefault' - (protocolParamProtocolVersion def) - "protocolVersion" - protocolVersionSpec - "Protocol version, major and minor. Updating the major version is used to trigger hard forks." - - protocolParamDecentralization <- - sectionWithDefault' - (protocolParamDecentralization def) - "decentralization" - customRationalSpec - "The decentralization parameter. This is fraction of slots that belong to the BFT overlay schedule, rather than the Praos schedule. So 1 means fully centralised, while 0 means fully decentralised." - - protocolParamExtraPraosEntropy <- - sectionWithDefault' - (protocolParamExtraPraosEntropy def) - "extraPraosEntropy" - (maybeSpec anySpec) - "Extra entropy for the Praos per-epoch nonce." - - protocolParamMaxBlockHeaderSize <- - sectionWithDefault - (protocolParamMaxBlockHeaderSize def) - "maxBlockHeaderSize" - "The maximum permitted size of a block header." - - protocolParamMaxBlockBodySize <- - sectionWithDefault - (protocolParamMaxBlockBodySize def) - "maxBlockBodySize" - "The maximum permitted size of the block body (that is, the block payload, without the block header)." - - protocolParamMaxTxSize <- - sectionWithDefault - (protocolParamMaxTxSize def) - "maxTxSize" - "The maximum permitted size of a transaction." - - protocolParamTxFeeFixed <- - sectionWithDefault - (protocolParamTxFeeFixed def) - "txFeeFixed" - "The constant factor for the minimum fee calculation." - - protocolParamTxFeePerByte <- - sectionWithDefault - (protocolParamTxFeePerByte def) - "txFeePerByte" - "The linear factor for the minimum fee calculation." - - protocolParamMinUTxOValue <- - sectionWithDefault' - (protocolParamMinUTxOValue def) - "minUTxOValue" - (maybeSpec anySpec) - "The minimum permitted value for new UTxO entries, ie for transaction outputs." - - protocolParamStakePoolDeposit <- - sectionWithDefault - (protocolParamStakePoolDeposit def) - "stakePoolDeposit" - "The deposit required to register a stake address." - - protocolParamStakeAddressDeposit <- - sectionWithDefault - (protocolParamStakeAddressDeposit def) - "stakeAddressDeposit" - "The deposit required to register a stake pool." - - protocolParamMinPoolCost <- - sectionWithDefault - (protocolParamMinPoolCost def) - "minPoolCost" - "The minimum value that stake pools are permitted to declare for their cost parameter." - - protocolParamPoolRetireMaxEpoch <- - sectionWithDefault - (protocolParamPoolRetireMaxEpoch def) - "poolRetireMaxEpoch" - "The maximum number of epochs into the future that stake pools are permitted to schedule a retirement." - - protocolParamStakePoolTargetNum <- - sectionWithDefault - (protocolParamStakePoolTargetNum def) - "stakePoolTargetNum" - "The equilibrium target number of stake pools." - - protocolParamPoolPledgeInfluence <- - sectionWithDefault' - (protocolParamPoolPledgeInfluence def) - "poolPledgeInfluence" - customRationalSpec - "The influence of the pledge in stake pool rewards." - - protocolParamMonetaryExpansion <- - sectionWithDefault' - (protocolParamMonetaryExpansion def) - "monetaryExpansion" - customRationalSpec - "The monetary expansion rate. This determines the fraction of the reserves that are added to the fee pot each epoch." - - protocolParamTreasuryCut <- - sectionWithDefault' - (protocolParamTreasuryCut def) - "treasuryCut" - customRationalSpec - "The fraction of the fee pot each epoch that goes to the treasury." - - protocolParamUTxOCostPerWord <- - sectionWithDefault' - (protocolParamUTxOCostPerWord def) - "UTxOCostPerWord" - (maybeSpec anySpec) - "Cost in ada per word of UTxO storage." - - protocolParamCostModels <- - sectionWithDefault - (protocolParamCostModels def) - "costModels" - "Cost models for script languages that use them." - - protocolParamPrices <- - sectionWithDefault' - (protocolParamPrices def) - "prices" - (maybeSpec anySpec) - "Price of execution units for script languages that use them." - - protocolParamMaxTxExUnits <- - sectionWithDefault' - (protocolParamMaxTxExUnits def) - "maxTxExUnits" - (maybeSpec anySpec) - "Max total script execution resources units allowed per tx." - - protocolParamMaxBlockExUnits <- - sectionWithDefault' - (protocolParamMaxBlockExUnits def) - "maxBlockExUnits" - (maybeSpec anySpec) - "Max total script execution resources units allowed per block" - - protocolParamMaxValueSize <- - sectionWithDefault' - (protocolParamMaxValueSize def) - "maxValueSize" - (maybeSpec naturalSpec) - "Max size of a Value in a tx output." - - protocolParamCollateralPercent <- - sectionWithDefault' - (protocolParamCollateralPercent def) - "collateralPercent" - (maybeSpec naturalSpec) - "The percentage of the script contribution to the txfee that must be provided as collateral inputs when including Plutus scripts." - - protocolParamMaxCollateralInputs <- - sectionWithDefault' - (protocolParamMaxCollateralInputs def) - "maxCollateralInputs" - (maybeSpec naturalSpec) - "The maximum number of collateral inputs allowed in a transaction." - - pure ProtocolParameters {..} +-- instance ToValue (Natural, Natural) where +-- toValue (a, b) = List () [toValue a, toValue b] + +-- protocolVersionSpec :: ValueSpec (Natural, Natural) +-- protocolVersionSpec = +-- customSpec +-- "" +-- (listSpec naturalSpec) +-- ( \case +-- [major, minor] -> Right (major, minor) +-- _ -> Left $ Text.pack "[MAJOR, MINOR]" +-- ) + +-- {- ORMOLU_DISABLE -} +-- instance ToValue ProtocolParameters where +-- toValue +-- ( ProtocolParameters +-- protocolParamProtocolVersion +-- protocolParamDecentralization +-- protocolParamExtraPraosEntropy +-- protocolParamMaxBlockHeaderSize +-- protocolParamMaxBlockBodySize +-- protocolParamMaxTxSize +-- protocolParamTxFeeFixed +-- protocolParamTxFeePerByte +-- protocolParamMinUTxOValue +-- protocolParamStakeAddressDeposit +-- protocolParamStakePoolDeposit +-- protocolParamMinPoolCost +-- protocolParamPoolRetireMaxEpoch +-- protocolParamStakePoolTargetNum +-- protocolParamPoolPledgeInfluence +-- protocolParamMonetaryExpansion +-- protocolParamTreasuryCut +-- protocolParamUTxOCostPerWord +-- protocolParamCostModels +-- protocolParamPrices +-- protocolParamMaxTxExUnits +-- protocolParamMaxBlockExUnits +-- protocolParamMaxValueSize +-- protocolParamCollateralPercent +-- protocolParamMaxCollateralInputs +-- ) = +-- Sections +-- () +-- [ Section () "protocolVersion" $ toValue protocolParamProtocolVersion +-- , Section () "decentralization" $ toValue protocolParamDecentralization +-- , Section () "extraPraosEntropy" $ toValue protocolParamExtraPraosEntropy +-- , Section () "maxBlockHeaderSize" $ toValue protocolParamMaxBlockHeaderSize +-- , Section () "maxBlockBodySize" $ toValue protocolParamMaxBlockBodySize +-- , Section () "maxTxSize" $ toValue protocolParamMaxTxSize +-- , Section () "txFeeFixed" $ toValue protocolParamTxFeeFixed +-- , Section () "txFeePerByte" $ toValue protocolParamTxFeePerByte +-- , Section () "minUTxOValue" $ toValue protocolParamMinUTxOValue +-- , Section () "stakeAddressDeposit" $ toValue protocolParamStakeAddressDeposit +-- , Section () "stakePoolDeposit" $ toValue protocolParamStakePoolDeposit +-- , Section () "minPoolCost" $ toValue protocolParamMinPoolCost +-- , Section () "poolRetireMaxEpoch" $ toValue protocolParamPoolRetireMaxEpoch +-- , Section () "stakePoolTargetNum" $ toValue protocolParamStakePoolTargetNum +-- , Section () "poolPledgeInfluence" $ toValue protocolParamPoolPledgeInfluence +-- , Section () "monetaryExpansion" $ toValue protocolParamMonetaryExpansion +-- , Section () "treasuryCut" $ toValue protocolParamTreasuryCut +-- , Section () "UTxOCostPerWord" $ toValue protocolParamUTxOCostPerWord +-- , Section () "costModels" $ toValue protocolParamCostModels +-- , Section () "prices" $ toValue protocolParamPrices +-- , Section () "maxTxExUnits" $ toValue protocolParamMaxTxExUnits +-- , Section () "maxBlockExUnits" $ toValue protocolParamMaxBlockExUnits +-- , Section () "maxValueSize" $ toValue protocolParamMaxValueSize +-- , Section () "collateralPercent" $ toValue protocolParamCollateralPercent +-- , Section () "maxCollateralInputs" $ toValue protocolParamMaxCollateralInputs +-- ] +-- {- ORMOLU_ENABLE -} + +-- instance HasSpec ProtocolParameters where +-- anySpec = sectionsSpec "ProtocolParameters configuration" $ do +-- protocolParamProtocolVersion <- +-- sectionWithDefault' +-- (protocolParamProtocolVersion def) +-- "protocolVersion" +-- protocolVersionSpec +-- "Protocol version, major and minor. Updating the major version is used to trigger hard forks." + +-- protocolParamDecentralization <- +-- sectionWithDefault' +-- (protocolParamDecentralization def) +-- "decentralization" +-- (fmap Just customRationalSpec) +-- "The decentralization parameter. This is fraction of slots that belong to the BFT overlay schedule, rather than the Praos schedule. So 1 means fully centralised, while 0 means fully decentralised." + +-- protocolParamExtraPraosEntropy <- +-- sectionWithDefault' +-- (protocolParamExtraPraosEntropy def) +-- "extraPraosEntropy" +-- (maybeSpec anySpec) +-- "Extra entropy for the Praos per-epoch nonce." + +-- protocolParamMaxBlockHeaderSize <- +-- sectionWithDefault +-- (protocolParamMaxBlockHeaderSize def) +-- "maxBlockHeaderSize" +-- "The maximum permitted size of a block header." + +-- protocolParamMaxBlockBodySize <- +-- sectionWithDefault +-- (protocolParamMaxBlockBodySize def) +-- "maxBlockBodySize" +-- "The maximum permitted size of the block body (that is, the block payload, without the block header)." + +-- protocolParamMaxTxSize <- +-- sectionWithDefault +-- (protocolParamMaxTxSize def) +-- "maxTxSize" +-- "The maximum permitted size of a transaction." + +-- protocolParamTxFeeFixed <- +-- sectionWithDefault +-- (protocolParamTxFeeFixed def) +-- "txFeeFixed" +-- "The constant factor for the minimum fee calculation." + +-- protocolParamTxFeePerByte <- +-- sectionWithDefault +-- (protocolParamTxFeePerByte def) +-- "txFeePerByte" +-- "The linear factor for the minimum fee calculation." + +-- protocolParamMinUTxOValue <- +-- sectionWithDefault' +-- (protocolParamMinUTxOValue def) +-- "minUTxOValue" +-- (maybeSpec anySpec) +-- "The minimum permitted value for new UTxO entries, ie for transaction outputs." + +-- protocolParamStakePoolDeposit <- +-- sectionWithDefault +-- (protocolParamStakePoolDeposit def) +-- "stakePoolDeposit" +-- "The deposit required to register a stake address." + +-- protocolParamStakeAddressDeposit <- +-- sectionWithDefault +-- (protocolParamStakeAddressDeposit def) +-- "stakeAddressDeposit" +-- "The deposit required to register a stake pool." + +-- protocolParamMinPoolCost <- +-- sectionWithDefault +-- (protocolParamMinPoolCost def) +-- "minPoolCost" +-- "The minimum value that stake pools are permitted to declare for their cost parameter." + +-- protocolParamPoolRetireMaxEpoch <- +-- sectionWithDefault +-- (protocolParamPoolRetireMaxEpoch def) +-- "poolRetireMaxEpoch" +-- "The maximum number of epochs into the future that stake pools are permitted to schedule a retirement." + +-- protocolParamStakePoolTargetNum <- +-- sectionWithDefault +-- (protocolParamStakePoolTargetNum def) +-- "stakePoolTargetNum" +-- "The equilibrium target number of stake pools." + +-- protocolParamPoolPledgeInfluence <- +-- sectionWithDefault' +-- (protocolParamPoolPledgeInfluence def) +-- "poolPledgeInfluence" +-- customRationalSpec +-- "The influence of the pledge in stake pool rewards." + +-- protocolParamMonetaryExpansion <- +-- sectionWithDefault' +-- (protocolParamMonetaryExpansion def) +-- "monetaryExpansion" +-- customRationalSpec +-- "The monetary expansion rate. This determines the fraction of the reserves that are added to the fee pot each epoch." + +-- protocolParamTreasuryCut <- +-- sectionWithDefault' +-- (protocolParamTreasuryCut def) +-- "treasuryCut" +-- customRationalSpec +-- "The fraction of the fee pot each epoch that goes to the treasury." + +-- protocolParamUTxOCostPerWord <- +-- sectionWithDefault' +-- (protocolParamUTxOCostPerWord def) +-- "UTxOCostPerWord" +-- (maybeSpec anySpec) +-- "Cost in ada per word of UTxO storage." + +-- protocolParamCostModels <- +-- sectionWithDefault +-- (protocolParamCostModels def) +-- "costModels" +-- "Cost models for script languages that use them." + +-- protocolParamPrices <- +-- sectionWithDefault' +-- (protocolParamPrices def) +-- "prices" +-- (maybeSpec anySpec) +-- "Price of execution units for script languages that use them." + +-- protocolParamMaxTxExUnits <- +-- sectionWithDefault' +-- (protocolParamMaxTxExUnits def) +-- "maxTxExUnits" +-- (maybeSpec anySpec) +-- "Max total script execution resources units allowed per tx." + +-- protocolParamMaxBlockExUnits <- +-- sectionWithDefault' +-- (protocolParamMaxBlockExUnits def) +-- "maxBlockExUnits" +-- (maybeSpec anySpec) +-- "Max total script execution resources units allowed per block" + +-- protocolParamMaxValueSize <- +-- sectionWithDefault' +-- (protocolParamMaxValueSize def) +-- "maxValueSize" +-- (maybeSpec naturalSpec) +-- "Max size of a Value in a tx output." + +-- protocolParamCollateralPercent <- +-- sectionWithDefault' +-- (protocolParamCollateralPercent def) +-- "collateralPercent" +-- (maybeSpec naturalSpec) +-- "The percentage of the script contribution to the txfee that must be provided as collateral inputs when including Plutus scripts." + +-- protocolParamMaxCollateralInputs <- +-- sectionWithDefault' +-- (protocolParamMaxCollateralInputs def) +-- "maxCollateralInputs" +-- (maybeSpec naturalSpec) +-- "The maximum number of collateral inputs allowed in a transaction." + +-- pure ProtocolParameters {..} readProtocolParametersJSON :: FilePath -> IO (Either String ProtocolParameters) -readProtocolParametersJSON fn = (JSON.eitherDecode <$> LazyByteString.readFile fn) `catch` (\(e :: IOException) -> pure $ Left (show e)) +readProtocolParametersJSON fn = + (JSON.eitherDecode <$> LazyByteString.readFile fn) + `catch` (\(e :: IOException) -> pure $ Left (show e)) writeProtocolParametersJSON :: FilePath -> ProtocolParameters -> IO () writeProtocolParametersJSON fn params = diff --git a/test/Spec.hs b/test/Spec.hs index d5ad9992..57499773 100644 --- a/test/Spec.hs +++ b/test/Spec.hs @@ -1,19 +1,19 @@ module Main (main) where +import Spec.BotPlutusInterface.AdjustUnbalanced qualified import Spec.BotPlutusInterface.Balance qualified import Spec.BotPlutusInterface.CoinSelection qualified -import Spec.BotPlutusInterface.Collateral qualified import Spec.BotPlutusInterface.Contract qualified import Spec.BotPlutusInterface.ContractStats qualified import Spec.BotPlutusInterface.Server qualified import Spec.BotPlutusInterface.TxStatusChange qualified -import Spec.BotPlutusInterface.UtxoParser qualified +import System.IO import Test.Tasty (TestTree, defaultMain, testGroup) -import Prelude -- | @since 0.1 main :: IO () -main = defaultMain tests +main = do + defaultMain tests {- | Project wide tests @@ -24,11 +24,10 @@ tests = testGroup "BotPlutusInterface" [ Spec.BotPlutusInterface.Contract.tests - , Spec.BotPlutusInterface.UtxoParser.tests , Spec.BotPlutusInterface.Balance.tests , Spec.BotPlutusInterface.CoinSelection.tests , Spec.BotPlutusInterface.Server.tests , Spec.BotPlutusInterface.ContractStats.tests , Spec.BotPlutusInterface.TxStatusChange.tests - , Spec.BotPlutusInterface.Collateral.tests + , Spec.BotPlutusInterface.AdjustUnbalanced.tests ] diff --git a/test/Spec/BotPlutusInterface/AdjustUnbalanced.hs b/test/Spec/BotPlutusInterface/AdjustUnbalanced.hs new file mode 100644 index 00000000..63ba98c5 --- /dev/null +++ b/test/Spec/BotPlutusInterface/AdjustUnbalanced.hs @@ -0,0 +1,97 @@ +module Spec.BotPlutusInterface.AdjustUnbalanced (tests) where + +import BotPlutusInterface.Types ( + ContractEnvironment (cePABConfig), + PABConfig (pcOwnPubKeyHash, pcProtocolParams), + ) +import Control.Lens ((&), (.~), (^.)) +import Data.Default (def) +import Data.Text (Text) +import Ledger ( + ChainIndexTxOut (PublicKeyChainIndexTxOut), + PaymentPubKeyHash (unPaymentPubKeyHash), + TxOut (..), + Value, + outputs, + pubKeyHashAddress, + ) +import Ledger.Ada qualified as Ada +import Ledger.Constraints qualified as Constraints +import Ledger.Tx (TxOutRef (TxOutRef)) +import Plutus.Contract ( + Contract (..), + Endpoint, + adjustUnbalancedTx, + ) +import Spec.MockContract ( + contractEnv, + paymentPkh1, + paymentPkh2, + paymentPkh3, + pkhAddr1, + runContractPure, + utxos, + ) +import Test.Tasty (TestTree) +import Test.Tasty.HUnit (Assertion, assertBool, assertFailure, testCase) +import Prelude + +import Data.Foldable (find) +import Data.Void (Void) +import Ledger.Ada (fromValue) +import Ledger.Constraints.OffChain (tx) + +tests :: TestTree +tests = testCase "Adjusting unbalanced transaction" testOutsGetAdjusted + +testOutsGetAdjusted :: Assertion +testOutsGetAdjusted = do + let txOutRef = TxOutRef "e406b0cf676fc2b1a9edb0617f259ad025c20ea6f0333820aa7cef1bfe7302e5" 0 + txOut = PublicKeyChainIndexTxOut pkhAddr1 (Ada.lovelaceValueOf 1350) Nothing Nothing + initState = + def & utxos .~ [(txOutRef, txOut)] + & contractEnv .~ contractEnv' + pabConf = def {pcOwnPubKeyHash = unPaymentPubKeyHash paymentPkh1, pcProtocolParams = Just def} + contractEnv' = def {cePABConfig = pabConf} + + smallValue = Ada.lovelaceValueOf 1 + bigEnoughValue = Ada.adaValueOf 777 + + shouldBeAdjusted = (paymentPkh2, smallValue) + shouldNotBeAdjusted = (paymentPkh3, bigEnoughValue) + + contract :: Contract () (Endpoint "SendAda" ()) Text [TxOut] + contract = do + let constraints = foldMap toPayConstraint [shouldBeAdjusted, shouldNotBeAdjusted] + utx = either (error . show) id (Constraints.mkTx @Void mempty constraints) + adjustedUtx <- adjustUnbalancedTx utx + return (adjustedUtx ^. tx . outputs) + + case runContractPure contract initState of + (Right outs, _) -> do + -- check of value that should be adjusted + assertBool + "Small values should be adjusted and become bigger" + (fromValue (outValueForPkh outs paymentPkh2) > fromValue smallValue) + + -- check of value that should NOT be adjusted + let resultAdaAmount = fromValue (outValueForPkh outs paymentPkh3) + initialAdaAmount = fromValue bigEnoughValue + errMessage = + "Big enough value should not be adjusted, but it changed: " + <> show initialAdaAmount + <> " -> " + <> show resultAdaAmount + assertBool errMessage (resultAdaAmount == initialAdaAmount) + e -> assertFailure $ "RES:\n" ++ show e + +toPayConstraint :: (PaymentPubKeyHash, Value) -> Constraints.TxConstraints i o +toPayConstraint (pkh, value) = Constraints.mustPayToPubKey pkh value + +outValueForPkh :: [TxOut] -> PaymentPubKeyHash -> Value +outValueForPkh outs pkh = + let address = pubKeyHashAddress pkh Nothing + in maybe + (error "Should not happen: value for PKH used in test not found") + txOutValue + $ flip find outs $ \txOut -> address == txOutAddress txOut diff --git a/test/Spec/BotPlutusInterface/Balance.hs b/test/Spec/BotPlutusInterface/Balance.hs index 3648799a..86aa8abe 100644 --- a/test/Spec/BotPlutusInterface/Balance.hs +++ b/test/Spec/BotPlutusInterface/Balance.hs @@ -10,12 +10,11 @@ import BotPlutusInterface.Types ( ContractEnvironment (cePABConfig), PABConfig (pcOwnPubKeyHash), ) -import Control.Lens ((&), (.~), (<>~), (^.)) +import Control.Lens ((&), (.~), (^.)) import Data.Default (Default (def)) import Data.Function (on) import Data.List (delete, partition) import Data.Map qualified as Map -import Data.Set qualified as Set import Data.Text qualified as Text import Data.Void (Void) import Ledger qualified @@ -35,17 +34,21 @@ import Ledger.Tx ( TxOut (..), TxOutRef (..), ) -import Ledger.Value (AssetClass, Value) import Ledger.Value qualified as Value + +import Ledger.Value (AssetClass, Value) +import Plutus.Script.Utils.Scripts qualified as ScriptUtils +import Plutus.Script.Utils.V1.Address qualified as ScriptUtils import Plutus.V1.Ledger.Api qualified as Api import PlutusTx qualified +import Prettyprinter (pretty) import Spec.MockContract ( MockContractState, contractEnv, + currencySymbol1, paymentPkh3, pkh3, pkhAddr3, - -- runContractPure, runPABEffectPure, utxos, ) @@ -83,7 +86,7 @@ pkh2 = Address.unPaymentPubKeyHash . Wallet.paymentPubKeyHash $ Wallet.knownMock addr1, addr2, valAddr :: Address addr1 = Ledger.pubKeyHashAddress (PaymentPubKeyHash pkh1) Nothing addr2 = Ledger.pubKeyHashAddress (PaymentPubKeyHash pkh2) Nothing -valAddr = Ledger.scriptAddress validator +valAddr = ScriptUtils.mkValidatorAddress validator txOutRef1, txOutRef2, txOutRef3, txOutRef4, txOutRef5, txOutRef6, txOutRef7 :: TxOutRef txOutRef1 = TxOutRef "384de3f29396fdf687551e3f9e05bd400adcd277720c71f1d2b61f17f5183e51" 0 @@ -104,19 +107,18 @@ utxo1, utxo2, utxo3, utxo4 :: (TxOutRef, TxOut) utxo1 = (txOutRef1, TxOut addr1 (Ada.lovelaceValueOf 1_100_000) Nothing) utxo2 = (txOutRef2, TxOut addr1 (Ada.lovelaceValueOf 1_000_000) Nothing) utxo3 = (txOutRef3, TxOut addr1 (Ada.lovelaceValueOf 900_000) Nothing) -utxo4 = (txOutRef4, TxOut addr1 (Ada.lovelaceValueOf 800_000 <> Value.assetClassValue tokenAsset 200) Nothing) +utxo4 = (txOutRef4, TxOut addr1 (Ada.lovelaceValueOf 800_000 <> Value.singleton currencySymbol1 "Token" 200) Nothing) +-- Ada values set to amount that covers min Ada so we don't need to deal with +-- output's adjustments scrValue :: Value.Value -scrValue = Value.assetClassValue tokenAsset 200 <> Ada.lovelaceValueOf 500_000 - -scrValue' :: Value.Value -scrValue' = Value.assetClassValue tokenAsset 120 <> Ada.lovelaceValueOf 500_000 +scrValue = Value.assetClassValue tokenAsset 200 <> Ada.lovelaceValueOf 2_000_000 scrDatum :: Ledger.Datum scrDatum = Ledger.Datum $ Api.toBuiltinData (23 :: Integer) scrDatumHash :: Ledger.DatumHash -scrDatumHash = Ledger.datumHash scrDatum +scrDatumHash = ScriptUtils.datumHash scrDatum acValueOf :: AssetClass -> Value -> Integer acValueOf = flip Value.assetClassValueOf @@ -126,70 +128,70 @@ lovelaceInValue :: Value -> Integer lovelaceInValue = acValueOf (Value.assetClass Api.adaSymbol Api.adaToken) tokenAsset :: Value.AssetClass -tokenAsset = Value.assetClass "11223344" "Token" +tokenAsset = Value.assetClass currencySymbol1 "Token" addUtxosForFees :: Assertion addUtxosForFees = do let txout = TxOut addr2 (Ada.lovelaceValueOf 1_000_000) Nothing tx = mempty {txOutputs = [txout]} `withFee` 500_000 - minUtxo = [(txout, 1_000_000)] utxoIndex = Map.fromList [utxo1, utxo2, utxo3] ownAddr = addr1 ebalancedTx = fst $ - runPABEffectPure def $ - Balance.balanceTxStep @() @'[PABEffect ()] defaultBalanceConfig minUtxo utxoIndex ownAddr tx + runPABEffectPure def $ do + Balance.balanceTxStep @() @'[PABEffect ()] defaultBalanceConfig utxoIndex ownAddr tx case ebalancedTx of Left e -> assertFailure (Text.unpack e) - Right balanceTx -> txInputs <$> balanceTx @?= Right (Set.fromList [txIn1, txIn2]) + Right balanceTx -> txInputs <$> balanceTx @?= Right [txIn1, txIn2] addUtxosForNativeTokens :: Assertion addUtxosForNativeTokens = do - let txout = TxOut addr2 (Value.singleton "11223344" "Token" 123) Nothing + let txout = TxOut addr2 (Value.singleton currencySymbol1 "Token" 123) Nothing tx = mempty {txOutputs = [txout]} `withFee` 500_000 - minUtxo = [(txout, 1_000_000)] utxoIndex = Map.fromList [utxo1, utxo2, utxo3, utxo4] ownAddr = addr1 ebalancedTx = fst $ runPABEffectPure def $ - Balance.balanceTxStep @() @'[PABEffect ()] defaultBalanceConfig minUtxo utxoIndex ownAddr tx + Balance.balanceTxStep @() @'[PABEffect ()] defaultBalanceConfig utxoIndex ownAddr tx case ebalancedTx of Left e -> assertFailure (Text.unpack e) - Right balancedTx -> txInputs <$> balancedTx @?= Right (Set.fromList [txIn3, txIn4]) + Right balancedTx -> txInputs <$> balancedTx @?= Right [txIn4] addUtxosForChange :: Assertion addUtxosForChange = do let txout = TxOut addr2 (Ada.lovelaceValueOf 1_600_000) Nothing tx = mempty {txOutputs = [txout]} `withFee` 500_000 - minUtxo = [(txout, 1_000_000)] utxoIndex = Map.fromList [utxo1, utxo2, utxo3] ownAddr = addr1 ebalancedTx = fst $ runPABEffectPure def $ - Balance.balanceTxStep @() @'[PABEffect ()] defaultBalanceConfig minUtxo utxoIndex ownAddr tx + Balance.balanceTxStep @() @'[PABEffect ()] defaultBalanceConfig utxoIndex ownAddr tx case ebalancedTx of Left e -> assertFailure (Text.unpack e) - Right balancedTx -> txInputs <$> balancedTx @?= Right (Set.fromList [txIn1, txIn2]) + Right balancedTx -> txInputs <$> balancedTx @?= Right [txIn1, txIn2] dontAddChangeToDatum :: Assertion dontAddChangeToDatum = do - let scrTxOut' = + let scrTxOut = ScriptChainIndexTxOut valAddr - (Right validator) - (Right scrDatum) scrValue - scrTxOut = Ledger.toTxOut scrTxOut' - usrTxOut' = + (toHashAndDatum scrDatum) + Nothing + (toHashAndValidator validator) + -- scrTxOut = Ledger.toTxOut scrTxOut' + usrTxOut = PublicKeyChainIndexTxOut pkhAddr3 (Ada.lovelaceValueOf 1_001_000) - usrTxOut = Ledger.toTxOut usrTxOut' + Nothing + Nothing + -- usrTxOut = Ledger.toTxOut usrTxOut' initState :: MockContractState () initState = def & utxos .~ [(txOutRef6, scrTxOut), (txOutRef7, usrTxOut)] @@ -205,7 +207,7 @@ dontAddChangeToDatum = do -- - Amt : 1.001 ADA -- UTxO 2: -- - From: Script - -- - Amt : 0.5 ADA + 200 Tokens + -- - Amt : 2 ADA + 200 Tokens -- -- Output UTxOs: -- UTxO 1: @@ -213,18 +215,22 @@ dontAddChangeToDatum = do -- - Amt: 1 ADA -- UTxO 2: -- - To : Script - -- - Amt: 0.5005 Ada + 200 Token + -- - Amt: 1.5 Ada + 200 Token -- -- Fees : 400 Lovelace - -- Change : 100 Lovelace + -- Change : 500600 Lovelace scrLkups = - Constraints.unspentOutputs (Map.fromList [(txOutRef6, scrTxOut'), (txOutRef7, usrTxOut')]) + Constraints.unspentOutputs (Map.fromList [(txOutRef6, scrTxOut), (txOutRef7, usrTxOut)]) <> Constraints.ownPaymentPubKeyHash paymentPkh3 + <> Constraints.plutusV1OtherScript validator + + payToScriptValue = Ada.lovelaceValueOf 1_500_000 + payToUserValue = Ada.lovelaceValueOf 1_000_000 txConsts = -- Pay the same datum to the script, but with more ada. - Constraints.mustPayToOtherScript valHash scrDatum (scrValue <> Ada.lovelaceValueOf 500) - <> Constraints.mustPayToPubKey paymentPkh3 (Ada.lovelaceValueOf 1_000_000) + Constraints.mustPayToOtherScript valHash scrDatum payToScriptValue + <> Constraints.mustPayToPubKey paymentPkh3 payToUserValue <> Constraints.mustSpendScriptOutput txOutRef6 Ledger.unitRedeemer <> Constraints.mustSpendPubKeyOutput txOutRef7 eunbalancedTx = Constraints.mkTx @Void scrLkups txConsts @@ -233,7 +239,7 @@ dontAddChangeToDatum = do let (eRslt, _finalState) = runPABEffectPure initState (balanceTxIO @() @'[PABEffect ()] pabConf pkh3 unbalancedTx) eRslt' <- liftAssertFailure eRslt (\txt -> "PAB effect error: " <> Text.unpack txt) trx <- liftAssertFailure eRslt' (\txt -> "Balancing error: " <> Text.unpack txt) - let scrTxOut'' = scrTxOut' & Ledger.ciTxOutValue <>~ Ada.lovelaceValueOf 500 + let scrTxOut'' = scrTxOut & Ledger.ciTxOutValue .~ payToScriptValue scrTxOutExpected = Ledger.toTxOut scrTxOut'' isScrUtxo :: TxOut -> Bool isScrUtxo utxo = txOutAddress utxo == txOutAddress scrTxOutExpected @@ -241,13 +247,13 @@ dontAddChangeToDatum = do assertBool ( "Expected UTxO not in output Tx." <> "\nExpected UTxO: \n" - <> show scrTxOutExpected + <> show (pretty scrTxOutExpected) <> "\nBalanced Script UTxOs: \n" - <> show balScrUtxos + <> show (pretty balScrUtxos) <> "\nOther Balanced UTxOs: \n" - <> show balOtherUtxos + <> show (pretty balOtherUtxos) <> "\nUnbalanced UTxOs: \n" - <> show (txOutputs (unbalancedTx ^. OffChain.tx)) + <> show (pretty (txOutputs (unbalancedTx ^. OffChain.tx))) ) (scrTxOutExpected `elem` txOutputs trx) @@ -255,13 +261,14 @@ dontAddChangeToDatum = do -- only has inputs from the script. dontAddChangeToDatum2 :: Assertion dontAddChangeToDatum2 = do - let scrTxOut' = + let scrTxOut = ScriptChainIndexTxOut valAddr - (Right validator) - (Right scrDatum) (scrValue <> Ada.lovelaceValueOf 1_500_000) - scrTxOut = Ledger.toTxOut scrTxOut' + (toHashAndDatum scrDatum) + Nothing + (toHashAndValidator validator) + -- scrTxOut = Ledger.toTxOut scrTxOut' initState :: MockContractState () initState = def & utxos .~ [(txOutRef6, scrTxOut)] @@ -272,25 +279,29 @@ dontAddChangeToDatum2 = do contractEnv' = def {cePABConfig = pabConf} -- Input UTxO : - -- - 2.0 ADA + -- - 3.5 ADA -- - 200 tokens -- Output UTxO : - -- - 0.5 ADA + -- - 2 ADA -- - 120 tokens -- Change: -- - 1.5 ADA (400 Lovelace to fees) -- - 80 tokens + payToScrValue :: Value.Value + payToScrValue = Value.assetClassValue tokenAsset 120 <> Ada.lovelaceValueOf 2_000_000 + scrLkups = - Constraints.unspentOutputs (Map.fromList [(txOutRef6, scrTxOut')]) + Constraints.unspentOutputs (Map.fromList [(txOutRef6, scrTxOut)]) <> Constraints.ownPaymentPubKeyHash paymentPkh3 + <> Constraints.plutusV1OtherScript validator txConsts = -- Pay the same datum to the script, but with LESS ada -- and fewer tokens. This is to ensure that the excess -- ADA and tokens are moved into their own UTxO(s), -- rather than just being left in the original UTxO. -- (The extra ada is used to cover fees etc...) - Constraints.mustPayToOtherScript valHash scrDatum scrValue' + Constraints.mustPayToOtherScript valHash scrDatum payToScrValue <> Constraints.mustSpendScriptOutput txOutRef6 Ledger.unitRedeemer eunbalancedTx = Constraints.mkTx @Void scrLkups txConsts @@ -298,7 +309,7 @@ dontAddChangeToDatum2 = do let (eRslt, _finalState) = runPABEffectPure initState (balanceTxIO @() @'[PABEffect ()] pabConf pkh3 unbalancedTx) eRslt' <- liftAssertFailure eRslt (\txt -> "PAB effect error: " <> Text.unpack txt) trx <- liftAssertFailure eRslt' (\txt -> "Balancing error: " <> Text.unpack txt) - let scrTxOut'' = scrTxOut' & Ledger.ciTxOutValue .~ scrValue' + let scrTxOut'' = scrTxOut & Ledger.ciTxOutValue .~ payToScrValue scrTxOutExpected = Ledger.toTxOut scrTxOut'' isScrUtxo :: TxOut -> Bool isScrUtxo utxo = txOutAddress utxo == txOutAddress scrTxOutExpected @@ -320,11 +331,11 @@ dontAddChangeToDatum2 = do -- Check that the output has the remaining change let trxFee = txFee trx adaChange' :: Integer - adaChange' = ((-) `on` (lovelaceInValue . txOutValue)) scrTxOut scrTxOutExpected + adaChange' = ((-) `on` (lovelaceInValue . txOutValue)) (Ledger.toTxOut scrTxOut) scrTxOutExpected adaChange :: Integer adaChange = adaChange' - lovelaceInValue trxFee tokChange :: Integer - tokChange = ((-) `on` (acValueOf tokenAsset . txOutValue)) scrTxOut scrTxOutExpected + tokChange = ((-) `on` (acValueOf tokenAsset . txOutValue)) (Ledger.toTxOut scrTxOut) scrTxOutExpected remainingTxOuts :: [TxOut] remainingTxOuts = delete scrTxOutExpected (txOutputs trx) remainingValue :: Value.Value @@ -348,3 +359,9 @@ dontAddChangeToDatum2 = do liftAssertFailure :: Either a b -> (a -> String) -> IO b liftAssertFailure (Left err) fstr = assertFailure (fstr err) liftAssertFailure (Right rslt) _ = return rslt + +toHashAndDatum :: ScriptUtils.Datum -> (ScriptUtils.DatumHash, Maybe ScriptUtils.Datum) +toHashAndDatum d = (ScriptUtils.datumHash d, Just d) + +toHashAndValidator :: Api.Validator -> (Api.ValidatorHash, Maybe Api.Validator) +toHashAndValidator v = (Scripts.validatorHash v, Just v) diff --git a/test/Spec/BotPlutusInterface/Collateral.hs b/test/Spec/BotPlutusInterface/Collateral.hs index a7e11ffe..ecc3b40c 100644 --- a/test/Spec/BotPlutusInterface/Collateral.hs +++ b/test/Spec/BotPlutusInterface/Collateral.hs @@ -12,9 +12,9 @@ import Ledger qualified import Ledger.Ada qualified as Ada import Ledger.Constraints qualified as Constraints import Ledger.Scripts qualified as Scripts -import Ledger.Tx (CardanoTx, TxOut (TxOut), TxOutRef (TxOutRef)) +import Ledger.Tx (CardanoTx, ChainIndexTxOut (PublicKeyChainIndexTxOut), TxOutRef (TxOutRef)) import Ledger.Tx qualified as Tx -import Ledger.TxId qualified as TxId +import Ledger.Tx qualified as TxId import Ledger.Value qualified as Value import NeatInterpolation (text) import Plutus.Contract ( @@ -65,9 +65,9 @@ tests = testTxUsesCollateralCorrectly :: Assertion testTxUsesCollateralCorrectly = do let txOutRef1 = TxOutRef "e406b0cf676fc2b1a9edb0617f259ad025c20ea6f0333820aa7cef1bfe7302e5" 0 - txOut1 = TxOut pkhAddr1 (Ada.lovelaceValueOf 10_000_000) Nothing + txOut1 = PublicKeyChainIndexTxOut pkhAddr1 (Ada.lovelaceValueOf 10_000_000) Nothing Nothing txOutRef2 = TxOutRef "d406b0cf676fc2b1a9edb0617f259ad025c20ea6f0333820aa7cef1bfe7302e4" 0 - txOut2 = TxOut pkhAddr1 (Ada.lovelaceValueOf 90_000_000) Nothing + txOut2 = PublicKeyChainIndexTxOut pkhAddr1 (Ada.lovelaceValueOf 90_000_000) Nothing Nothing cenv' = def {ceCollateral = CollateralVar $ unsafePerformIO $ newTVarIO Nothing} initState = def & utxos .~ [(txOutRef1, txOut1), (txOutRef2, txOut2)] & contractEnv .~ cenv' & collateralUtxo .~ Nothing @@ -106,7 +106,7 @@ testTxUsesCollateralCorrectly = do testTxCreatesCollateralCorrectly :: Assertion testTxCreatesCollateralCorrectly = do let txOutRef1 = TxOutRef "d406b0cf676fc2b1a9edb0617f259ad025c20ea6f0333820aa7cef1bfe7302e4" 0 - txOut1 = TxOut pkhAddr1 (Ada.lovelaceValueOf 90_000_000) Nothing + txOut1 = PublicKeyChainIndexTxOut pkhAddr1 (Ada.lovelaceValueOf 90_000_000) Nothing Nothing cenv' = def {ceCollateral = CollateralVar $ unsafePerformIO $ newTVarIO Nothing} initState = def & utxos .~ [(txOutRef1, txOut1)] & contractEnv .~ cenv' & collateralUtxo .~ Nothing @@ -150,7 +150,7 @@ curSymbol' = encodeByteString $ fromBuiltin $ Value.unCurrencySymbol curSymbol mintContract :: Contract () (Endpoint "SendAda" ()) Text CardanoTx mintContract = do let lookups = - Constraints.mintingPolicy mintingPolicy + Constraints.plutusV1MintingPolicy mintingPolicy let constraints = Constraints.mustMintValue (Value.singleton curSymbol "testToken" 5) <> Constraints.mustPayToPubKey diff --git a/test/Spec/BotPlutusInterface/Config.hs b/test/Spec/BotPlutusInterface/Config.hs index d188b010..9f74259b 100644 --- a/test/Spec/BotPlutusInterface/Config.hs +++ b/test/Spec/BotPlutusInterface/Config.hs @@ -69,43 +69,45 @@ pabConfigExample = , pcChainIndexUrl = BaseUrl Https "127.0.0.1" 8080 "" , pcNetwork = Mainnet , pcProtocolParams = - ProtocolParameters - { protocolParamProtocolVersion = (4, 1) - , protocolParamDecentralization = 2 % 4 - , protocolParamExtraPraosEntropy = Just $ makePraosNonce "HASH2" - , protocolParamMaxBlockHeaderSize = 1001 - , protocolParamMaxBlockBodySize = 1002 - , protocolParamMaxTxSize = 1003 - , protocolParamTxFeeFixed = 1004 - , protocolParamTxFeePerByte = 1005 - , protocolParamMinUTxOValue = Just 1006 - , protocolParamStakeAddressDeposit = Lovelace 1007 - , protocolParamStakePoolDeposit = Lovelace 1008 - , protocolParamMinPoolCost = Lovelace 1009 - , protocolParamPoolRetireMaxEpoch = EpochNo 19 - , protocolParamStakePoolTargetNum = 1010 - , protocolParamPoolPledgeInfluence = 2 % 8 - , protocolParamMonetaryExpansion = 4 % 1011 - , protocolParamTreasuryCut = 5 % 7 - , protocolParamUTxOCostPerWord = Nothing - , protocolParamCostModels = - Map.fromList - [ - ( AnyPlutusScriptVersion PlutusScriptV2 - , CostModel - ( Map.fromList - [ ("add_integer-cpu-arguments-intercept", 123456) - ] - ) - ) - ] - , protocolParamPrices = Just (ExecutionUnitPrices {priceExecutionSteps = 1 % 9, priceExecutionMemory = 1 % 10}) - , protocolParamMaxTxExUnits = Just (ExecutionUnits {executionSteps = 1012, executionMemory = 1013}) - , protocolParamMaxBlockExUnits = Just (ExecutionUnits {executionSteps = 1014, executionMemory = 1015}) - , protocolParamMaxValueSize = Just 1016 - , protocolParamCollateralPercent = Just 1017 - , protocolParamMaxCollateralInputs = Just 1018 - } + Just $ + ProtocolParameters + { protocolParamProtocolVersion = (4, 1) + , protocolParamDecentralization = Just $ 2 % 4 + , protocolParamExtraPraosEntropy = Just $ makePraosNonce "HASH2" + , protocolParamMaxBlockHeaderSize = 1001 + , protocolParamMaxBlockBodySize = 1002 + , protocolParamMaxTxSize = 1003 + , protocolParamTxFeeFixed = 1004 + , protocolParamTxFeePerByte = 1005 + , protocolParamMinUTxOValue = Just 1006 + , protocolParamStakeAddressDeposit = Lovelace 1007 + , protocolParamStakePoolDeposit = Lovelace 1008 + , protocolParamMinPoolCost = Lovelace 1009 + , protocolParamPoolRetireMaxEpoch = EpochNo 19 + , protocolParamStakePoolTargetNum = 1010 + , protocolParamPoolPledgeInfluence = 2 % 8 + , protocolParamMonetaryExpansion = 4 % 1011 + , protocolParamTreasuryCut = 5 % 7 + , protocolParamUTxOCostPerWord = Nothing + , protocolParamCostModels = + Map.fromList + [ + ( AnyPlutusScriptVersion PlutusScriptV2 + , CostModel + ( Map.fromList + [ ("add_integer-cpu-arguments-intercept", 123456) + ] + ) + ) + ] + , protocolParamPrices = Just (ExecutionUnitPrices {priceExecutionSteps = 1 % 9, priceExecutionMemory = 1 % 10}) + , protocolParamMaxTxExUnits = Just (ExecutionUnits {executionSteps = 1012, executionMemory = 1013}) + , protocolParamMaxBlockExUnits = Just (ExecutionUnits {executionSteps = 1014, executionMemory = 1015}) + , protocolParamMaxValueSize = Just 1016 + , protocolParamCollateralPercent = Just 1017 + , protocolParamMaxCollateralInputs = Just 1018 + , protocolParamUTxOCostPerByte = Just 0 + } , pcTipPollingInterval = 1021 , pcScriptFileDir = "./result-scripts2" , pcSigningKeyFileDir = "./signing-keys2" diff --git a/test/Spec/BotPlutusInterface/Contract.hs b/test/Spec/BotPlutusInterface/Contract.hs index efcf4f32..8a432025 100644 --- a/test/Spec/BotPlutusInterface/Contract.hs +++ b/test/Spec/BotPlutusInterface/Contract.hs @@ -20,17 +20,22 @@ import Data.Row (Row) import Data.Text (Text) import Data.Text qualified as Text import Data.Void (Void) +import Ledger (validatorHash) import Ledger qualified import Ledger.Ada qualified as Ada +import Ledger.Address (scriptHashAddress) import Ledger.Address qualified as Address import Ledger.Constraints qualified as Constraints import Ledger.Interval (interval) import Ledger.Scripts qualified as Scripts import Ledger.Slot (Slot) import Ledger.Time (POSIXTime (POSIXTime)) -import Ledger.Tx (CardanoTx, TxOut (TxOut), TxOutRef (TxOutRef)) +import Ledger.Tx ( + CardanoTx, + ChainIndexTxOut (PublicKeyChainIndexTxOut, ScriptChainIndexTxOut), + TxOutRef (TxOutRef), + ) import Ledger.Tx qualified as Tx -import Ledger.TxId qualified as TxId import Ledger.Value qualified as Value import NeatInterpolation (text) import Plutus.ChainIndex.Types (BlockId (..), Tip (..)) @@ -43,6 +48,7 @@ import Plutus.Contract ( utxosAt, waitNSlots, ) +import Plutus.Script.Utils.Scripts qualified as ScriptUtils import PlutusTx qualified import PlutusTx.Builtins (fromBuiltin) import Pretty.Diff ( @@ -55,6 +61,7 @@ import Spec.MockContract ( addr1, addr2, commandHistory, + currencySymbol1, files, observableState, paymentPkh2, @@ -104,17 +111,17 @@ tests = sendAda :: Assertion sendAda = do let txOutRef = TxOutRef "e406b0cf676fc2b1a9edb0617f259ad025c20ea6f0333820aa7cef1bfe7302e5" 0 - txOut = TxOut pkhAddr1 (Ada.lovelaceValueOf 1350) Nothing + txOut = PublicKeyChainIndexTxOut pkhAddr1 (Ada.lovelaceValueOf 13500000) Nothing Nothing -- We append the new utxo with the already present collateral utxo present at `pkhAddr1`. initState = def & utxos <>~ [(txOutRef, txOut)] - inTxId = encodeByteString $ fromBuiltin $ TxId.getTxId $ Tx.txOutRefId txOutRef + inTxId = encodeByteString $ fromBuiltin $ Tx.getTxId $ Tx.txOutRefId txOutRef - contract :: Contract () (Endpoint "SendAda" ()) Text CardanoTx + contract :: Plutus.Contract.Contract () (Plutus.Contract.Endpoint "SendAda" ()) Text CardanoTx contract = do let constraints = Constraints.mustPayToPubKey paymentPkh2 (Ada.lovelaceValueOf 1000) - submitTx constraints + Plutus.Contract.submitTx constraints assertContract contract initState $ \state -> assertCommandHistory @@ -122,32 +129,16 @@ sendAda = do [ ( 0 , [text| - cardano-cli query utxo - --address ${addr1} - --mainnet - |] - ) - , - ( 1 - , [text| - cardano-cli transaction calculate-min-required-utxo --alonzo-era - --tx-out ${addr2}+1000 - --protocol-params-file ./protocol.json - |] - ) - , - ( 2 - , [text| - cardano-cli transaction build-raw --alonzo-era + cardano-cli transaction build-raw --babbage-era --tx-in ${inTxId}#0 - --tx-out ${addr2}+1000 + --tx-out ${addr2}+857690 --required-signer ./signing-keys/signing-key-${pkh1'}.skey --fee 0 --protocol-params-file ./protocol.json --out-file ./txs/tx-? |] ) , - ( 4 + ( 2 , [text| cardano-cli transaction calculate-min-fee --tx-body-file ./txs/tx-? @@ -158,21 +149,21 @@ sendAda = do --mainnet |] ) - , -- Steps 4 to 11 are near repeats of 1, 2 and 3, to ensure min utxo values are met, and change is dispursed + , -- Steps 3 to 10 are near repeats of 1, 2 and 3, to ensure min utxo values are met, and change is dispursed - ( 17 + ( 13 , [text| - cardano-cli transaction build-raw --alonzo-era + cardano-cli transaction build-raw --babbage-era --tx-in ${inTxId}#0 - --tx-out ${addr2}+1000 - --tx-out ${addr1}+50 + --tx-out ${addr2}+857690 + --tx-out ${addr1}+12642010 --required-signer ./signing-keys/signing-key-${pkh1'}.skey --fee 300 --protocol-params-file ./protocol.json --out-file ./txs/tx-?.raw |] ) , - ( 18 + ( 14 , [text| cardano-cli transaction sign --tx-body-file ./txs/tx-?.raw @@ -185,27 +176,28 @@ sendAda = do sendAdaNoChange :: Assertion sendAdaNoChange = do let txOutRef = TxOutRef "e406b0cf676fc2b1a9edb0617f259ad025c20ea6f0333820aa7cef1bfe7302e5" 0 - txOut = TxOut pkhAddr1 (Ada.lovelaceValueOf 1200) Nothing + txOut = PublicKeyChainIndexTxOut pkhAddr1 (Ada.adaValueOf 50) Nothing Nothing initState = def & utxos <>~ [(txOutRef, txOut)] - inTxId = encodeByteString $ fromBuiltin $ TxId.getTxId $ Tx.txOutRefId txOutRef + inTxId = encodeByteString $ fromBuiltin $ Tx.getTxId $ Tx.txOutRefId txOutRef - contract :: Contract () (Endpoint "SendAda" ()) Text CardanoTx + contract :: Plutus.Contract.Contract () (Plutus.Contract.Endpoint "SendAda" ()) Text CardanoTx contract = do let constraints = Constraints.mustPayToPubKey paymentPkh2 (Ada.lovelaceValueOf 1000) - submitTx constraints + Plutus.Contract.submitTx constraints assertContract contract initState $ \state -> assertCommandHistory state [ - ( 8 + ( 7 , [text| - cardano-cli transaction build-raw --alonzo-era + cardano-cli transaction build-raw --babbage-era --tx-in ${inTxId}#0 - --tx-out ${addr2}+1000 + --tx-out ${addr2}+857690 + --tx-out ${addr1}+857690 --required-signer ./signing-keys/signing-key-${pkh1'}.skey - --fee 200 + --fee 0 --protocol-params-file ./protocol.json --out-file ./txs/tx-?.raw |] ) @@ -214,18 +206,18 @@ sendAdaNoChange = do sendAdaStaking :: Assertion sendAdaStaking = do let txOutRef = TxOutRef "e406b0cf676fc2b1a9edb0617f259ad025c20ea6f0333820aa7cef1bfe7302e5" 0 - txOut = TxOut pkhAddr1 (Ada.lovelaceValueOf 1200) Nothing + txOut = PublicKeyChainIndexTxOut pkhAddr1 (Ada.adaValueOf 50) Nothing Nothing initState = def & utxos <>~ [(txOutRef, txOut)] - inTxId = encodeByteString $ fromBuiltin $ TxId.getTxId $ Tx.txOutRefId txOutRef + inTxId = encodeByteString $ fromBuiltin $ Tx.getTxId $ Tx.txOutRefId txOutRef stakePkh3 = Address.StakePubKeyHash pkh3 addr2Staking = unsafeSerialiseAddress Mainnet (Ledger.pubKeyHashAddress paymentPkh2 (Just stakePkh3)) - contract :: Contract () (Endpoint "SendAda" ()) Text CardanoTx + contract :: Plutus.Contract.Contract () (Plutus.Contract.Endpoint "SendAda" ()) Text CardanoTx contract = do let constraints = Constraints.mustPayToPubKeyAddress paymentPkh2 stakePkh3 (Ada.lovelaceValueOf 1000) - submitTx constraints + Plutus.Contract.submitTx constraints assertContract contract initState $ \state -> assertCommandHistory @@ -233,32 +225,16 @@ sendAdaStaking = do [ ( 0 , [text| - cardano-cli query utxo - --address ${addr1} - --mainnet - |] - ) - , - ( 1 - , [text| - cardano-cli transaction calculate-min-required-utxo --alonzo-era - --tx-out ${addr2Staking}+1000 - --protocol-params-file ./protocol.json - |] - ) - , - ( 2 - , [text| - cardano-cli transaction build-raw --alonzo-era + cardano-cli transaction build-raw --babbage-era --tx-in ${inTxId}#0 - --tx-out ${addr2Staking}+1000 + --tx-out ${addr2Staking}+978370 --required-signer ./signing-keys/signing-key-${pkh1'}.skey --fee 0 --protocol-params-file ./protocol.json --out-file ./txs/tx-? |] ) , - ( 4 + ( 2 , [text| cardano-cli transaction calculate-min-fee --tx-body-file ./txs/tx-? @@ -270,85 +246,75 @@ sendAdaStaking = do |] ) , - ( 9 + ( 7 , [text| - cardano-cli transaction build-raw --alonzo-era + cardano-cli transaction build-raw --babbage-era --tx-in ${inTxId}#0 - --tx-out ${addr2Staking}+1000 + --tx-out ${addr2Staking}+978370 + --tx-out ${addr1}+857690 --required-signer ./signing-keys/signing-key-${pkh1'}.skey - --fee 200 + --fee 0 --protocol-params-file ./protocol.json --out-file ./txs/tx-?.raw |] ) , - ( 10 + ( 14 , [text| - cardano-cli transaction sign - --tx-body-file ./txs/tx-?.raw - --signing-key-file ./signing-keys/signing-key-${pkh1'}.skey - --out-file ./txs/tx-?.signed - |] + cardano-cli transaction sign + --tx-body-file ./txs/tx-?.raw + --signing-key-file ./signing-keys/signing-key-${pkh1'}.skey + --out-file ./txs/tx-?.signed + |] ) ] multisigSupport :: Assertion multisigSupport = do let txOutRef = TxOutRef "e406b0cf676fc2b1a9edb0617f259ad025c20ea6f0333820aa7cef1bfe7302e5" 0 - txOut = TxOut pkhAddr1 (Ada.lovelaceValueOf 1200) Nothing + txOut = PublicKeyChainIndexTxOut pkhAddr1 (Ada.adaValueOf 50) Nothing Nothing initState = def & utxos <>~ [(txOutRef, txOut)] - inTxId = encodeByteString $ fromBuiltin $ TxId.getTxId $ Tx.txOutRefId txOutRef + inTxId = encodeByteString $ fromBuiltin $ Tx.getTxId $ Tx.txOutRefId txOutRef - contract :: Contract Text (Endpoint "SendAda" ()) Text CardanoTx + contract :: Plutus.Contract.Contract Text (Plutus.Contract.Endpoint "SendAda" ()) Text CardanoTx contract = do let constraints = Constraints.mustPayToPubKey paymentPkh2 (Ada.lovelaceValueOf 1000) <> Constraints.mustBeSignedBy paymentPkh3 - submitTx constraints + Plutus.Contract.submitTx constraints -- Building and siging the tx should include both signing keys assertContract contract initState $ \state -> assertCommandHistory state [ - ( 4 + ( 7 , [text| - cardano-cli transaction calculate-min-fee - --tx-body-file ./txs/tx-? - --tx-in-count 1 - --tx-out-count 1 - --witness-count 2 - --protocol-params-file ./protocol.json - --mainnet - |] - ) - , - ( 9 - , [text| - cardano-cli transaction build-raw --alonzo-era + cardano-cli transaction build-raw --babbage-era --tx-in ${inTxId}#0 - --tx-out ${addr2}+1000 + --tx-out ${addr2}+857690 + --tx-out ${addr1}+857690 --required-signer ./signing-keys/signing-key-${pkh1'}.skey --required-signer ./signing-keys/signing-key-${pkh3'}.skey - --fee 200 + --fee 0 --protocol-params-file ./protocol.json --out-file ./txs/tx-?.raw |] ) , - ( 10 + ( 14 , [text| - cardano-cli transaction sign - --tx-body-file ./txs/tx-?.raw - --signing-key-file ./signing-keys/signing-key-${pkh1'}.skey - --signing-key-file ./signing-keys/signing-key-${pkh3'}.skey - --out-file ./txs/tx-?.signed - |] + cardano-cli transaction sign + --tx-body-file ./txs/tx-?.raw + --signing-key-file ./signing-keys/signing-key-${pkh1'}.skey + --signing-key-file ./signing-keys/signing-key-${pkh3'}.skey + --out-file ./txs/tx-?.signed + |] ) ] withoutSigning :: Assertion withoutSigning = do let txOutRef = TxOutRef "e406b0cf676fc2b1a9edb0617f259ad025c20ea6f0333820aa7cef1bfe7302e5" 0 - txOut = TxOut pkhAddr1 (Ada.lovelaceValueOf 1200) Nothing + txOut = PublicKeyChainIndexTxOut pkhAddr1 (Ada.adaValueOf 50) Nothing Nothing initState = def & utxos <>~ [(txOutRef, txOut)] @@ -358,28 +324,29 @@ withoutSigning = do , toVerificationKeyFile "./signing-keys" verificationKey1 , toVerificationKeyFile "./signing-keys" verificationKey3 ] - inTxId = encodeByteString $ fromBuiltin $ TxId.getTxId $ Tx.txOutRefId txOutRef + inTxId = encodeByteString $ fromBuiltin $ Tx.getTxId $ Tx.txOutRefId txOutRef - contract :: Contract Text (Endpoint "SendAda" ()) Text CardanoTx + contract :: Plutus.Contract.Contract Text (Plutus.Contract.Endpoint "SendAda" ()) Text CardanoTx contract = do let constraints = Constraints.mustPayToPubKey paymentPkh2 (Ada.lovelaceValueOf 1000) <> Constraints.mustBeSignedBy paymentPkh3 - submitTx constraints + Plutus.Contract.submitTx constraints -- Building and siging the tx should include both signing keys assertContract contract initState $ \state -> do assertCommandHistory state [ - ( 9 + ( 7 , [text| - cardano-cli transaction build-raw --alonzo-era + cardano-cli transaction build-raw --babbage-era --tx-in ${inTxId}#0 - --tx-out ${addr2}+1000 + --tx-out ${addr2}+857690 + --tx-out ${addr1}+857690 --required-signer ./signing-keys/signing-key-${pkh1'}.skey --required-signer-hash ${pkh3'} - --fee 200 + --fee 0 --protocol-params-file ./protocol.json --out-file ./txs/tx-?.raw |] ) @@ -390,37 +357,38 @@ sendTokens :: Assertion sendTokens = do let txOutRef1 = TxOutRef "08b27dbdcff9ab3b432638536ec7eab36c8a2e457703fb1b559dd754032ef431" 0 txOut1 = - TxOut + PublicKeyChainIndexTxOut pkhAddr1 - (Ada.lovelaceValueOf 1350 <> Value.singleton "abcd1234" "testToken" 100) + (Ada.adaValueOf 50 <> Value.singleton currencySymbol1 "testToken" 100) + Nothing Nothing txOutRef2 = TxOutRef "e406b0cf676fc2b1a9edb0617f259ad025c20ea6f0333820aa7cef1bfe7302e5" 1 txOut2 = - TxOut - pkhAddr1 - (Ada.lovelaceValueOf 1250) - Nothing + PublicKeyChainIndexTxOut pkhAddr1 (Ada.adaValueOf 50) Nothing Nothing initState = def & utxos <>~ [(txOutRef1, txOut1), (txOutRef2, txOut2)] - inTxId1 = encodeByteString $ fromBuiltin $ TxId.getTxId $ Tx.txOutRefId txOutRef1 + inTxId1 = encodeByteString $ fromBuiltin $ Tx.getTxId $ Tx.txOutRefId txOutRef1 - contract :: Contract () (Endpoint "SendAda" ()) Text CardanoTx + contract :: Plutus.Contract.Contract () (Plutus.Contract.Endpoint "SendAda" ()) Text CardanoTx contract = do let constraints = Constraints.mustPayToPubKey paymentPkh2 - (Ada.lovelaceValueOf 1000 <> Value.singleton "abcd1234" "testToken" 5) - submitTx constraints + (Ada.lovelaceValueOf 1000 <> Value.singleton currencySymbol1 "testToken" 5) + Plutus.Contract.submitTx constraints + + curSymbol' :: Text + curSymbol' = encodeByteString $ fromBuiltin $ Value.unCurrencySymbol currencySymbol1 assertContract contract initState $ \state -> assertCommandHistory state [ - ( 13 + ( 7 , [text| - cardano-cli transaction build-raw --alonzo-era + cardano-cli transaction build-raw --babbage-era --tx-in ${inTxId1}#0 - --tx-out ${addr2}+1000 + 5 abcd1234.74657374546F6B656E - --tx-out ${addr1}+50 + 95 abcd1234.74657374546F6B656E + --tx-out ${addr2}+1047330 + 5 ${curSymbol'}.74657374546F6B656E + --tx-out ${addr1}+48952370 + 95 ${curSymbol'}.74657374546F6B656E --required-signer ./signing-keys/signing-key-${pkh1'}.skey --fee 300 --protocol-params-file ./protocol.json --out-file ./txs/tx-?.raw @@ -432,37 +400,34 @@ sendTokensWithoutName :: Assertion sendTokensWithoutName = do let txOutRef1 = TxOutRef "08b27dbdcff9ab3b432638536ec7eab36c8a2e457703fb1b559dd754032ef431" 0 txOut1 = - TxOut - pkhAddr1 - (Ada.lovelaceValueOf 1350 <> Value.singleton "abcd1234" "" 100) - Nothing + PublicKeyChainIndexTxOut pkhAddr1 (Ada.adaValueOf 50 <> Value.singleton currencySymbol1 "" 100) Nothing Nothing txOutRef2 = TxOutRef "e406b0cf676fc2b1a9edb0617f259ad025c20ea6f0333820aa7cef1bfe7302e5" 1 txOut2 = - TxOut - pkhAddr1 - (Ada.lovelaceValueOf 1250) - Nothing + PublicKeyChainIndexTxOut pkhAddr1 (Ada.adaValueOf 50) Nothing Nothing initState = def & utxos <>~ [(txOutRef1, txOut1), (txOutRef2, txOut2)] - inTxId1 = encodeByteString $ fromBuiltin $ TxId.getTxId $ Tx.txOutRefId txOutRef1 + inTxId1 = encodeByteString $ fromBuiltin $ Tx.getTxId $ Tx.txOutRefId txOutRef1 - contract :: Contract () (Endpoint "SendAda" ()) Text CardanoTx + contract :: Plutus.Contract.Contract () (Plutus.Contract.Endpoint "SendAda" ()) Text CardanoTx contract = do let constraints = Constraints.mustPayToPubKey paymentPkh2 - (Ada.lovelaceValueOf 1000 <> Value.singleton "abcd1234" "" 5) - submitTx constraints + (Ada.lovelaceValueOf 1000 <> Value.singleton currencySymbol1 "" 5) + Plutus.Contract.submitTx constraints + + curSymbol' :: Text + curSymbol' = encodeByteString $ fromBuiltin $ Value.unCurrencySymbol currencySymbol1 assertContract contract initState $ \state -> assertCommandHistory state [ - ( 13 + ( 7 , [text| - cardano-cli transaction build-raw --alonzo-era + cardano-cli transaction build-raw --babbage-era --tx-in ${inTxId1}#0 - --tx-out ${addr2}+1000 + 5 abcd1234 - --tx-out ${addr1}+50 + 95 abcd1234 + --tx-out ${addr2}+1008540 + 5 ${curSymbol'} + --tx-out ${addr1}+48991160 + 95 ${curSymbol'} --required-signer ./signing-keys/signing-key-${pkh1'}.skey --fee 300 --protocol-params-file ./protocol.json --out-file ./txs/tx-?.raw @@ -473,50 +438,48 @@ sendTokensWithoutName = do mintTokens :: Assertion mintTokens = do let txOutRef = TxOutRef "e406b0cf676fc2b1a9edb0617f259ad025c20ea6f0333820aa7cef1bfe7302e5" 0 - txOut = TxOut pkhAddr1 (Ada.lovelaceValueOf 1_000_000) Nothing + txOut = PublicKeyChainIndexTxOut pkhAddr1 (Ada.adaValueOf 50) Nothing Nothing initState = def & utxos <>~ [(txOutRef, txOut)] - inTxId = encodeByteString $ fromBuiltin $ TxId.getTxId $ Tx.txOutRefId txOutRef - collateralTxId = encodeByteString $ fromBuiltin $ TxId.getTxId theCollateralTxId + inTxId = encodeByteString $ fromBuiltin $ Tx.getTxId $ Tx.txOutRefId txOutRef + collateralTxId = encodeByteString $ fromBuiltin $ Tx.getTxId theCollateralTxId mintingPolicy :: Scripts.MintingPolicy - mintingPolicy = - Scripts.mkMintingPolicyScript - $$(PlutusTx.compile [||(\_ _ -> ())||]) + mintingPolicy = Scripts.mkMintingPolicyScript $$(PlutusTx.compile [||(\_ _ -> ())||]) - curSymbol :: Value.CurrencySymbol + curSymbol :: Ledger.CurrencySymbol curSymbol = Ledger.scriptCurrencySymbol mintingPolicy curSymbol' :: Text curSymbol' = encodeByteString $ fromBuiltin $ Value.unCurrencySymbol curSymbol redeemerHash = - let (Scripts.RedeemerHash rh) = Ledger.redeemerHash Ledger.unitRedeemer + let (Scripts.RedeemerHash rh) = ScriptUtils.redeemerHash Scripts.unitRedeemer in encodeByteString $ fromBuiltin rh - contract :: Contract () (Endpoint "SendAda" ()) Text CardanoTx + contract :: Plutus.Contract.Contract () (Plutus.Contract.Endpoint "SendAda" ()) Text CardanoTx contract = do let lookups = - Constraints.mintingPolicy mintingPolicy + Constraints.plutusV1MintingPolicy mintingPolicy let constraints = Constraints.mustMintValue (Value.singleton curSymbol "testToken" 5) <> Constraints.mustPayToPubKey paymentPkh2 (Ada.lovelaceValueOf 1000 <> Value.singleton curSymbol "testToken" 5) - submitTxConstraintsWith @Void lookups constraints + Plutus.Contract.submitTxConstraintsWith @Void lookups constraints assertContract contract initState $ \state -> do assertCommandHistory state [ - ( 3 + ( 1 , [text| - cardano-cli transaction build-raw --alonzo-era + cardano-cli transaction build-raw --babbage-era --tx-in ${inTxId}#0 --tx-in-collateral ${collateralTxId}#0 - --tx-out ${addr2}+1000 + 5 ${curSymbol'}.74657374546F6B656E + --tx-out ${addr2}+1047330 + 5 ${curSymbol'}.74657374546F6B656E --mint-script-file ./result-scripts/policy-${curSymbol'}.plutus --mint-redeemer-file ./result-scripts/redeemer-${redeemerHash}.json - --mint-execution-units (500000,2000) + --mint-execution-units (0,0) --mint 5 ${curSymbol'}.74657374546F6B656E --required-signer ./signing-keys/signing-key-${pkh1'}.skey --fee 0 @@ -524,19 +487,19 @@ mintTokens = do |] ) , - ( 17 + ( 13 , [text| - cardano-cli transaction build-raw --alonzo-era + cardano-cli transaction build-raw --babbage-era --tx-in ${inTxId}#0 --tx-in-collateral ${collateralTxId}#0 - --tx-out ${addr2}+1000 + 5 ${curSymbol'}.74657374546F6B656E - --tx-out ${addr1}+496700 + --tx-out ${addr2}+1047330 + 5 ${curSymbol'}.74657374546F6B656E + --tx-out ${addr1}+48952370 --mint-script-file ./result-scripts/policy-${curSymbol'}.plutus --mint-redeemer-file ./result-scripts/redeemer-${redeemerHash}.json - --mint-execution-units (500000,2000) + --mint-execution-units (0,0) --mint 5 ${curSymbol'}.74657374546F6B656E --required-signer ./signing-keys/signing-key-${pkh1'}.skey - --fee 502300 + --fee 300 --protocol-params-file ./protocol.json --out-file ./txs/tx-?.raw |] ) @@ -554,9 +517,9 @@ mintTokens = do spendToValidator :: Assertion spendToValidator = do let txOutRef = TxOutRef "e406b0cf676fc2b1a9edb0617f259ad025c20ea6f0333820aa7cef1bfe7302e5" 0 - txOut = TxOut pkhAddr1 (Ada.lovelaceValueOf 1000) Nothing + txOut = PublicKeyChainIndexTxOut pkhAddr1 (Ada.adaValueOf 5) Nothing Nothing initState = def & utxos <>~ [(txOutRef, txOut)] - inTxId = encodeByteString $ fromBuiltin $ TxId.getTxId $ Tx.txOutRefId txOutRef + inTxId = encodeByteString $ fromBuiltin $ Tx.getTxId $ Tx.txOutRefId txOutRef validator :: Scripts.Validator validator = @@ -567,46 +530,46 @@ spendToValidator = do valHash = Ledger.validatorHash validator valAddr :: Ledger.Address - valAddr = Address.scriptAddress validator + valAddr = scriptHashAddress $ validatorHash validator valAddr' :: Text valAddr' = unsafeSerialiseAddress Mainnet valAddr valHash' :: Text valHash' = - let (Ledger.ValidatorHash vh) = valHash + let (Scripts.ValidatorHash vh) = valHash in encodeByteString $ fromBuiltin vh - datum :: Ledger.Datum - datum = Ledger.Datum $ PlutusTx.toBuiltinData (11 :: Integer) + datum :: Scripts.Datum + datum = Scripts.Datum $ PlutusTx.toBuiltinData (11 :: Integer) - datumHash :: Scripts.DatumHash - datumHash = Ledger.datumHash datum + datumHash :: ScriptUtils.DatumHash + datumHash = ScriptUtils.datumHash datum datumHash' = let (Scripts.DatumHash dh) = datumHash in encodeByteString $ fromBuiltin dh - contract :: Contract () (Endpoint "SendAda" ()) Text CardanoTx + contract :: Plutus.Contract.Contract () (Plutus.Contract.Endpoint "SendAda" ()) Text CardanoTx contract = do - utxos' <- utxosAt valAddr + utxos' <- Plutus.Contract.utxosAt valAddr let lookups = - Constraints.otherScript validator + Constraints.plutusV1OtherScript validator <> Constraints.otherData datum <> Constraints.unspentOutputs utxos' let constraints = Constraints.mustPayToOtherScript valHash datum (Ada.lovelaceValueOf 500) - submitTxConstraintsWith @Void lookups constraints + Plutus.Contract.submitTxConstraintsWith @Void lookups constraints assertContract contract initState $ \state -> do assertCommandHistory state [ - ( 2 + ( 1 , [text| - cardano-cli transaction build-raw --alonzo-era + cardano-cli transaction build-raw --babbage-era --tx-in ${inTxId}#0 - --tx-out ${valAddr'}+500 + --tx-out ${valAddr'}+1017160 --tx-out-datum-embed-file ./result-scripts/datum-${datumHash'}.json --required-signer ./signing-keys/signing-key-${pkh1'}.skey --fee 0 @@ -614,13 +577,13 @@ spendToValidator = do |] ) , - ( 17 + ( 13 , [text| - cardano-cli transaction build-raw --alonzo-era + cardano-cli transaction build-raw --babbage-era --tx-in ${inTxId}#0 - --tx-out ${valAddr'}+500 + --tx-out ${valAddr'}+1017160 --tx-out-datum-embed-file ./result-scripts/datum-${datumHash'}.json - --tx-out ${addr1}+200 + --tx-out ${addr1}+3982540 --required-signer ./signing-keys/signing-key-${pkh1'}.skey --fee 300 --protocol-params-file ./protocol.json --out-file ./txs/tx-?.raw @@ -639,88 +602,95 @@ spendToValidator = do redeemFromValidator :: Assertion redeemFromValidator = do let txOutRef = TxOutRef "e406b0cf676fc2b1a9edb0617f259ad025c20ea6f0333820aa7cef1bfe7302e5" 0 - txOut = TxOut pkhAddr1 (Ada.lovelaceValueOf 1_000_000) Nothing + txOut = PublicKeyChainIndexTxOut pkhAddr1 (Ada.adaValueOf 50) Nothing Nothing txOutRef' = TxOutRef "e406b0cf676fc2b1a9edb0617f259ad025c20ea6f0333820aa7cef1bfe7302e5" 1 - txOut' = TxOut valAddr (Ada.lovelaceValueOf 1250) (Just datumHash) + txOut' = + ScriptChainIndexTxOut + valAddr + (Ada.lovelaceValueOf 1250) + (datumHash, Nothing) + Nothing + (validatorHash validator, Just validator) initState = def & utxos <>~ [(txOutRef, txOut), (txOutRef', txOut')] - inTxId = encodeByteString $ fromBuiltin $ TxId.getTxId $ Tx.txOutRefId txOutRef - collateralTxId = encodeByteString $ fromBuiltin $ TxId.getTxId theCollateralTxId + inTxId = encodeByteString $ fromBuiltin $ Tx.getTxId $ Tx.txOutRefId txOutRef + collateralTxId = encodeByteString $ fromBuiltin $ Tx.getTxId theCollateralTxId validator :: Scripts.Validator validator = Scripts.mkValidatorScript $$(PlutusTx.compile [||(\_ _ _ -> ())||]) - valHash :: Ledger.ValidatorHash - valHash = Ledger.validatorHash validator + valHash :: Scripts.ValidatorHash + valHash = Scripts.validatorHash validator valAddr :: Ledger.Address - valAddr = Address.scriptAddress validator + valAddr = scriptHashAddress $ validatorHash validator valHash' :: Text valHash' = - let (Ledger.ValidatorHash vh) = valHash + let (Scripts.ValidatorHash vh) = valHash in encodeByteString $ fromBuiltin vh - datum :: Ledger.Datum - datum = Ledger.Datum $ PlutusTx.toBuiltinData (11 :: Integer) + datum :: Scripts.Datum + datum = Scripts.Datum $ PlutusTx.toBuiltinData (11 :: Integer) datumHash :: Scripts.DatumHash - datumHash = Ledger.datumHash datum + datumHash = ScriptUtils.datumHash datum datumHash' = let (Scripts.DatumHash dh) = datumHash in encodeByteString $ fromBuiltin dh redeemerHash = - let (Scripts.RedeemerHash rh) = Ledger.redeemerHash Ledger.unitRedeemer + let (Scripts.RedeemerHash rh) = ScriptUtils.redeemerHash Scripts.unitRedeemer in encodeByteString $ fromBuiltin rh - contract :: Contract () (Endpoint "SendAda" ()) Text CardanoTx + contract :: Plutus.Contract.Contract () (Plutus.Contract.Endpoint "SendAda" ()) Text CardanoTx contract = do - utxos' <- utxosAt valAddr + utxos' <- Plutus.Contract.utxosAt valAddr let lookups = - Constraints.otherScript validator + Constraints.plutusV1OtherScript validator <> Constraints.otherData datum <> Constraints.unspentOutputs utxos' let constraints = - Constraints.mustSpendScriptOutput txOutRef' Ledger.unitRedeemer + Constraints.mustSpendScriptOutput txOutRef' Scripts.unitRedeemer <> Constraints.mustPayToPubKey paymentPkh2 (Ada.lovelaceValueOf 500) - submitTxConstraintsWith @Void lookups constraints + Plutus.Contract.submitTxConstraintsWith @Void lookups constraints assertContract contract initState $ \state -> do assertCommandHistory state [ - ( 3 + ( 1 , [text| - cardano-cli transaction build-raw --alonzo-era + cardano-cli transaction build-raw --babbage-era + --tx-in ${collateralTxId}#0 --tx-in ${inTxId}#1 --tx-in-script-file ./result-scripts/validator-${valHash'}.plutus --tx-in-datum-file ./result-scripts/datum-${datumHash'}.json --tx-in-redeemer-file ./result-scripts/redeemer-${redeemerHash}.json --tx-in-execution-units (500000,2000) --tx-in-collateral ${collateralTxId}#0 - --tx-out ${addr2}+500 + --tx-out ${addr2}+857690 --required-signer ./signing-keys/signing-key-${pkh1'}.skey --fee 0 --protocol-params-file ./protocol.json --out-file ./txs/tx-? |] ) , - ( 20 + ( 13 , [text| - cardano-cli transaction build-raw --alonzo-era - --tx-in ${inTxId}#0 + cardano-cli transaction build-raw --babbage-era + --tx-in ${collateralTxId}#0 --tx-in ${inTxId}#1 --tx-in-script-file ./result-scripts/validator-${valHash'}.plutus --tx-in-datum-file ./result-scripts/datum-${datumHash'}.json --tx-in-redeemer-file ./result-scripts/redeemer-${redeemerHash}.json --tx-in-execution-units (500000,2000) --tx-in-collateral ${collateralTxId}#0 - --tx-out ${addr2}+500 - --tx-out ${addr1}+498350 + --tx-out ${addr2}+857690 + --tx-out ${addr1}+9143160 --required-signer ./signing-keys/signing-key-${pkh1'}.skey - --fee 502400 + --fee 400 --protocol-params-file ./protocol.json --out-file ./txs/tx-?.raw |] ) @@ -739,15 +709,15 @@ redeemFromValidator = do multiTx :: Assertion multiTx = do let txOutRef = TxOutRef "e406b0cf676fc2b1a9edb0617f259ad025c20ea6f0333820aa7cef1bfe7302e5" 0 - txOut = TxOut pkhAddr1 (Ada.lovelaceValueOf 1200) Nothing + txOut = PublicKeyChainIndexTxOut pkhAddr1 (Ada.adaValueOf 50) Nothing Nothing initState = def & utxos <>~ [(txOutRef, txOut)] - contract :: Contract () (Endpoint "SendAda" ()) Text [CardanoTx] + contract :: Plutus.Contract.Contract () (Plutus.Contract.Endpoint "SendAda" ()) Text [CardanoTx] contract = do let constraints = Constraints.mustPayToPubKey paymentPkh2 . Ada.lovelaceValueOf - tx1 <- submitTx $ constraints 1000 - tx2 <- submitTx $ constraints 850 + tx1 <- Plutus.Contract.submitTx $ constraints 1000 + tx2 <- Plutus.Contract.submitTx $ constraints 850 pure [tx1, tx2] @@ -768,26 +738,26 @@ multiTx = do withValidRange :: Assertion withValidRange = do let txOutRef = TxOutRef "e406b0cf676fc2b1a9edb0617f259ad025c20ea6f0333820aa7cef1bfe7302e5" 0 - txOut = TxOut pkhAddr1 (Ada.lovelaceValueOf 1200) Nothing + txOut = PublicKeyChainIndexTxOut pkhAddr1 (Ada.adaValueOf 50) Nothing Nothing initState = def & utxos <>~ [(txOutRef, txOut)] - inTxId = encodeByteString $ fromBuiltin $ TxId.getTxId $ Tx.txOutRefId txOutRef + inTxId = encodeByteString $ fromBuiltin $ Tx.getTxId $ Tx.txOutRefId txOutRef - contract :: Contract () (Endpoint "SendAda" ()) Text CardanoTx + contract :: Plutus.Contract.Contract () (Plutus.Contract.Endpoint "SendAda" ()) Text CardanoTx contract = do let constraints = Constraints.mustPayToPubKey paymentPkh2 (Ada.lovelaceValueOf 1000) <> Constraints.mustValidateIn (interval (POSIXTime 1643636293000) (POSIXTime 1646314693000)) - submitTx constraints + Plutus.Contract.submitTx constraints assertContract contract initState $ \state -> assertCommandHistory state [ - ( 2 + ( 0 , [text| - cardano-cli transaction build-raw --alonzo-era + cardano-cli transaction build-raw --babbage-era --tx-in ${inTxId}#0 - --tx-out ${addr2}+1000 + --tx-out ${addr2}+857690 --invalid-before 47577202 --invalid-hereafter 50255602 --required-signer ./signing-keys/signing-key-${pkh1'}.skey @@ -796,15 +766,16 @@ withValidRange = do |] ) , - ( 9 + ( 7 , [text| - cardano-cli transaction build-raw --alonzo-era + cardano-cli transaction build-raw --babbage-era --tx-in ${inTxId}#0 - --tx-out ${addr2}+1000 + --tx-out ${addr2}+857690 + --tx-out ${addr1}+857690 --invalid-before 47577202 --invalid-hereafter 50255602 --required-signer ./signing-keys/signing-key-${pkh1'}.skey - --fee 200 + --fee 0 --protocol-params-file ./protocol.json --out-file ./txs/tx-?.raw |] ) @@ -813,15 +784,15 @@ withValidRange = do useWriter :: Assertion useWriter = do let txOutRef = TxOutRef "e406b0cf676fc2b1a9edb0617f259ad025c20ea6f0333820aa7cef1bfe7302e5" 0 - txOut = TxOut pkhAddr1 (Ada.lovelaceValueOf 1200) Nothing + txOut = PublicKeyChainIndexTxOut pkhAddr1 (Ada.adaValueOf 50) Nothing Nothing initState = def & utxos <>~ [(txOutRef, txOut)] - contract :: Contract (Last Text) (Endpoint "SendAda" ()) Text CardanoTx + contract :: Plutus.Contract.Contract (Last Text) (Plutus.Contract.Endpoint "SendAda" ()) Text CardanoTx contract = do - tell $ Last $ Just "Init contract" + Plutus.Contract.tell $ Last $ Just "Init contract" let constraints = Constraints.mustPayToPubKey paymentPkh2 (Ada.lovelaceValueOf 1000) - submitTx constraints + Plutus.Contract.submitTx constraints assertContract contract initState $ \state -> do (state ^. observableState) @@ -833,8 +804,8 @@ waitNextBlock = do initTip = Tip initSlot (BlockId "ab12") 4 initState = def & tip .~ initTip - contract :: Contract () (Endpoint "SendAda" ()) Text Slot - contract = waitNSlots 1 + contract :: Plutus.Contract.Contract () (Plutus.Contract.Endpoint "SendAda" ()) Text Slot + contract = Plutus.Contract.waitNSlots 1 (result, state) = runContractPure contract initState @@ -867,7 +838,7 @@ assertFiles state expectedFiles = assertContractWithTxId :: forall (w :: Type) (s :: Row Type). (ToJSON w, Monoid w) => - Contract w s Text CardanoTx -> + Plutus.Contract.Contract w s Text CardanoTx -> MockContractState w -> (MockContractState w -> Text -> Assertion) -> Assertion @@ -877,13 +848,13 @@ assertContractWithTxId contract initState assertion = do case result of Left errMsg -> assertFailure (show errMsg) Right tx -> - let outTxId = encodeByteString $ fromBuiltin $ TxId.getTxId $ Tx.getCardanoTxId tx + let outTxId = encodeByteString $ fromBuiltin $ Tx.getTxId $ Tx.getCardanoTxId tx in assertion state outTxId assertContract :: forall (w :: Type) (s :: Row Type). (ToJSON w, Monoid w) => - Contract w s Text CardanoTx -> + Plutus.Contract.Contract w s Text CardanoTx -> MockContractState w -> (MockContractState w -> Assertion) -> Assertion diff --git a/test/Spec/BotPlutusInterface/ContractStats.hs b/test/Spec/BotPlutusInterface/ContractStats.hs index c126cd0e..4c39c99f 100644 --- a/test/Spec/BotPlutusInterface/ContractStats.hs +++ b/test/Spec/BotPlutusInterface/ContractStats.hs @@ -8,10 +8,10 @@ import Control.Lens ((&), (.~), (^.)) import Data.Default (def) import Data.Text (Text) import Data.Text qualified as Text -import Ledger (PaymentPubKeyHash (unPaymentPubKeyHash)) +import Ledger (ChainIndexTxOut (PublicKeyChainIndexTxOut), PaymentPubKeyHash (unPaymentPubKeyHash)) import Ledger.Ada qualified as Ada import Ledger.Constraints qualified as Constraints -import Ledger.Tx (CardanoTx, TxOut (TxOut), TxOutRef (TxOutRef)) +import Ledger.Tx (CardanoTx, TxOutRef (TxOutRef)) import Plutus.Contract ( Contract (..), Endpoint, @@ -42,7 +42,7 @@ tests = budgetSavingEnabled :: Assertion budgetSavingEnabled = do let txOutRef = TxOutRef "e406b0cf676fc2b1a9edb0617f259ad025c20ea6f0333820aa7cef1bfe7302e5" 0 - txOut = TxOut pkhAddr1 (Ada.lovelaceValueOf 1350) Nothing + txOut = PublicKeyChainIndexTxOut pkhAddr1 (Ada.adaValueOf 50) Nothing Nothing initState = def & utxos .~ [(txOutRef, txOut)] & contractEnv .~ contractEnv' @@ -62,7 +62,7 @@ budgetSavingEnabled = do budgetSavingDisabled :: Assertion budgetSavingDisabled = do let txOutRef = TxOutRef "e406b0cf676fc2b1a9edb0617f259ad025c20ea6f0333820aa7cef1bfe7302e5" 0 - txOut = TxOut pkhAddr1 (Ada.lovelaceValueOf 1350) Nothing + txOut = PublicKeyChainIndexTxOut pkhAddr1 (Ada.adaValueOf 50) Nothing Nothing initState = def & utxos .~ [(txOutRef, txOut)] contract :: Contract () (Endpoint "SendAda" ()) Text CardanoTx diff --git a/test/Spec/BotPlutusInterface/Server.hs b/test/Spec/BotPlutusInterface/Server.hs index 08bb4169..f96c61d8 100644 --- a/test/Spec/BotPlutusInterface/Server.hs +++ b/test/Spec/BotPlutusInterface/Server.hs @@ -9,7 +9,7 @@ import BotPlutusInterface.Types ( SomeBuiltin (..), ) -import Ledger.TxId (TxId) +import Ledger.Tx (TxId) import Playground.Types (FunctionSchema) import Schema (FormSchema) @@ -115,7 +115,7 @@ testTxFileName = unpack $ txFileName txHash "raw" rawTx :: RawTx rawTx = RawTx - { _type = "TxBodyAlonzo" + { _type = "TxBodyBabbage" , _description = "description" , _cborHex = "hex" } diff --git a/test/Spec/BotPlutusInterface/TxStatusChange.hs b/test/Spec/BotPlutusInterface/TxStatusChange.hs index c99abcad..14d91c32 100644 --- a/test/Spec/BotPlutusInterface/TxStatusChange.hs +++ b/test/Spec/BotPlutusInterface/TxStatusChange.hs @@ -9,10 +9,10 @@ import Control.Lens ((&), (.~), (^.)) import Data.Default (def) import Data.Text (Text) import Data.Text qualified as Text -import Ledger (PaymentPubKeyHash (unPaymentPubKeyHash), getCardanoTxId) +import Ledger (ChainIndexTxOut (PublicKeyChainIndexTxOut), PaymentPubKeyHash (unPaymentPubKeyHash), getCardanoTxId) import Ledger.Ada qualified as Ada import Ledger.Constraints qualified as Constraints -import Ledger.Tx (TxOut (TxOut), TxOutRef (TxOutRef)) +import Ledger.Tx (TxOutRef (TxOutRef)) import Plutus.ChainIndex (RollbackState (Unknown), Tip (TipAtGenesis), TxStatus) import Plutus.ChainIndex.Types (Tip (Tip)) import Plutus.Contract ( @@ -48,7 +48,7 @@ tests = testTxFoundAndConfirmed :: Assertion testTxFoundAndConfirmed = do let txOutRef = TxOutRef "e406b0cf676fc2b1a9edb0617f259ad025c20ea6f0333820aa7cef1bfe7302e5" 0 - txOut = TxOut pkhAddr1 (Ada.lovelaceValueOf 1350) Nothing + txOut = PublicKeyChainIndexTxOut pkhAddr1 (Ada.adaValueOf 50) Nothing Nothing initState = def & utxos .~ [(txOutRef, txOut)] & contractEnv .~ contractEnv' diff --git a/test/Spec/BotPlutusInterface/UtxoParser.hs b/test/Spec/BotPlutusInterface/UtxoParser.hs deleted file mode 100644 index 9a255d30..00000000 --- a/test/Spec/BotPlutusInterface/UtxoParser.hs +++ /dev/null @@ -1,144 +0,0 @@ -{-# LANGUAGE NamedFieldPuns #-} -{-# LANGUAGE QuasiQuotes #-} -{-# LANGUAGE TemplateHaskell #-} - -module Spec.BotPlutusInterface.UtxoParser (tests) where - -import BotPlutusInterface.UtxoParser qualified as UtxoParser -import Data.Attoparsec.Text (parseOnly) -import Data.ByteString qualified as ByteString -import Data.Text (Text) -import Ledger qualified -import Ledger.Ada qualified as Ada -import Ledger.Address (Address) -import Ledger.Tx ( - ChainIndexTxOut (PublicKeyChainIndexTxOut, ScriptChainIndexTxOut), - TxOutRef (TxOutRef), - ) -import Ledger.Value (TokenName (TokenName)) -import Ledger.Value qualified as Value -import NeatInterpolation (text) -import PlutusTx.Builtins (toBuiltin) -import Test.Tasty (TestTree, testGroup) -import Test.Tasty.HUnit (Assertion, testCase, (@?=)) -import Prelude - -pubKeyHashAddress :: Ledger.PubKeyHash -> Address -pubKeyHashAddress pkh = Ledger.pubKeyHashAddress (Ledger.PaymentPubKeyHash pkh) Nothing - -{- | Tests for 'cardano-cli query utxo' result parsers - - @since 0.1 --} -tests :: TestTree -tests = - testGroup - "BotPlutusInterface.UtxoParser" - [ testCase "Without utxo" withoutUtxo - , testCase "Single utxo, ada only" singleAdaOnly - , testCase "Multiple utxos, ada only" multiAdaOnly - , testCase "Single utxo, ada and native tokens" singleWithNativeTokens - , testCase "Single utxo, with datum" singleWithDatum - ] - -withoutUtxo :: Assertion -withoutUtxo = do - let addr = pubKeyHashAddress "0000" - testUtxoParser - addr - [text| TxHash TxIx Amount - -------------------------------------------------------------------------------------- - |] - [] - -singleAdaOnly :: Assertion -singleAdaOnly = do - let addr = pubKeyHashAddress "0000" - testUtxoParser - addr - [text| TxHash TxIx Amount - -------------------------------------------------------------------------------------- - 384de3f29396fdf687551e3f9e05bd400adcd277720c71f1d2b61f17f5183e51 0 5000000000 lovelace + TxOutDatumNone - |] - [ - ( TxOutRef "384de3f29396fdf687551e3f9e05bd400adcd277720c71f1d2b61f17f5183e51" 0 - , PublicKeyChainIndexTxOut addr (Ada.lovelaceValueOf 5000000000) - ) - ] - -multiAdaOnly :: Assertion -multiAdaOnly = do - let addr = pubKeyHashAddress "0000" - testUtxoParser - addr - [text| TxHash TxIx Amount - -------------------------------------------------------------------------------------- - 384de3f29396fdf687551e3f9e05bd400adcd277720c71f1d2b61f17f5183e51 0 5000000000 lovelace + TxOutDatumNone - 52a003b3f4956433429631afe4002f82a924a5a7a891db7ae1f6434797a57dff 1 89835907 lovelace + TxOutDatumNone - d8a5630a9d7e913f9d186c95e5138a239a4e79ece3414ac894dbf37280944de3 0 501000123456 lovelace + TxOutDatumNone - |] - [ - ( TxOutRef "384de3f29396fdf687551e3f9e05bd400adcd277720c71f1d2b61f17f5183e51" 0 - , PublicKeyChainIndexTxOut addr (Ada.lovelaceValueOf 5000000000) - ) - , - ( TxOutRef "52a003b3f4956433429631afe4002f82a924a5a7a891db7ae1f6434797a57dff" 1 - , PublicKeyChainIndexTxOut addr (Ada.lovelaceValueOf 89835907) - ) - , - ( TxOutRef "d8a5630a9d7e913f9d186c95e5138a239a4e79ece3414ac894dbf37280944de3" 0 - , PublicKeyChainIndexTxOut addr (Ada.lovelaceValueOf 501000123456) - ) - ] - -singleWithNativeTokens :: Assertion -singleWithNativeTokens = do - let addr = pubKeyHashAddress "0000" - token = - Value.assetClass "057910a2c93551443cb2c0544d1d65da3fb033deaa79452bd431ee08" "testToken" - tokenWithRawByteString = - Value.assetClass - "7c6de14062b27c3dc3ba9f232ade32efe22fb8e2ae76b24f33212fdb" - (TokenName (toBuiltin (ByteString.pack [1, 35, 69, 103, 137, 171, 205, 239]))) - tokenWithEmptyName = - Value.assetClass "98a759ed2e20f6d83aa4d37d028d4bbb547a696fc345d54126188614" "" - testUtxoParser - addr - [text| TxHash TxIx Amount - -------------------------------------------------------------------------------------- - 384de3f29396fdf687551e3f9e05bd400adcd277720c71f1d2b61f17f5183e51 0 1234 lovelace + 2345 057910a2c93551443cb2c0544d1d65da3fb033deaa79452bd431ee08.74657374546f6b656e + 3456 7c6de14062b27c3dc3ba9f232ade32efe22fb8e2ae76b24f33212fdb.0x0123456789abcdef + 4567 98a759ed2e20f6d83aa4d37d028d4bbb547a696fc345d54126188614 + TxOutDatumNone - |] - [ - ( TxOutRef "384de3f29396fdf687551e3f9e05bd400adcd277720c71f1d2b61f17f5183e51" 0 - , PublicKeyChainIndexTxOut - addr - ( Ada.lovelaceValueOf 1234 - <> Value.assetClassValue token 2345 - <> Value.assetClassValue tokenWithRawByteString 3456 - <> Value.assetClassValue tokenWithEmptyName 4567 - ) - ) - ] - -singleWithDatum :: Assertion -singleWithDatum = do - let addr = Ledger.scriptHashAddress "0000" - testUtxoParser - addr - [text| TxHash TxIx Amount - -------------------------------------------------------------------------------------- - 384de3f29396fdf687551e3f9e05bd400adcd277720c71f1d2b61f17f5183e51 0 5000000000 lovelace + TxOutDatumHash ScriptDataInAlonzoEra "2cdb268baecefad822e5712f9e690e1787f186f5c84c343ffdc060b21f0241e0" - |] - [ - ( TxOutRef "384de3f29396fdf687551e3f9e05bd400adcd277720c71f1d2b61f17f5183e51" 0 - , ScriptChainIndexTxOut - addr - (Left "0000") - (Left "2cdb268baecefad822e5712f9e690e1787f186f5c84c343ffdc060b21f0241e0") - (Ada.lovelaceValueOf 5000000000) - ) - ] - -testUtxoParser :: Address -> Text -> [(TxOutRef, ChainIndexTxOut)] -> Assertion -testUtxoParser addr output expected = - parseOnly (UtxoParser.utxoMapParser addr) output @?= Right expected diff --git a/test/Spec/MockContract.hs b/test/Spec/MockContract.hs index b0166c6f..2fc62672 100644 --- a/test/Spec/MockContract.hs +++ b/test/Spec/MockContract.hs @@ -31,6 +31,7 @@ module Spec.MockContract ( pkhAddr1, pkhAddr2, pkhAddr3, + currencySymbol1, -- Test interpreter runPABEffectPure, runContractPure, @@ -53,9 +54,11 @@ module Spec.MockContract ( ) where import BotPlutusInterface.CardanoCLI (unsafeSerialiseAddress) +import BotPlutusInterface.CardanoNode.Effects (NodeQuery (PParams, UtxosAt)) +import BotPlutusInterface.CardanoNode.Query (toQueryError) import BotPlutusInterface.Collateral (removeCollateralFromPage) import BotPlutusInterface.Contract (handleContract) -import BotPlutusInterface.Effects (PABEffect (..), ShellArgs (..)) +import BotPlutusInterface.Effects (PABEffect (..), ShellArgs (..), calcMinUtxo) import BotPlutusInterface.Files qualified as Files import BotPlutusInterface.TimeSlot (TimeSlotConversionError) import BotPlutusInterface.Types ( @@ -77,6 +80,8 @@ import Cardano.Api ( Key (VerificationKey, getVerificationKey), NetworkId (Mainnet), PaymentKey, + PlutusScriptVersion (PlutusScriptV2), + Script (PlutusScript), SigningKey (PaymentSigningKey), TextEnvelope (TextEnvelope, teDescription, teRawCBOR, teType), TextEnvelopeDescr, @@ -84,12 +89,15 @@ import Cardano.Api ( deserialiseFromTextEnvelope, getVerificationKey, serialiseToTextEnvelope, + toScriptInAnyLang, ) +import Cardano.Api.Shelley (PlutusScript (PlutusScriptSerialised)) import Cardano.Crypto.DSIGN (genKeyDSIGN) import Cardano.Crypto.Seed (mkSeedFromBytes) +import Codec.Serialise (serialise) import Control.Applicative (liftA2) import Control.Concurrent.STM (newTVarIO) -import Control.Lens (at, set, (%~), (&), (<|), (?~), (^.), (^..), _1) +import Control.Lens (at, set, view, (%~), (&), (<|), (?~), (^.), (^..), _1) import Control.Lens.TH (makeLenses) import Control.Monad (join) import Control.Monad.Freer (Eff, reinterpret2, run) @@ -102,6 +110,8 @@ import Data.Aeson.Extras (encodeByteString) import Data.Bool (bool) import Data.ByteString qualified as ByteString import Data.ByteString.Char8 qualified as BS +import Data.ByteString.Lazy qualified as LBS +import Data.ByteString.Short qualified as SBS import Data.Default (Default (def)) import Data.Either.Combinators (fromRight, mapLeft) import Data.Hex (hex, unhex) @@ -131,19 +141,31 @@ import Ledger ( import Ledger qualified import Ledger.Ada qualified as Ada import Ledger.Crypto (PubKey, PubKeyHash) -import Ledger.Scripts (DatumHash (DatumHash)) +import Ledger.Scripts (Datum (Datum), DatumHash (DatumHash)) import Ledger.Slot (Slot (getSlot)) -import Ledger.Tx (TxOut (TxOut), TxOutRef (TxOutRef)) +import Ledger.Tx ( + ChainIndexTxOut (PublicKeyChainIndexTxOut, ScriptChainIndexTxOut), + TxId (TxId), + TxOutRef (TxOutRef), + ciTxOutAddress, + ciTxOutValue, + ) import Ledger.Tx qualified as Tx -import Ledger.TxId (TxId (TxId)) import Ledger.Value qualified as Value import NeatInterpolation (text) -import Plutus.ChainIndex.Api (UtxosResponse (..)) -import Plutus.ChainIndex.Tx (ChainIndexTx (..), ChainIndexTxOutputs (ValidTx)) +import Plutus.ChainIndex.Api (QueryResponse (QueryResponse), UtxosResponse (..)) +import Plutus.ChainIndex.Tx ( + ChainIndexTx (..), + ChainIndexTxOutputs (ValidTx), + OutputDatum (NoOutputDatum, OutputDatum, OutputDatumHash), + ReferenceScript (ReferenceScriptInAnyLang, ReferenceScriptNone), + ) +import Plutus.ChainIndex.Tx qualified as CIT import Plutus.ChainIndex.Types (BlockId (..), BlockNumber (unBlockNumber), Tip (..)) import Plutus.Contract (Contract (Contract)) import Plutus.Contract.Effects (ChainIndexQuery (..), ChainIndexResponse (..)) import Plutus.PAB.Core.ContractInstance.STM (Activity (Active)) +import Plutus.V1.Ledger.Api qualified as V1 import Plutus.V1.Ledger.Credential (Credential (PubKeyCredential)) import PlutusTx.Builtins (fromBuiltin) import PlutusTx.Builtins.Internal (BuiltinByteString (BuiltinByteString)) @@ -153,6 +175,9 @@ import Text.Read (readMaybe) import Wallet.Types (ContractInstanceId (ContractInstanceId)) import Prelude +currencySymbol1 :: Ledger.CurrencySymbol +currencySymbol1 = "363d3944282b3d16b239235a112c0f6e2f1195de5067f61c0dfc0f5f" + signingKey1, signingKey2, signingKey3 :: SigningKey PaymentKey signingKey1 = PaymentSigningKey $ genKeyDSIGN $ mkSeedFromBytes $ ByteString.replicate 32 0 signingKey2 = PaymentSigningKey $ genKeyDSIGN $ mkSeedFromBytes $ ByteString.replicate 32 1 @@ -242,7 +267,7 @@ data MockContractState w = MockContractState , _observableState :: w , _logHistory :: [(LogContext, LogLevel, PP.Doc ())] , _contractEnv :: ContractEnvironment w - , _utxos :: [(TxOutRef, TxOut)] + , _utxos :: [(TxOutRef, ChainIndexTxOut)] , _tip :: Tip , _collateralUtxo :: Maybe CollateralUtxo } @@ -268,7 +293,7 @@ instance Monoid w => Default (MockContractState w) where _utxos = [ ( collateralTxOutRef theCollateralUtxo - , TxOut pkhAddr1 (Ada.lovelaceValueOf $ toInteger $ pcCollateralSize def) Nothing + , PublicKeyChainIndexTxOut pkhAddr1 (Ada.lovelaceValueOf $ toInteger $ pcCollateralSize def) Nothing Nothing ) ] , _tip = Tip 1000 (BlockId "ab12") 4 @@ -353,6 +378,10 @@ runPABEffectPure initState req = go (POSIXTimeRangeToSlotRange ptr) = mockSlotRange ptr go GetInMemCollateral = _collateralUtxo <$> get @(MockContractState w) go (SetInMemCollateral collateral) = modify @(MockContractState w) $ set collateralUtxo (Just collateral) + go (QueryNode query) = mockQueryNode query + go (MinUtxo utxo) = + return $ + calcMinUtxo (def {pcProtocolParams = Just def}) utxo incSlot :: forall (v :: Type). MockContract w v -> MockContract w v incSlot mc = mc <* modify @(MockContractState w) (tip %~ incTip) @@ -434,7 +463,7 @@ mockQueryTip = do pure $ Text.unpack [text|{ - "era": "Alonzo", + "era": "Babbage", "syncProgress": "100.00", "hash": "${blockId}", "epoch": 1, @@ -450,10 +479,10 @@ mockQueryUtxo addr = do pure $ mockQueryUtxoOut $ filter - ((==) addr . unsafeSerialiseAddress network . Ledger.txOutAddress . snd) + ((==) addr . unsafeSerialiseAddress network . view ciTxOutAddress . snd) (state ^. utxos) -mockQueryUtxoOut :: [(TxOutRef, TxOut)] -> String +mockQueryUtxoOut :: [(TxOutRef, ChainIndexTxOut)] -> String mockQueryUtxoOut utxos' = Text.unpack $ Text.unlines @@ -461,19 +490,31 @@ mockQueryUtxoOut utxos' = , "--------------------------------------------------------------------------------------" , Text.unlines $ map - ( \(TxOutRef (TxId txId) txIx, TxOut _ val datumHash) -> + ( \(TxOutRef (TxId txId) txIx, ciTxOut) -> let txId' = encodeByteString $ fromBuiltin txId txIx' = Text.pack $ show txIx - amts = valueToUtxoOut val - datumHash' = case datumHash of - Nothing -> "TxOutDatumNone" - Just (DatumHash dh) -> - "TxDatumHash ScriptDataInAlonzoEra " <> encodeByteString (fromBuiltin dh) - in [text|${txId'} ${txIx'} ${amts} + ${datumHash'}|] + amts = valueToUtxoOut $ view ciTxOutValue ciTxOut + outDatum = txOutToDatum ciTxOut + in [text|${txId'} ${txIx'} ${amts} + ${outDatum}|] ) utxos' ] +txOutToDatum :: ChainIndexTxOut -> Text +txOutToDatum = + \case + PublicKeyChainIndexTxOut _ _ Nothing _ -> "TxOutDatumNone" + PublicKeyChainIndexTxOut _ _ (Just (dh, Nothing)) _ -> printDatumHash dh + PublicKeyChainIndexTxOut _ _ (Just (_, Just (Datum d))) _ -> printDatum d + ScriptChainIndexTxOut _ _ (dh, Nothing) _ _ -> printDatumHash dh + ScriptChainIndexTxOut _ _ (_, Just (Datum d)) _ _ -> printDatum d + where + printDatumHash (DatumHash dh) = + "TxDatumHash ScriptDataInBabbageEra " <> encodeByteString (fromBuiltin dh) + printDatum d = + "TxOutDatumInline ReferenceTxInsScriptsInlineDatumsInBabbageEra " + <> Text.pack (show d) + mockBudget :: String mockBudget = "Some budget" @@ -590,7 +631,13 @@ mockQueryChainIndex = \case throwError @Text "RedeemerFromHash is unimplemented" TxOutFromRef txOutRef -> do state <- get @(MockContractState w) - pure $ TxOutRefResponse $ Tx.fromTxOut =<< lookup txOutRef (state ^. utxos) + pure $ TxOutRefResponse $ lookup txOutRef (state ^. utxos) + UnspentTxOutFromRef txOutRef -> do + state <- get @(MockContractState w) + pure $ UnspentTxOutResponse $ lookup txOutRef (state ^. utxos) + UnspentTxOutSetAtAddress _ _ -> do + state <- get @(MockContractState w) + pure $ UnspentTxOutsAtResponse $ QueryResponse (state ^. utxos) Nothing TxFromTxId txId -> if txId == nonExistingTxId then pure $ TxIdResponse Nothing @@ -649,16 +696,50 @@ mockQueryChainIndex = \case pure $ GetTipResponse (state ^. tip) -- | Fills in gaps of inputs with garbage TxOuts, so that the indexes we know about are in the correct positions -buildOutputsFromKnownUTxOs :: [(TxOutRef, TxOut)] -> TxId -> ChainIndexTxOutputs -buildOutputsFromKnownUTxOs knownUtxos txId = ValidTx $ fillGaps sortedRelatedRefs 0 +buildOutputsFromKnownUTxOs :: [(TxOutRef, ChainIndexTxOut)] -> TxId -> ChainIndexTxOutputs +buildOutputsFromKnownUTxOs knownUtxos txId = ValidTx $ map converCiTxOut $ fillGaps sortedRelatedRefs 0 where sortedRelatedRefs = sortOn (Tx.txOutRefIdx . fst) $ filter ((== txId) . Tx.txOutRefId . fst) knownUtxos - fillGaps :: [(TxOutRef, TxOut)] -> Integer -> [TxOut] + fillGaps :: [(TxOutRef, ChainIndexTxOut)] -> Integer -> [ChainIndexTxOut] fillGaps [] _ = [] fillGaps (out@(TxOutRef _ n', txOut) : outs) n | n' == n = txOut : fillGaps outs (n + 1) | otherwise = defTxOut : fillGaps (out : outs) (n + 1) - defTxOut = TxOut (Ledger.Address (PubKeyCredential "") Nothing) mempty Nothing + defTxOut = + PublicKeyChainIndexTxOut + (Ledger.Address (PubKeyCredential "") Nothing) + mempty + Nothing + Nothing + +converCiTxOut :: ChainIndexTxOut -> CIT.ChainIndexTxOut +converCiTxOut (PublicKeyChainIndexTxOut addr val dat maybeRefSc) = + CIT.ChainIndexTxOut addr val (convertMaybeDatum dat) (convertRefScript maybeRefSc) +converCiTxOut (ScriptChainIndexTxOut addr val eitherDatum maybeRefSc _) = + let datum = case eitherDatum of + (dh, Nothing) -> OutputDatumHash dh + (_, Just d) -> OutputDatum d + in CIT.ChainIndexTxOut addr val datum (convertRefScript maybeRefSc) + +convertMaybeDatum :: Maybe (DatumHash, Maybe Datum) -> OutputDatum +convertMaybeDatum = \case + Nothing -> NoOutputDatum + Just (dh, Nothing) -> OutputDatumHash dh + Just (_dh, Just d) -> OutputDatum d + +convertRefScript :: Maybe V1.Script -> ReferenceScript +convertRefScript = + \case + Nothing -> ReferenceScriptNone + Just v -> + ReferenceScriptInAnyLang + . toScriptInAnyLang + . PlutusScript PlutusScriptV2 + . PlutusScriptSerialised + . SBS.toShort + . LBS.toStrict + . serialise + $ v mockExBudget :: forall (w :: Type). @@ -690,7 +771,7 @@ mockExBudget _ = pure . Right $ TxBudget inBudgets policyBudgets dummyTxRawFile :: TextEnvelope dummyTxRawFile = TextEnvelope - { teType = "TxBodyAlonzo" + { teType = "TxBodyBabbage" , teDescription = "" , teRawCBOR = fromRight (error "failed to unpack CBOR hex") $ unhex "86a500848258205d677265fa5bb21ce6d8c7502aca70b9316d10e958611f3c6b758f65ad9599960182582076ed2fcda860de2cbacd0f3a169058fa91eff47bc1e1e5b6d84497159fbc9300008258209405c89393ba84b14bf8d3e7ed4788cc6e2257831943b58338bee8d37a3668fc00825820a1be9565ccac4a04d2b5bf0d0167196ae467da0d88161c9c827fbe76452b24ef000d8182582076ed2fcda860de2cbacd0f3a169058fa91eff47bc1e1e5b6d84497159fbc930000018482581d600f45aaf1b2959db6e5ff94dbb1f823bf257680c3c723ac2d49f975461a3b8cc4a582581d600f45aaf1b2959db6e5ff94dbb1f823bf257680c3c723ac2d49f97546821a00150bd0a1581c1d6445ddeda578117f393848e685128f1e78ad0c4e48129c5964dc2ea14974657374546f6b656e1a000d062782581d606696936bb8ae24859d0c2e4d05584106601f58a5e9466282c8561b88821a00150bd0a1581c1d6445ddeda578117f393848e685128f1e78ad0c4e48129c5964dc2ea14974657374546f6b656e1282581d60981fc565bcf0c95c0cfa6ee6693875b60d529d87ed7082e9bf03c6a4821a00150bd0a1581c1d6445ddeda578117f393848e685128f1e78ad0c4e48129c5964dc2ea14974657374546f6b656e0f021a000320250e81581c0f45aaf1b2959db6e5ff94dbb1f823bf257680c3c723ac2d49f975469fff8080f5f6" } @@ -698,7 +779,7 @@ dummyTxRawFile = dummyTxSignedFile :: TextEnvelope dummyTxSignedFile = TextEnvelope - { teType = "Tx AlonzoEra" + { teType = "Tx BabbageEra" , teDescription = "" , teRawCBOR = fromRight (error "failed to unpack CBOR hex") $ unhex "84a500848258205d677265fa5bb21ce6d8c7502aca70b9316d10e958611f3c6b758f65ad9599960182582076ed2fcda860de2cbacd0f3a169058fa91eff47bc1e1e5b6d84497159fbc9300008258209405c89393ba84b14bf8d3e7ed4788cc6e2257831943b58338bee8d37a3668fc00825820a1be9565ccac4a04d2b5bf0d0167196ae467da0d88161c9c827fbe76452b24ef000d8182582076ed2fcda860de2cbacd0f3a169058fa91eff47bc1e1e5b6d84497159fbc930000018482581d600f45aaf1b2959db6e5ff94dbb1f823bf257680c3c723ac2d49f975461a3b8cc4a582581d600f45aaf1b2959db6e5ff94dbb1f823bf257680c3c723ac2d49f97546821a00150bd0a1581c1d6445ddeda578117f393848e685128f1e78ad0c4e48129c5964dc2ea14974657374546f6b656e1a000d062782581d606696936bb8ae24859d0c2e4d05584106601f58a5e9466282c8561b88821a00150bd0a1581c1d6445ddeda578117f393848e685128f1e78ad0c4e48129c5964dc2ea14974657374546f6b656e1282581d60981fc565bcf0c95c0cfa6ee6693875b60d529d87ed7082e9bf03c6a4821a00150bd0a1581c1d6445ddeda578117f393848e685128f1e78ad0c4e48129c5964dc2ea14974657374546f6b656e0f021a000320250e81581c0f45aaf1b2959db6e5ff94dbb1f823bf257680c3c723ac2d49f97546a10081825820096092b8515d75c2a2f75d6aa7c5191996755840e81deaa403dba5b690f091b65840295a93849a67cecabb8286e561c407b6bd49abf8d2da8bfb821105eae4d28ef0ef1b9ee5e8abb8fd334059f3dfc78c0a65e74057a2dc8d1d12e46842abea600ff5f6" } @@ -715,3 +796,17 @@ mockSlotRange = slotRange where slotRange = Interval (lowerBound 47577202) (strictUpperBound 50255602) + +mockQueryNode :: + forall (w :: Type) (a :: Type). + NodeQuery a -> + MockContract w a +mockQueryNode (UtxosAt _addr) = do + state <- get @(MockContractState w) + return $ Right $ Map.fromList (state ^. utxos) +mockQueryNode PParams = do + state <- get @(MockContractState w) + + case pcProtocolParams $ cePABConfig $ _contractEnv state of + Nothing -> return $ Left $ toQueryError @String "Not able to get protocol parameters." + (Just pparams) -> return $ Right pparams