From cf5dfb62d19857c4c5d716d06450333ecdffefd8 Mon Sep 17 00:00:00 2001 From: Nikolaos Bezirgiannis <329939+bezirg@users.noreply.github.com> Date: Wed, 14 Aug 2024 22:37:28 +0200 Subject: [PATCH] [plinth][plc][api][agda] Draft of modExpInteger builtin (#6348) [agda] Added builtin expModInteger Co-authored-by: Nikolaos Bezirgiannis --- .../bitwise/src/PlutusBenchmark/Ed25519.hs | 15 +- .../bitwise/test/9.6/Ed25519.pir.golden | 18 +-- .../exp-neg-non-inverse1.uplc | 1 + .../exp-neg-non-inverse1.uplc.budget.expected | 1 + .../exp-neg-non-inverse1.uplc.expected | 1 + .../exp-neg-non-inverse2.uplc | 1 + .../exp-neg-non-inverse2.uplc.budget.expected | 1 + .../exp-neg-non-inverse2.uplc.expected | 1 + .../expModInteger/expMod1/expMod1.uplc | 1 + .../expMod1/expMod1.uplc.budget.expected | 2 + .../expMod1/expMod1.uplc.expected | 1 + .../expModInteger/expMod2/expMod2.uplc | 1 + .../expMod2/expMod2.uplc.budget.expected | 2 + .../expMod2/expMod2.uplc.expected | 1 + .../expModInteger/expMod3/expMod3.uplc | 1 + .../expMod3/expMod3.uplc.budget.expected | 2 + .../expMod3/expMod3.uplc.expected | 1 + .../expModInteger/expMod4/expMod4.uplc | 1 + .../expMod4/expMod4.uplc.budget.expected | 2 + .../expMod4/expMod4.uplc.expected | 1 + .../expModInteger/expMod5/expMod5.uplc | 1 + .../expMod5/expMod5.uplc.budget.expected | 2 + .../expMod5/expMod5.uplc.expected | 1 + .../expModInteger/mod-neg/mod-neg.uplc | 1 + .../mod-neg/mod-neg.uplc.budget.expected | 1 + .../mod-neg/mod-neg.uplc.expected | 1 + .../expModInteger/mod-zero/mod-zero.uplc | 1 + .../mod-zero/mod-zero.uplc.budget.expected | 1 + .../mod-zero/mod-zero.uplc.expected | 1 + .../20240726_124910_bezirg_modexp.md | 3 + .../create-cost-model/BuiltinMemoryModels.hs | 1 + .../CreateBuiltinCostModel.hs | 3 +- .../cost-model/data/builtinCostModelA.json | 10 ++ .../cost-model/data/builtinCostModelB.json | 10 ++ .../cost-model/data/builtinCostModelC.json | 10 ++ plutus-core/cost-model/data/models.R | 4 + .../executables/plutus/Debugger/TUI/Event.hs | 4 +- plutus-core/plutus-core.cabal | 1 + .../src/PlutusCore/Crypto/ExpMod.hs | 40 +++++ .../src/PlutusCore/Default/Builtins.hs | 13 ++ .../Evaluation/Machine/BuiltinCostModel.hs | 1 + .../Evaluation/Machine/ExBudgetingDefaults.hs | 1 + .../Evaluation/Machine/ExMemoryUsage.hs | 6 + .../plutus-core/test/CostModelSafety/Spec.hs | 2 + .../DefaultFun/ExpModInteger.plc.golden | 1 + .../Golden/DefaultFun/Ripemd_160.plc.golden | 1 + .../RewriteRules/CommuteFnWithConst.hs | 1 + .../PlutusCore/Generators/Hedgehog/Builtin.hs | 2 + .../test/Evaluation/Builtins/Definition.hs | 35 ++++- .../ExpMod/exp-neg-non-inverse1.err.golden | 5 + .../ExpMod/exp-neg-non-inverse2.err.golden | 5 + .../Golden/Integer/ExpMod/mod-neg.err.golden | 5 + .../Golden/Integer/ExpMod/mod-zero.err.golden | 5 + .../divideInteger-div-by-zero.err.golden | 5 + .../Integer/modInteger-div-by-zero.err.golden | 5 + .../quotientInteger-div-by-zero.err.golden | 5 + .../remainderInteger-div-by-zero.err.golden | 5 + .../20240726_125029_bezirg_modexp.md | 3 + .../src/PlutusLedgerApi/Common/Versions.hs | 2 +- .../src/PlutusLedgerApi/V3/ParamName.hs | 3 + .../Test/V3/Data/EvaluationContext.hs | 2 + .../Test/V3/EvaluationContext.hs | 2 + .../src/Algorithmic/CEK.lagda.md | 3 + plutus-metatheory/src/Builtin.lagda.md | 12 ++ plutus-metatheory/src/Untyped/CEK.lagda.md | 7 + .../20240726_125023_bezirg_modexp.md | 3 + .../src/PlutusTx/Compiler/Builtins.hs | 4 + plutus-tx-plugin/src/PlutusTx/Plugin.hs | 2 +- .../Plugin/Profiling/9.6/addInt.pir.golden | 8 +- .../Plugin/Profiling/9.6/addInt3.eval.golden | 2 +- .../Profiling/9.6/argMismatch1.eval.golden | 12 +- .../Profiling/9.6/argMismatch2.eval.golden | 2 +- .../Plugin/Profiling/9.6/fact4.eval.golden | 72 ++++----- .../test/Plugin/Profiling/9.6/fib.pir.golden | 16 +- .../Plugin/Profiling/9.6/fib4.eval.golden | 148 +++++++++--------- .../test/Plugin/Profiling/9.6/id.eval.golden | 2 +- .../Plugin/Profiling/9.6/idCode.pir.golden | 4 +- .../Plugin/Profiling/9.6/letInFun.eval.golden | 20 +-- .../Profiling/9.6/letInFunMoreArg.eval.golden | 24 +-- .../Profiling/9.6/letRecInFun.eval.golden | 56 +++---- .../Plugin/Profiling/9.6/swap.eval.golden | 2 +- .../Profiling/9.6/typeclass.eval.golden | 24 +-- .../20240726_125008_bezirg_modexp.md | 3 + plutus-tx/src/PlutusTx/Builtins.hs | 16 ++ plutus-tx/src/PlutusTx/Builtins/Internal.hs | 16 ++ plutus-tx/src/PlutusTx/Prelude.hs | 7 + stubs/plutus-ghc-stub/src/Plugins.hs | 3 - 87 files changed, 513 insertions(+), 221 deletions(-) create mode 100644 plutus-conformance/test-cases/uplc/evaluation/builtin/semantics/expModInteger/exp-neg-non-inverse1/exp-neg-non-inverse1.uplc create mode 100644 plutus-conformance/test-cases/uplc/evaluation/builtin/semantics/expModInteger/exp-neg-non-inverse1/exp-neg-non-inverse1.uplc.budget.expected create mode 100644 plutus-conformance/test-cases/uplc/evaluation/builtin/semantics/expModInteger/exp-neg-non-inverse1/exp-neg-non-inverse1.uplc.expected create mode 100644 plutus-conformance/test-cases/uplc/evaluation/builtin/semantics/expModInteger/exp-neg-non-inverse2/exp-neg-non-inverse2.uplc create mode 100644 plutus-conformance/test-cases/uplc/evaluation/builtin/semantics/expModInteger/exp-neg-non-inverse2/exp-neg-non-inverse2.uplc.budget.expected create mode 100644 plutus-conformance/test-cases/uplc/evaluation/builtin/semantics/expModInteger/exp-neg-non-inverse2/exp-neg-non-inverse2.uplc.expected create mode 100644 plutus-conformance/test-cases/uplc/evaluation/builtin/semantics/expModInteger/expMod1/expMod1.uplc create mode 100644 plutus-conformance/test-cases/uplc/evaluation/builtin/semantics/expModInteger/expMod1/expMod1.uplc.budget.expected create mode 100644 plutus-conformance/test-cases/uplc/evaluation/builtin/semantics/expModInteger/expMod1/expMod1.uplc.expected create mode 100644 plutus-conformance/test-cases/uplc/evaluation/builtin/semantics/expModInteger/expMod2/expMod2.uplc create mode 100644 plutus-conformance/test-cases/uplc/evaluation/builtin/semantics/expModInteger/expMod2/expMod2.uplc.budget.expected create mode 100644 plutus-conformance/test-cases/uplc/evaluation/builtin/semantics/expModInteger/expMod2/expMod2.uplc.expected create mode 100644 plutus-conformance/test-cases/uplc/evaluation/builtin/semantics/expModInteger/expMod3/expMod3.uplc create mode 100644 plutus-conformance/test-cases/uplc/evaluation/builtin/semantics/expModInteger/expMod3/expMod3.uplc.budget.expected create mode 100644 plutus-conformance/test-cases/uplc/evaluation/builtin/semantics/expModInteger/expMod3/expMod3.uplc.expected create mode 100644 plutus-conformance/test-cases/uplc/evaluation/builtin/semantics/expModInteger/expMod4/expMod4.uplc create mode 100644 plutus-conformance/test-cases/uplc/evaluation/builtin/semantics/expModInteger/expMod4/expMod4.uplc.budget.expected create mode 100644 plutus-conformance/test-cases/uplc/evaluation/builtin/semantics/expModInteger/expMod4/expMod4.uplc.expected create mode 100644 plutus-conformance/test-cases/uplc/evaluation/builtin/semantics/expModInteger/expMod5/expMod5.uplc create mode 100644 plutus-conformance/test-cases/uplc/evaluation/builtin/semantics/expModInteger/expMod5/expMod5.uplc.budget.expected create mode 100644 plutus-conformance/test-cases/uplc/evaluation/builtin/semantics/expModInteger/expMod5/expMod5.uplc.expected create mode 100644 plutus-conformance/test-cases/uplc/evaluation/builtin/semantics/expModInteger/mod-neg/mod-neg.uplc create mode 100644 plutus-conformance/test-cases/uplc/evaluation/builtin/semantics/expModInteger/mod-neg/mod-neg.uplc.budget.expected create mode 100644 plutus-conformance/test-cases/uplc/evaluation/builtin/semantics/expModInteger/mod-neg/mod-neg.uplc.expected create mode 100644 plutus-conformance/test-cases/uplc/evaluation/builtin/semantics/expModInteger/mod-zero/mod-zero.uplc create mode 100644 plutus-conformance/test-cases/uplc/evaluation/builtin/semantics/expModInteger/mod-zero/mod-zero.uplc.budget.expected create mode 100644 plutus-conformance/test-cases/uplc/evaluation/builtin/semantics/expModInteger/mod-zero/mod-zero.uplc.expected create mode 100644 plutus-core/changelog.d/20240726_124910_bezirg_modexp.md create mode 100644 plutus-core/plutus-core/src/PlutusCore/Crypto/ExpMod.hs create mode 100644 plutus-core/plutus-core/test/TypeSynthesis/Golden/DefaultFun/ExpModInteger.plc.golden create mode 100644 plutus-core/plutus-core/test/TypeSynthesis/Golden/DefaultFun/Ripemd_160.plc.golden create mode 100644 plutus-core/untyped-plutus-core/test/Evaluation/Builtins/Golden/Integer/ExpMod/exp-neg-non-inverse1.err.golden create mode 100644 plutus-core/untyped-plutus-core/test/Evaluation/Builtins/Golden/Integer/ExpMod/exp-neg-non-inverse2.err.golden create mode 100644 plutus-core/untyped-plutus-core/test/Evaluation/Builtins/Golden/Integer/ExpMod/mod-neg.err.golden create mode 100644 plutus-core/untyped-plutus-core/test/Evaluation/Builtins/Golden/Integer/ExpMod/mod-zero.err.golden create mode 100644 plutus-core/untyped-plutus-core/test/Evaluation/Builtins/Golden/Integer/divideInteger-div-by-zero.err.golden create mode 100644 plutus-core/untyped-plutus-core/test/Evaluation/Builtins/Golden/Integer/modInteger-div-by-zero.err.golden create mode 100644 plutus-core/untyped-plutus-core/test/Evaluation/Builtins/Golden/Integer/quotientInteger-div-by-zero.err.golden create mode 100644 plutus-core/untyped-plutus-core/test/Evaluation/Builtins/Golden/Integer/remainderInteger-div-by-zero.err.golden create mode 100644 plutus-ledger-api/changelog.d/20240726_125029_bezirg_modexp.md create mode 100644 plutus-tx-plugin/changelog.d/20240726_125023_bezirg_modexp.md create mode 100644 plutus-tx/changelog.d/20240726_125008_bezirg_modexp.md diff --git a/plutus-benchmark/bitwise/src/PlutusBenchmark/Ed25519.hs b/plutus-benchmark/bitwise/src/PlutusBenchmark/Ed25519.hs index 361557a2012..029d1595dfa 100644 --- a/plutus-benchmark/bitwise/src/PlutusBenchmark/Ed25519.hs +++ b/plutus-benchmark/bitwise/src/PlutusBenchmark/Ed25519.hs @@ -101,7 +101,7 @@ xRecover y = xx :: Integer xx = (y * y - 1) * inv (d * y * y + 1) x :: Integer - x = expMod xx ((q + 3) `divide` 8) q + x = expModManual xx ((q + 3) `divide` 8) q xA :: Integer xA = x * i `modulo` q xB :: Integer @@ -113,7 +113,7 @@ xRecover y = cond2 :: Bool cond2 = if cond1 then odd xA else odd x i :: Integer - i = expMod 2 ((q - 1) `divide` 4) q + i = expModManual 2 ((q - 1) `divide` 4) q {-# INLINEABLE clearBit #-} clearBit :: Integer -> BuiltinByteString -> BuiltinByteString @@ -121,19 +121,20 @@ clearBit ix bs = writeBits bs [ix] [False] {-# INLINEABLE inv #-} inv :: Integer -> Integer -inv x = expMod x (q - 2) q +inv x = expModManual x (q - 2) q {-# INLINEABLE d #-} d :: Integer d = (-121665) * inv 121666 -{-# INLINEABLE expMod #-} -expMod :: Integer -> Integer -> Integer -> Integer -expMod b' e m = +{-# INLINEABLE expModManual #-} +-- TODO: switch to the builtin `expMod` (aka ExpModInteger)? +expModManual :: Integer -> Integer -> Integer -> Integer +expModManual b' e m = if e == 0 then 1 else - let reduced = expMod b' (e `divide` 2) m + let reduced = expModManual b' (e `divide` 2) m t = (reduced * reduced) `modulo` m in if odd e then (t * b') `modulo` m diff --git a/plutus-benchmark/bitwise/test/9.6/Ed25519.pir.golden b/plutus-benchmark/bitwise/test/9.6/Ed25519.pir.golden index bcf732ba499..ae399be67b1 100644 --- a/plutus-benchmark/bitwise/test/9.6/Ed25519.pir.golden +++ b/plutus-benchmark/bitwise/test/9.6/Ed25519.pir.golden @@ -52,7 +52,7 @@ ifThenElse {Bool} (equalsInteger 0 (modInteger n 2)) True False in letrec - !expMod : integer -> integer -> integer -> integer + !expModManual : integer -> integer -> integer -> integer = \(b' : integer) (e : integer) (m : integer) -> Bool_match (ifThenElse {Bool} (equalsInteger 0 e) True False) @@ -60,7 +60,7 @@ (/\dead -> 1) (/\dead -> let - !reduced : integer = expMod b' (divideInteger e 2) m + !reduced : integer = expModManual b' (divideInteger e 2) m !t : integer = modInteger (multiplyInteger reduced reduced) m in Bool_match @@ -76,7 +76,7 @@ integer = multiplyInteger -121665 - (expMod + (expModManual 121666 57896044618658097711785492504343953926634992332820282019728792003956564819947 57896044618658097711785492504343953926634992332820282019728792003956564819949) @@ -86,7 +86,7 @@ let !i : integer - = expMod + = expModManual 2 14474011154664524427946373126085988481658748083205070504932198000989141204987 57896044618658097711785492504343953926634992332820282019728792003956564819949 @@ -94,13 +94,13 @@ integer = multiplyInteger (subtractInteger (multiplyInteger y y) 1) - (expMod + (expModManual (addInteger 1 (multiplyInteger (multiplyInteger d y) y)) 57896044618658097711785492504343953926634992332820282019728792003956564819947 57896044618658097711785492504343953926634992332820282019728792003956564819949) !x : integer - = expMod + = expModManual xx 7237005577332262213973186563042994240829374041602535252466099000494570602494 57896044618658097711785492504343953926634992332820282019728792003956564819949 @@ -431,7 +431,7 @@ (addInteger (multiplyInteger y y) (multiplyInteger x x)) - (expMod + (expModManual (subtractInteger 1 (multiplyInteger @@ -452,7 +452,7 @@ (addInteger (multiplyInteger x y) (multiplyInteger x y)) - (expMod + (expModManual (addInteger 1 (multiplyInteger @@ -575,7 +575,7 @@ integer = multiplyInteger 4 - (expMod + (expModManual 5 57896044618658097711785492504343953926634992332820282019728792003956564819947 57896044618658097711785492504343953926634992332820282019728792003956564819949) diff --git a/plutus-conformance/test-cases/uplc/evaluation/builtin/semantics/expModInteger/exp-neg-non-inverse1/exp-neg-non-inverse1.uplc b/plutus-conformance/test-cases/uplc/evaluation/builtin/semantics/expModInteger/exp-neg-non-inverse1/exp-neg-non-inverse1.uplc new file mode 100644 index 00000000000..ec619715b30 --- /dev/null +++ b/plutus-conformance/test-cases/uplc/evaluation/builtin/semantics/expModInteger/exp-neg-non-inverse1/exp-neg-non-inverse1.uplc @@ -0,0 +1 @@ +(program 1.0.0 [ [ [ (builtin expModInteger) (con integer 2)] (con integer -3) ] (con integer -4)]) \ No newline at end of file diff --git a/plutus-conformance/test-cases/uplc/evaluation/builtin/semantics/expModInteger/exp-neg-non-inverse1/exp-neg-non-inverse1.uplc.budget.expected b/plutus-conformance/test-cases/uplc/evaluation/builtin/semantics/expModInteger/exp-neg-non-inverse1/exp-neg-non-inverse1.uplc.budget.expected new file mode 100644 index 00000000000..ccc477ffed6 --- /dev/null +++ b/plutus-conformance/test-cases/uplc/evaluation/builtin/semantics/expModInteger/exp-neg-non-inverse1/exp-neg-non-inverse1.uplc.budget.expected @@ -0,0 +1 @@ +evaluation failure \ No newline at end of file diff --git a/plutus-conformance/test-cases/uplc/evaluation/builtin/semantics/expModInteger/exp-neg-non-inverse1/exp-neg-non-inverse1.uplc.expected b/plutus-conformance/test-cases/uplc/evaluation/builtin/semantics/expModInteger/exp-neg-non-inverse1/exp-neg-non-inverse1.uplc.expected new file mode 100644 index 00000000000..ccc477ffed6 --- /dev/null +++ b/plutus-conformance/test-cases/uplc/evaluation/builtin/semantics/expModInteger/exp-neg-non-inverse1/exp-neg-non-inverse1.uplc.expected @@ -0,0 +1 @@ +evaluation failure \ No newline at end of file diff --git a/plutus-conformance/test-cases/uplc/evaluation/builtin/semantics/expModInteger/exp-neg-non-inverse2/exp-neg-non-inverse2.uplc b/plutus-conformance/test-cases/uplc/evaluation/builtin/semantics/expModInteger/exp-neg-non-inverse2/exp-neg-non-inverse2.uplc new file mode 100644 index 00000000000..c063c86c30d --- /dev/null +++ b/plutus-conformance/test-cases/uplc/evaluation/builtin/semantics/expModInteger/exp-neg-non-inverse2/exp-neg-non-inverse2.uplc @@ -0,0 +1 @@ +(program 1.0.0 [ [ [ (builtin expModInteger) (con integer 500)] (con integer -5) ] (con integer 5)]) \ No newline at end of file diff --git a/plutus-conformance/test-cases/uplc/evaluation/builtin/semantics/expModInteger/exp-neg-non-inverse2/exp-neg-non-inverse2.uplc.budget.expected b/plutus-conformance/test-cases/uplc/evaluation/builtin/semantics/expModInteger/exp-neg-non-inverse2/exp-neg-non-inverse2.uplc.budget.expected new file mode 100644 index 00000000000..ccc477ffed6 --- /dev/null +++ b/plutus-conformance/test-cases/uplc/evaluation/builtin/semantics/expModInteger/exp-neg-non-inverse2/exp-neg-non-inverse2.uplc.budget.expected @@ -0,0 +1 @@ +evaluation failure \ No newline at end of file diff --git a/plutus-conformance/test-cases/uplc/evaluation/builtin/semantics/expModInteger/exp-neg-non-inverse2/exp-neg-non-inverse2.uplc.expected b/plutus-conformance/test-cases/uplc/evaluation/builtin/semantics/expModInteger/exp-neg-non-inverse2/exp-neg-non-inverse2.uplc.expected new file mode 100644 index 00000000000..ccc477ffed6 --- /dev/null +++ b/plutus-conformance/test-cases/uplc/evaluation/builtin/semantics/expModInteger/exp-neg-non-inverse2/exp-neg-non-inverse2.uplc.expected @@ -0,0 +1 @@ +evaluation failure \ No newline at end of file diff --git a/plutus-conformance/test-cases/uplc/evaluation/builtin/semantics/expModInteger/expMod1/expMod1.uplc b/plutus-conformance/test-cases/uplc/evaluation/builtin/semantics/expModInteger/expMod1/expMod1.uplc new file mode 100644 index 00000000000..bafff0e7a8f --- /dev/null +++ b/plutus-conformance/test-cases/uplc/evaluation/builtin/semantics/expModInteger/expMod1/expMod1.uplc @@ -0,0 +1 @@ +(program 1.0.0 [ [ [ (builtin expModInteger) (con integer 500)] (con integer 0) ] (con integer 500)]) \ No newline at end of file diff --git a/plutus-conformance/test-cases/uplc/evaluation/builtin/semantics/expModInteger/expMod1/expMod1.uplc.budget.expected b/plutus-conformance/test-cases/uplc/evaluation/builtin/semantics/expModInteger/expMod1/expMod1.uplc.budget.expected new file mode 100644 index 00000000000..8331e319f3a --- /dev/null +++ b/plutus-conformance/test-cases/uplc/evaluation/builtin/semantics/expModInteger/expMod1/expMod1.uplc.budget.expected @@ -0,0 +1,2 @@ +({cpu: 100000112100 +| mem: 100000000800}) \ No newline at end of file diff --git a/plutus-conformance/test-cases/uplc/evaluation/builtin/semantics/expModInteger/expMod1/expMod1.uplc.expected b/plutus-conformance/test-cases/uplc/evaluation/builtin/semantics/expModInteger/expMod1/expMod1.uplc.expected new file mode 100644 index 00000000000..8e9a3b22d84 --- /dev/null +++ b/plutus-conformance/test-cases/uplc/evaluation/builtin/semantics/expModInteger/expMod1/expMod1.uplc.expected @@ -0,0 +1 @@ +(program 1.0.0 (con integer 1)) \ No newline at end of file diff --git a/plutus-conformance/test-cases/uplc/evaluation/builtin/semantics/expModInteger/expMod2/expMod2.uplc b/plutus-conformance/test-cases/uplc/evaluation/builtin/semantics/expModInteger/expMod2/expMod2.uplc new file mode 100644 index 00000000000..82d0936da9a --- /dev/null +++ b/plutus-conformance/test-cases/uplc/evaluation/builtin/semantics/expModInteger/expMod2/expMod2.uplc @@ -0,0 +1 @@ +(program 1.0.0 [ [ [ (builtin expModInteger) (con integer 500)] (con integer 5) ] (con integer 500)]) \ No newline at end of file diff --git a/plutus-conformance/test-cases/uplc/evaluation/builtin/semantics/expModInteger/expMod2/expMod2.uplc.budget.expected b/plutus-conformance/test-cases/uplc/evaluation/builtin/semantics/expModInteger/expMod2/expMod2.uplc.budget.expected new file mode 100644 index 00000000000..8331e319f3a --- /dev/null +++ b/plutus-conformance/test-cases/uplc/evaluation/builtin/semantics/expModInteger/expMod2/expMod2.uplc.budget.expected @@ -0,0 +1,2 @@ +({cpu: 100000112100 +| mem: 100000000800}) \ No newline at end of file diff --git a/plutus-conformance/test-cases/uplc/evaluation/builtin/semantics/expModInteger/expMod2/expMod2.uplc.expected b/plutus-conformance/test-cases/uplc/evaluation/builtin/semantics/expModInteger/expMod2/expMod2.uplc.expected new file mode 100644 index 00000000000..87e0223f6f0 --- /dev/null +++ b/plutus-conformance/test-cases/uplc/evaluation/builtin/semantics/expModInteger/expMod2/expMod2.uplc.expected @@ -0,0 +1 @@ +(program 1.0.0 (con integer 0)) \ No newline at end of file diff --git a/plutus-conformance/test-cases/uplc/evaluation/builtin/semantics/expModInteger/expMod3/expMod3.uplc b/plutus-conformance/test-cases/uplc/evaluation/builtin/semantics/expModInteger/expMod3/expMod3.uplc new file mode 100644 index 00000000000..6c94ba7fb3d --- /dev/null +++ b/plutus-conformance/test-cases/uplc/evaluation/builtin/semantics/expModInteger/expMod3/expMod3.uplc @@ -0,0 +1 @@ +(program 1.0.0 [ [ [ (builtin expModInteger) (con integer 1)] (con integer -3) ] (con integer 4)]) \ No newline at end of file diff --git a/plutus-conformance/test-cases/uplc/evaluation/builtin/semantics/expModInteger/expMod3/expMod3.uplc.budget.expected b/plutus-conformance/test-cases/uplc/evaluation/builtin/semantics/expModInteger/expMod3/expMod3.uplc.budget.expected new file mode 100644 index 00000000000..8331e319f3a --- /dev/null +++ b/plutus-conformance/test-cases/uplc/evaluation/builtin/semantics/expModInteger/expMod3/expMod3.uplc.budget.expected @@ -0,0 +1,2 @@ +({cpu: 100000112100 +| mem: 100000000800}) \ No newline at end of file diff --git a/plutus-conformance/test-cases/uplc/evaluation/builtin/semantics/expModInteger/expMod3/expMod3.uplc.expected b/plutus-conformance/test-cases/uplc/evaluation/builtin/semantics/expModInteger/expMod3/expMod3.uplc.expected new file mode 100644 index 00000000000..8e9a3b22d84 --- /dev/null +++ b/plutus-conformance/test-cases/uplc/evaluation/builtin/semantics/expModInteger/expMod3/expMod3.uplc.expected @@ -0,0 +1 @@ +(program 1.0.0 (con integer 1)) \ No newline at end of file diff --git a/plutus-conformance/test-cases/uplc/evaluation/builtin/semantics/expModInteger/expMod4/expMod4.uplc b/plutus-conformance/test-cases/uplc/evaluation/builtin/semantics/expModInteger/expMod4/expMod4.uplc new file mode 100644 index 00000000000..821e954011d --- /dev/null +++ b/plutus-conformance/test-cases/uplc/evaluation/builtin/semantics/expModInteger/expMod4/expMod4.uplc @@ -0,0 +1 @@ +(program 1.0.0 [ [ [ (builtin expModInteger) (con integer 2)] (con integer -3) ] (con integer 3)]) \ No newline at end of file diff --git a/plutus-conformance/test-cases/uplc/evaluation/builtin/semantics/expModInteger/expMod4/expMod4.uplc.budget.expected b/plutus-conformance/test-cases/uplc/evaluation/builtin/semantics/expModInteger/expMod4/expMod4.uplc.budget.expected new file mode 100644 index 00000000000..8331e319f3a --- /dev/null +++ b/plutus-conformance/test-cases/uplc/evaluation/builtin/semantics/expModInteger/expMod4/expMod4.uplc.budget.expected @@ -0,0 +1,2 @@ +({cpu: 100000112100 +| mem: 100000000800}) \ No newline at end of file diff --git a/plutus-conformance/test-cases/uplc/evaluation/builtin/semantics/expModInteger/expMod4/expMod4.uplc.expected b/plutus-conformance/test-cases/uplc/evaluation/builtin/semantics/expModInteger/expMod4/expMod4.uplc.expected new file mode 100644 index 00000000000..00abe6f7a79 --- /dev/null +++ b/plutus-conformance/test-cases/uplc/evaluation/builtin/semantics/expModInteger/expMod4/expMod4.uplc.expected @@ -0,0 +1 @@ +(program 1.0.0 (con integer 2)) \ No newline at end of file diff --git a/plutus-conformance/test-cases/uplc/evaluation/builtin/semantics/expModInteger/expMod5/expMod5.uplc b/plutus-conformance/test-cases/uplc/evaluation/builtin/semantics/expModInteger/expMod5/expMod5.uplc new file mode 100644 index 00000000000..4b0b5f4f549 --- /dev/null +++ b/plutus-conformance/test-cases/uplc/evaluation/builtin/semantics/expModInteger/expMod5/expMod5.uplc @@ -0,0 +1 @@ +(program 1.0.0 [ [ [ (builtin expModInteger) (con integer 4)] (con integer -5) ] (con integer 9)]) \ No newline at end of file diff --git a/plutus-conformance/test-cases/uplc/evaluation/builtin/semantics/expModInteger/expMod5/expMod5.uplc.budget.expected b/plutus-conformance/test-cases/uplc/evaluation/builtin/semantics/expModInteger/expMod5/expMod5.uplc.budget.expected new file mode 100644 index 00000000000..8331e319f3a --- /dev/null +++ b/plutus-conformance/test-cases/uplc/evaluation/builtin/semantics/expModInteger/expMod5/expMod5.uplc.budget.expected @@ -0,0 +1,2 @@ +({cpu: 100000112100 +| mem: 100000000800}) \ No newline at end of file diff --git a/plutus-conformance/test-cases/uplc/evaluation/builtin/semantics/expModInteger/expMod5/expMod5.uplc.expected b/plutus-conformance/test-cases/uplc/evaluation/builtin/semantics/expModInteger/expMod5/expMod5.uplc.expected new file mode 100644 index 00000000000..68ab9fd04f7 --- /dev/null +++ b/plutus-conformance/test-cases/uplc/evaluation/builtin/semantics/expModInteger/expMod5/expMod5.uplc.expected @@ -0,0 +1 @@ +(program 1.0.0 (con integer 4)) \ No newline at end of file diff --git a/plutus-conformance/test-cases/uplc/evaluation/builtin/semantics/expModInteger/mod-neg/mod-neg.uplc b/plutus-conformance/test-cases/uplc/evaluation/builtin/semantics/expModInteger/mod-neg/mod-neg.uplc new file mode 100644 index 00000000000..5820f4d1873 --- /dev/null +++ b/plutus-conformance/test-cases/uplc/evaluation/builtin/semantics/expModInteger/mod-neg/mod-neg.uplc @@ -0,0 +1 @@ +(program 1.0.0 [ [ [ (builtin expModInteger) (con integer 1)] (con integer 1) ] (con integer -3)]) \ No newline at end of file diff --git a/plutus-conformance/test-cases/uplc/evaluation/builtin/semantics/expModInteger/mod-neg/mod-neg.uplc.budget.expected b/plutus-conformance/test-cases/uplc/evaluation/builtin/semantics/expModInteger/mod-neg/mod-neg.uplc.budget.expected new file mode 100644 index 00000000000..ccc477ffed6 --- /dev/null +++ b/plutus-conformance/test-cases/uplc/evaluation/builtin/semantics/expModInteger/mod-neg/mod-neg.uplc.budget.expected @@ -0,0 +1 @@ +evaluation failure \ No newline at end of file diff --git a/plutus-conformance/test-cases/uplc/evaluation/builtin/semantics/expModInteger/mod-neg/mod-neg.uplc.expected b/plutus-conformance/test-cases/uplc/evaluation/builtin/semantics/expModInteger/mod-neg/mod-neg.uplc.expected new file mode 100644 index 00000000000..ccc477ffed6 --- /dev/null +++ b/plutus-conformance/test-cases/uplc/evaluation/builtin/semantics/expModInteger/mod-neg/mod-neg.uplc.expected @@ -0,0 +1 @@ +evaluation failure \ No newline at end of file diff --git a/plutus-conformance/test-cases/uplc/evaluation/builtin/semantics/expModInteger/mod-zero/mod-zero.uplc b/plutus-conformance/test-cases/uplc/evaluation/builtin/semantics/expModInteger/mod-zero/mod-zero.uplc new file mode 100644 index 00000000000..ff1b07c264f --- /dev/null +++ b/plutus-conformance/test-cases/uplc/evaluation/builtin/semantics/expModInteger/mod-zero/mod-zero.uplc @@ -0,0 +1 @@ +(program 1.0.0 [ [ [ (builtin expModInteger) (con integer 1)] (con integer 1) ] (con integer 0)]) \ No newline at end of file diff --git a/plutus-conformance/test-cases/uplc/evaluation/builtin/semantics/expModInteger/mod-zero/mod-zero.uplc.budget.expected b/plutus-conformance/test-cases/uplc/evaluation/builtin/semantics/expModInteger/mod-zero/mod-zero.uplc.budget.expected new file mode 100644 index 00000000000..ccc477ffed6 --- /dev/null +++ b/plutus-conformance/test-cases/uplc/evaluation/builtin/semantics/expModInteger/mod-zero/mod-zero.uplc.budget.expected @@ -0,0 +1 @@ +evaluation failure \ No newline at end of file diff --git a/plutus-conformance/test-cases/uplc/evaluation/builtin/semantics/expModInteger/mod-zero/mod-zero.uplc.expected b/plutus-conformance/test-cases/uplc/evaluation/builtin/semantics/expModInteger/mod-zero/mod-zero.uplc.expected new file mode 100644 index 00000000000..ccc477ffed6 --- /dev/null +++ b/plutus-conformance/test-cases/uplc/evaluation/builtin/semantics/expModInteger/mod-zero/mod-zero.uplc.expected @@ -0,0 +1 @@ +evaluation failure \ No newline at end of file diff --git a/plutus-core/changelog.d/20240726_124910_bezirg_modexp.md b/plutus-core/changelog.d/20240726_124910_bezirg_modexp.md new file mode 100644 index 00000000000..7e5e74e1a0a --- /dev/null +++ b/plutus-core/changelog.d/20240726_124910_bezirg_modexp.md @@ -0,0 +1,3 @@ +### Added + +- An initial DRAFT implementation of 'modularExponentiation' builtin diff --git a/plutus-core/cost-model/create-cost-model/BuiltinMemoryModels.hs b/plutus-core/cost-model/create-cost-model/BuiltinMemoryModels.hs index a53bcd1eefc..7601a1b2097 100644 --- a/plutus-core/cost-model/create-cost-model/BuiltinMemoryModels.hs +++ b/plutus-core/cost-model/create-cost-model/BuiltinMemoryModels.hs @@ -169,6 +169,7 @@ builtinMemoryModels = BuiltinCostModelBase , paramCountSetBits = Id $ ModelOneArgumentConstantCost 1 , paramFindFirstSetBit = Id $ ModelOneArgumentConstantCost 1 , paramRipemd_160 = Id $ hashMemModel Hash.ripemd_160 + , paramExpModInteger = Id $ ModelThreeArgumentsConstantCost 100000000000 -- FIXME: stub } where identityFunction = OneVariableLinearFunction 0 1 diff --git a/plutus-core/cost-model/create-cost-model/CreateBuiltinCostModel.hs b/plutus-core/cost-model/create-cost-model/CreateBuiltinCostModel.hs index ca520bd5a8b..fedbadcaf5a 100644 --- a/plutus-core/cost-model/create-cost-model/CreateBuiltinCostModel.hs +++ b/plutus-core/cost-model/create-cost-model/CreateBuiltinCostModel.hs @@ -124,7 +124,7 @@ builtinCostModelNames = BuiltinCostModelBase , paramCountSetBits = "countSetBitsModel" , paramFindFirstSetBit = "findFirstSetBitModel" , paramRipemd_160 = "ripemd_160Model" - + , paramExpModInteger = "expModIntegerModel" } @@ -264,6 +264,7 @@ createBuiltinCostModel bmfile rfile = do paramFindFirstSetBit <- getParams readCF1 paramFindFirstSetBit -- And another hash function paramRipemd_160 <- getParams readCF1 paramRipemd_160 + paramExpModInteger <- getParams readCF3 paramExpModInteger pure $ BuiltinCostModelBase {..} diff --git a/plutus-core/cost-model/data/builtinCostModelA.json b/plutus-core/cost-model/data/builtinCostModelA.json index 211942e8850..7053057ff9f 100644 --- a/plutus-core/cost-model/data/builtinCostModelA.json +++ b/plutus-core/cost-model/data/builtinCostModelA.json @@ -1113,5 +1113,15 @@ "arguments": 3, "type": "constant_cost" } + }, + "expModInteger": { + "cpu": { + "arguments": 100000000000, + "type": "constant_cost" + }, + "memory": { + "arguments": 100000000000, + "type": "constant_cost" + } } } diff --git a/plutus-core/cost-model/data/builtinCostModelB.json b/plutus-core/cost-model/data/builtinCostModelB.json index 2a5f6f32da2..d52c258c175 100644 --- a/plutus-core/cost-model/data/builtinCostModelB.json +++ b/plutus-core/cost-model/data/builtinCostModelB.json @@ -1113,5 +1113,15 @@ "arguments": 3, "type": "constant_cost" } + }, + "expModInteger": { + "cpu": { + "arguments": 100000000000, + "type": "constant_cost" + }, + "memory": { + "arguments": 100000000000, + "type": "constant_cost" + } } } diff --git a/plutus-core/cost-model/data/builtinCostModelC.json b/plutus-core/cost-model/data/builtinCostModelC.json index 0de45a43f58..4664f40d9b2 100644 --- a/plutus-core/cost-model/data/builtinCostModelC.json +++ b/plutus-core/cost-model/data/builtinCostModelC.json @@ -1131,5 +1131,15 @@ "arguments": 3, "type": "constant_cost" } + }, + "expModInteger": { + "cpu": { + "arguments": 100000000000, + "type": "constant_cost" + }, + "memory": { + "arguments": 100000000000, + "type": "constant_cost" + } } } diff --git a/plutus-core/cost-model/data/models.R b/plutus-core/cost-model/data/models.R index 93202a18e09..ea2d840f184 100644 --- a/plutus-core/cost-model/data/models.R +++ b/plutus-core/cost-model/data/models.R @@ -131,6 +131,7 @@ arity <- function(name) { "Keccak_256" = 1, "Blake2b_224" = 1, "Ripemd_160" = 1, + "ExpModInteger" = 3, "IntegerToByteString" = 3, "ByteStringToInteger" = 2, "AndByteString" = 3, @@ -470,6 +471,8 @@ modelFun <- function(path) { quotientIntegerModel <- divideIntegerModel remainderIntegerModel <- divideIntegerModel modIntegerModel <- divideIntegerModel + expModIntegerModel <- constantModel ("ExpModInteger") # FIXME: stub + ## This could possibly be made constant away from the diagonal; it's harmless ## to make it linear everywhere, but may overprice some comparisons a bit. @@ -805,6 +808,7 @@ modelFun <- function(path) { blake2b_256Model = blake2b_256Model, keccak_256Model = keccak_256Model, ripemd_160Model = ripemd_160Model, + expModIntegerModel = expModIntegerModel, verifyEd25519SignatureModel = verifyEd25519SignatureModel, verifyEcdsaSecp256k1SignatureModel = verifyEcdsaSecp256k1SignatureModel, verifySchnorrSecp256k1SignatureModel = verifySchnorrSecp256k1SignatureModel, diff --git a/plutus-core/executables/plutus/Debugger/TUI/Event.hs b/plutus-core/executables/plutus/Debugger/TUI/Event.hs index c0c76783e22..7d848c9702d 100644 --- a/plutus-core/executables/plutus/Debugger/TUI/Event.hs +++ b/plutus-core/executables/plutus/Debugger/TUI/Event.hs @@ -16,8 +16,8 @@ import Brick.Focus qualified as B import Brick.Main qualified as B import Brick.Types qualified as B import Brick.Widgets.Edit qualified as BE --- ghc 9.6 has this in base -#if __GLASGOW_HASKELL__ < 906 +-- ghc>=9.6 has this in base +#if ! MIN_VERSION_base(4,18,0) import Control.Applicative (liftA2) #endif import Control.Arrow ((>>>)) diff --git a/plutus-core/plutus-core.cabal b/plutus-core/plutus-core.cabal index c2aa165315c..839ef3f6909 100644 --- a/plutus-core/plutus-core.cabal +++ b/plutus-core/plutus-core.cabal @@ -111,6 +111,7 @@ library PlutusCore.Crypto.BLS12_381.G2 PlutusCore.Crypto.BLS12_381.Pairing PlutusCore.Crypto.Ed25519 + PlutusCore.Crypto.ExpMod PlutusCore.Crypto.Hash PlutusCore.Crypto.Secp256k1 PlutusCore.Data diff --git a/plutus-core/plutus-core/src/PlutusCore/Crypto/ExpMod.hs b/plutus-core/plutus-core/src/PlutusCore/Crypto/ExpMod.hs new file mode 100644 index 00000000000..619992d87ae --- /dev/null +++ b/plutus-core/plutus-core/src/PlutusCore/Crypto/ExpMod.hs @@ -0,0 +1,40 @@ +{-# LANGUAGE CPP #-} +{-# LANGUAGE MagicHash #-} +{-# LANGUAGE UnboxedSums #-} +module PlutusCore.Crypto.ExpMod + ( expMod + ) where + +import PlutusCore.Builtin + +import GHC.Natural + +-- Ghc>=9 has this in base +#if MIN_VERSION_base(4,15,0) +import GHC.Num.Integer +-- similar to `Default.Builtins.nonZeroSecondArg` +-- We don't really need it because integerPowMod# returns `()` on zero mod, but we put +-- in case of future implementation changes. +expMod _ _ 0 = fail "Cannot divide by zero" +expMod b e m = + case integerPowMod# b e m of + (# n | #) -> pure n + (# | () #) -> fail "expMod: failure" +#else +-- FIXME: fugly stub implementation to make the various test-suites/CI pass for GHC8.10. +-- This means that we cannot provide random testing for expMod at the moment. +expMod _ _ 0 = fail "Cannot divide by zero" +expMod 500 0 500 = pure 1 +expMod 500 5 500 = pure 0 +expMod 1 (-3) 4 = pure 1 +expMod 2 (-3) 3 = pure 2 +expMod 4 (-5) 9 = pure 4 +expMod 2 (-3) 4 = fail "expMod: failure" +expMod 500 (-5) 5 = fail "expMod: failure" +-- FIXME: this has to be fixed either by deciding to stop supporting GHC8.10 +-- or by backporting ghc-bignum's integerPowMod# implementation to old ghc8.10/integer-gmp<1.1 +expMod _b _e _m = fail "expMod: FIXME: stub for GHC8.10, report to plutus developers" +#endif + +expMod :: Integer -> Integer -> Natural -> BuiltinResult Natural +{-# INLINE expMod #-} diff --git a/plutus-core/plutus-core/src/PlutusCore/Default/Builtins.hs b/plutus-core/plutus-core/src/PlutusCore/Default/Builtins.hs index 2d986657520..ff2a4164a31 100644 --- a/plutus-core/plutus-core/src/PlutusCore/Default/Builtins.hs +++ b/plutus-core/plutus-core/src/PlutusCore/Default/Builtins.hs @@ -32,6 +32,7 @@ import PlutusCore.Crypto.BLS12_381.G1 qualified as BLS12_381.G1 import PlutusCore.Crypto.BLS12_381.G2 qualified as BLS12_381.G2 import PlutusCore.Crypto.BLS12_381.Pairing qualified as BLS12_381.Pairing import PlutusCore.Crypto.Ed25519 (verifyEd25519Signature_V1, verifyEd25519Signature_V2) +import PlutusCore.Crypto.ExpMod qualified as ExpMod import PlutusCore.Crypto.Hash qualified as Hash import PlutusCore.Crypto.Secp256k1 (verifyEcdsaSecp256k1Signature, verifySchnorrSecp256k1Signature) @@ -169,6 +170,7 @@ data DefaultFun | FindFirstSetBit -- Ripemd_160 | Ripemd_160 + | ExpModInteger deriving stock (Show, Eq, Ord, Enum, Bounded, Generic, Ix) deriving anyclass (NFData, Hashable, PrettyBy PrettyConfigPlc) @@ -1992,6 +1994,14 @@ instance uni ~ DefaultUni => ToBuiltinMeaning uni DefaultFun where ripemd_160Denotation (runCostingFunOneArgument . paramRipemd_160) + toBuiltinMeaning _semvar ExpModInteger = + let expModIntegerDenotation :: Integer -> Integer -> Natural -> BuiltinResult Natural + expModIntegerDenotation = ExpMod.expMod + {-# INLINE expModIntegerDenotation #-} + in makeBuiltinMeaning + expModIntegerDenotation + (runCostingFunThreeArguments . paramExpModInteger) + -- See Note [Inlining meanings of builtins]. {-# INLINE toBuiltinMeaning #-} @@ -2132,6 +2142,8 @@ instance Flat DefaultFun where FindFirstSetBit -> 85 Ripemd_160 -> 86 + ExpModInteger -> 87 + decode = go =<< decodeBuiltin where go 0 = pure AddInteger go 1 = pure SubtractInteger @@ -2220,6 +2232,7 @@ instance Flat DefaultFun where go 84 = pure CountSetBits go 85 = pure FindFirstSetBit go 86 = pure Ripemd_160 + go 87 = pure ExpModInteger go t = fail $ "Failed to decode builtin tag, got: " ++ show t size _ n = n + builtinTagWidth diff --git a/plutus-core/plutus-core/src/PlutusCore/Evaluation/Machine/BuiltinCostModel.hs b/plutus-core/plutus-core/src/PlutusCore/Evaluation/Machine/BuiltinCostModel.hs index 42311f0cd62..b19656b6971 100644 --- a/plutus-core/plutus-core/src/PlutusCore/Evaluation/Machine/BuiltinCostModel.hs +++ b/plutus-core/plutus-core/src/PlutusCore/Evaluation/Machine/BuiltinCostModel.hs @@ -182,6 +182,7 @@ data BuiltinCostModelBase f = , paramFindFirstSetBit :: f ModelOneArgument -- Ripemd_160 , paramRipemd_160 :: f ModelOneArgument + , paramExpModInteger :: f ModelThreeArguments } deriving stock (Generic) deriving anyclass (FunctorB, TraversableB, ConstraintsB) diff --git a/plutus-core/plutus-core/src/PlutusCore/Evaluation/Machine/ExBudgetingDefaults.hs b/plutus-core/plutus-core/src/PlutusCore/Evaluation/Machine/ExBudgetingDefaults.hs index 0e0ed24ead2..5b1387859c1 100644 --- a/plutus-core/plutus-core/src/PlutusCore/Evaluation/Machine/ExBudgetingDefaults.hs +++ b/plutus-core/plutus-core/src/PlutusCore/Evaluation/Machine/ExBudgetingDefaults.hs @@ -343,6 +343,7 @@ unitCostBuiltinCostModel = BuiltinCostModelBase , paramFindFirstSetBit = unitCostOneArgument -- Ripemd_160 , paramRipemd_160 = unitCostOneArgument + , paramExpModInteger = unitCostThreeArguments } unitCekParameters :: Typeable ann => MachineParameters CekMachineCosts DefaultFun (CekValue DefaultUni DefaultFun ann) diff --git a/plutus-core/plutus-core/src/PlutusCore/Evaluation/Machine/ExMemoryUsage.hs b/plutus-core/plutus-core/src/PlutusCore/Evaluation/Machine/ExMemoryUsage.hs index e3b4fb2136e..e208410037f 100644 --- a/plutus-core/plutus-core/src/PlutusCore/Evaluation/Machine/ExMemoryUsage.hs +++ b/plutus-core/plutus-core/src/PlutusCore/Evaluation/Machine/ExMemoryUsage.hs @@ -31,6 +31,7 @@ import Data.Word import GHC.Exts (Int (I#)) import GHC.Integer import GHC.Integer.Logarithms +import GHC.Natural import GHC.Prim import Universe @@ -233,6 +234,11 @@ instance ExMemoryUsage Integer where memoryUsage i = singletonRose $ memoryUsageInteger i {-# INLINE memoryUsage #-} +instance ExMemoryUsage Natural where + -- Same as Integer since we are going via Integer + memoryUsage n = memoryUsage $ toInteger n + {-# INLINE memoryUsage #-} + instance ExMemoryUsage Word8 where memoryUsage _ = singletonRose 1 {-# INLINE memoryUsage #-} diff --git a/plutus-core/plutus-core/test/CostModelSafety/Spec.hs b/plutus-core/plutus-core/test/CostModelSafety/Spec.hs index 603e655c168..d3d81100e4c 100644 --- a/plutus-core/plutus-core/test/CostModelSafety/Spec.hs +++ b/plutus-core/plutus-core/test/CostModelSafety/Spec.hs @@ -49,6 +49,7 @@ import Data.Kind qualified as GHC (Type) import Data.List.Extra (enumerate) import Data.Text (Text) import Data.Word (Word8) +import GHC.Natural import Test.Tasty (TestTree, testGroup) import Test.Tasty.HUnit (Assertion, assertBool, testCase) import Type.Reflection (TypeRep, eqTypeRep, pattern App, typeRep, (:~~:) (..)) @@ -108,6 +109,7 @@ smallConstant :: forall (a :: GHC.Type). TypeRep a -> SomeConst DefaultUni smallConstant tr | Just HRefl <- eqTypeRep tr (typeRep @()) = SomeConst () | Just HRefl <- eqTypeRep tr (typeRep @Integer) = SomeConst (0 :: Integer) + | Just HRefl <- eqTypeRep tr (typeRep @Natural) = SomeConst (0 :: Integer) | Just HRefl <- eqTypeRep tr (typeRep @Int) = SomeConst (0 :: Integer) | Just HRefl <- eqTypeRep tr (typeRep @Word8) = SomeConst (0 :: Integer) | Just HRefl <- eqTypeRep tr (typeRep @NumBytesCostedAsNumWords) = SomeConst (0 :: Integer) diff --git a/plutus-core/plutus-core/test/TypeSynthesis/Golden/DefaultFun/ExpModInteger.plc.golden b/plutus-core/plutus-core/test/TypeSynthesis/Golden/DefaultFun/ExpModInteger.plc.golden new file mode 100644 index 00000000000..c78f4787d46 --- /dev/null +++ b/plutus-core/plutus-core/test/TypeSynthesis/Golden/DefaultFun/ExpModInteger.plc.golden @@ -0,0 +1 @@ +integer -> integer -> integer -> integer \ No newline at end of file diff --git a/plutus-core/plutus-core/test/TypeSynthesis/Golden/DefaultFun/Ripemd_160.plc.golden b/plutus-core/plutus-core/test/TypeSynthesis/Golden/DefaultFun/Ripemd_160.plc.golden new file mode 100644 index 00000000000..770236177ca --- /dev/null +++ b/plutus-core/plutus-core/test/TypeSynthesis/Golden/DefaultFun/Ripemd_160.plc.golden @@ -0,0 +1 @@ +bytestring -> bytestring \ No newline at end of file diff --git a/plutus-core/plutus-ir/src/PlutusIR/Transform/RewriteRules/CommuteFnWithConst.hs b/plutus-core/plutus-ir/src/PlutusIR/Transform/RewriteRules/CommuteFnWithConst.hs index dbb70ed0541..c35a22ad479 100644 --- a/plutus-core/plutus-ir/src/PlutusIR/Transform/RewriteRules/CommuteFnWithConst.hs +++ b/plutus-core/plutus-ir/src/PlutusIR/Transform/RewriteRules/CommuteFnWithConst.hs @@ -143,3 +143,4 @@ isCommutative = \case RotateByteString -> False CountSetBits -> False FindFirstSetBit -> False + ExpModInteger -> False diff --git a/plutus-core/testlib/PlutusCore/Generators/Hedgehog/Builtin.hs b/plutus-core/testlib/PlutusCore/Generators/Hedgehog/Builtin.hs index c29b51d3a66..6acd21a1291 100644 --- a/plutus-core/testlib/PlutusCore/Generators/Hedgehog/Builtin.hs +++ b/plutus-core/testlib/PlutusCore/Generators/Hedgehog/Builtin.hs @@ -27,6 +27,7 @@ import Data.Kind qualified as GHC import Data.Text (Text) import Data.Type.Equality import Data.Word (Word8) +import GHC.Natural import Hedgehog hiding (Opaque, Var, eval) import Hedgehog.Gen qualified as Gen import Hedgehog.Gen.QuickCheck (arbitrary) @@ -75,6 +76,7 @@ genConstant tr | Just HRefl <- eqTypeRep tr (typeRep @Integer) = genArbitraryBuiltin @Integer | Just HRefl <- eqTypeRep tr (typeRep @Int) = genArbitraryBuiltin @Integer | Just HRefl <- eqTypeRep tr (typeRep @Word8) = genArbitraryBuiltin @Integer + | Just HRefl <- eqTypeRep tr (typeRep @Natural) = genArbitraryBuiltin @Integer | Just HRefl <- eqTypeRep tr (typeRep @NumBytesCostedAsNumWords) = genArbitraryBuiltin @Integer | Just HRefl <- eqTypeRep tr (typeRep @IntegerCostedLiterally) = genArbitraryBuiltin @Integer | Just HRefl <- eqTypeRep tr (typeRep @Bool) = genArbitraryBuiltin @Bool diff --git a/plutus-core/untyped-plutus-core/test/Evaluation/Builtins/Definition.hs b/plutus-core/untyped-plutus-core/test/Evaluation/Builtins/Definition.hs index dbe2fe816ec..8cb8a32f2d5 100644 --- a/plutus-core/untyped-plutus-core/test/Evaluation/Builtins/Definition.hs +++ b/plutus-core/untyped-plutus-core/test/Evaluation/Builtins/Definition.hs @@ -1,6 +1,7 @@ -- editorconfig-checker-disable-file -- | Tests for all kinds of built-in functions. +{-# LANGUAGE CPP #-} {-# LANGUAGE LambdaCase #-} {-# LANGUAGE OverloadedStrings #-} {-# LANGUAGE PartialTypeSignatures #-} @@ -476,7 +477,7 @@ test_TrackCostsRetaining = err = concat [ "Too many elements picked up by GC\n" , "Expected at most: " ++ show expected ++ "\n" - , "But got: " ++ show actual + , "But got: " ++ show actual ++ "\n" , "The result was: " ++ show res ] assertBool err $ expected > actual @@ -573,6 +574,27 @@ test_Integer = testNestedM "Integer" $ do evals False LessThanEqualsInteger [] [cons @Integer 4001, cons @Integer 4000] evals True EqualsInteger [] [cons @Integer (-101), cons @Integer (-101)] evals False EqualsInteger [] [cons @Integer 0, cons @Integer 1] + for_ [DivideInteger, QuotientInteger, ModInteger, RemainderInteger] $ \ b -> + fails (lowerInitialChar $ show b <> "-div-by-zero") b [] [cons @Integer 1, cons @Integer 0] + test_ExpModInteger + +test_ExpModInteger :: TestNested +test_ExpModInteger = testNestedM "ExpMod" $ do + evals @Integer 1 b [] [cons @Integer 500, cons @Integer 0, cons @Integer 500] -- base:X, exp: zero, mod: X(strictpos) + evals @Integer 0 b [] [cons @Integer 500, cons @Integer 5, cons @Integer 500] -- base:X, exp: strictpos, mod: X(strictpos) + evals @Integer 1 b [] [one , cons @Integer (-3), cons @Integer 4] -- base:1, exp: * , mod: strictpos + evals @Integer 2 b [] [cons @Integer 2, cons @Integer (-3), cons @Integer 3] -- base:*, exp: neg, mod: prime + -- base is co-prime with mod and exponent is negative + evals @Integer 4 b [] [cons @Integer 4, cons @Integer (-5), cons @Integer 9] + fails "mod-zero" b [] [one, one, cons @Integer 0] -- base:*, exp:*, mod: 0 + fails "mod-neg" b [] [one, one, cons @Integer (-3)] -- base:*, exp:*, mod: neg + -- base and mod are not co-prime, negative exponent + fails "exp-neg-non-inverse1" b [] [cons @Integer 2, cons @Integer (-3), cons @Integer 4] + -- mod is prime, but base&mod are not co-prime, negative exponent + fails "exp-neg-non-inverse2" b [] [cons @Integer 500, cons @Integer (-5), cons @Integer 5] + where + one = cons @Integer 1 + b = ExpModInteger -- | Test all string-like builtins test_String :: TestNested @@ -1116,7 +1138,18 @@ test_definition = , test_SwapEls , test_IdBuiltinData , test_TrackCostsRestricting +#if MIN_VERSION_base(4,15,0) + -- FIXME: @effectfully + -- broken only for darwin :x86_64-darwin.ghc810 + -- TrackCosts: retaining: FAIL (0.51s) + -- untyped-plutus-core/test/Evaluation/Builtins/Definition.hs:482: + -- Too many elements picked up by GC + -- Expected at most: 5 + -- But got: 6 + -- The result was: [6829,0,0,0,0,3173] + -- Use -p '/TrackCosts: retaining/' to rerun this test only. , test_TrackCostsRetaining +#endif , test_SerialiseDataImpossible , runTestNestedHere [ test_Integer diff --git a/plutus-core/untyped-plutus-core/test/Evaluation/Builtins/Golden/Integer/ExpMod/exp-neg-non-inverse1.err.golden b/plutus-core/untyped-plutus-core/test/Evaluation/Builtins/Golden/Integer/ExpMod/exp-neg-non-inverse1.err.golden new file mode 100644 index 00000000000..39d6113a876 --- /dev/null +++ b/plutus-core/untyped-plutus-core/test/Evaluation/Builtins/Golden/Integer/ExpMod/exp-neg-non-inverse1.err.golden @@ -0,0 +1,5 @@ +An error has occurred: +The machine terminated because of an error, either from a built-in function or from an explicit use of 'error'. +Caused by: expModInteger 2 -3 4 +Logs were: +expMod: failure \ No newline at end of file diff --git a/plutus-core/untyped-plutus-core/test/Evaluation/Builtins/Golden/Integer/ExpMod/exp-neg-non-inverse2.err.golden b/plutus-core/untyped-plutus-core/test/Evaluation/Builtins/Golden/Integer/ExpMod/exp-neg-non-inverse2.err.golden new file mode 100644 index 00000000000..dca0254f11a --- /dev/null +++ b/plutus-core/untyped-plutus-core/test/Evaluation/Builtins/Golden/Integer/ExpMod/exp-neg-non-inverse2.err.golden @@ -0,0 +1,5 @@ +An error has occurred: +The machine terminated because of an error, either from a built-in function or from an explicit use of 'error'. +Caused by: expModInteger 500 -5 5 +Logs were: +expMod: failure \ No newline at end of file diff --git a/plutus-core/untyped-plutus-core/test/Evaluation/Builtins/Golden/Integer/ExpMod/mod-neg.err.golden b/plutus-core/untyped-plutus-core/test/Evaluation/Builtins/Golden/Integer/ExpMod/mod-neg.err.golden new file mode 100644 index 00000000000..917d2d185d6 --- /dev/null +++ b/plutus-core/untyped-plutus-core/test/Evaluation/Builtins/Golden/Integer/ExpMod/mod-neg.err.golden @@ -0,0 +1,5 @@ +An error has occurred: +The machine terminated because of an error, either from a built-in function or from an explicit use of 'error'. +Caused by: expModInteger 1 1 -3 +Logs were: +-3 is not within the bounds of Natural \ No newline at end of file diff --git a/plutus-core/untyped-plutus-core/test/Evaluation/Builtins/Golden/Integer/ExpMod/mod-zero.err.golden b/plutus-core/untyped-plutus-core/test/Evaluation/Builtins/Golden/Integer/ExpMod/mod-zero.err.golden new file mode 100644 index 00000000000..d30ffd6b7e5 --- /dev/null +++ b/plutus-core/untyped-plutus-core/test/Evaluation/Builtins/Golden/Integer/ExpMod/mod-zero.err.golden @@ -0,0 +1,5 @@ +An error has occurred: +The machine terminated because of an error, either from a built-in function or from an explicit use of 'error'. +Caused by: expModInteger 1 1 0 +Logs were: +Cannot divide by zero \ No newline at end of file diff --git a/plutus-core/untyped-plutus-core/test/Evaluation/Builtins/Golden/Integer/divideInteger-div-by-zero.err.golden b/plutus-core/untyped-plutus-core/test/Evaluation/Builtins/Golden/Integer/divideInteger-div-by-zero.err.golden new file mode 100644 index 00000000000..90cbfbc5f59 --- /dev/null +++ b/plutus-core/untyped-plutus-core/test/Evaluation/Builtins/Golden/Integer/divideInteger-div-by-zero.err.golden @@ -0,0 +1,5 @@ +An error has occurred: +The machine terminated because of an error, either from a built-in function or from an explicit use of 'error'. +Caused by: divideInteger 1 0 +Logs were: +Cannot divide by zero \ No newline at end of file diff --git a/plutus-core/untyped-plutus-core/test/Evaluation/Builtins/Golden/Integer/modInteger-div-by-zero.err.golden b/plutus-core/untyped-plutus-core/test/Evaluation/Builtins/Golden/Integer/modInteger-div-by-zero.err.golden new file mode 100644 index 00000000000..65145f3b845 --- /dev/null +++ b/plutus-core/untyped-plutus-core/test/Evaluation/Builtins/Golden/Integer/modInteger-div-by-zero.err.golden @@ -0,0 +1,5 @@ +An error has occurred: +The machine terminated because of an error, either from a built-in function or from an explicit use of 'error'. +Caused by: modInteger 1 0 +Logs were: +Cannot divide by zero \ No newline at end of file diff --git a/plutus-core/untyped-plutus-core/test/Evaluation/Builtins/Golden/Integer/quotientInteger-div-by-zero.err.golden b/plutus-core/untyped-plutus-core/test/Evaluation/Builtins/Golden/Integer/quotientInteger-div-by-zero.err.golden new file mode 100644 index 00000000000..9e9bedb4ac8 --- /dev/null +++ b/plutus-core/untyped-plutus-core/test/Evaluation/Builtins/Golden/Integer/quotientInteger-div-by-zero.err.golden @@ -0,0 +1,5 @@ +An error has occurred: +The machine terminated because of an error, either from a built-in function or from an explicit use of 'error'. +Caused by: quotientInteger 1 0 +Logs were: +Cannot divide by zero \ No newline at end of file diff --git a/plutus-core/untyped-plutus-core/test/Evaluation/Builtins/Golden/Integer/remainderInteger-div-by-zero.err.golden b/plutus-core/untyped-plutus-core/test/Evaluation/Builtins/Golden/Integer/remainderInteger-div-by-zero.err.golden new file mode 100644 index 00000000000..b55a5d1bf2e --- /dev/null +++ b/plutus-core/untyped-plutus-core/test/Evaluation/Builtins/Golden/Integer/remainderInteger-div-by-zero.err.golden @@ -0,0 +1,5 @@ +An error has occurred: +The machine terminated because of an error, either from a built-in function or from an explicit use of 'error'. +Caused by: remainderInteger 1 0 +Logs were: +Cannot divide by zero \ No newline at end of file diff --git a/plutus-ledger-api/changelog.d/20240726_125029_bezirg_modexp.md b/plutus-ledger-api/changelog.d/20240726_125029_bezirg_modexp.md new file mode 100644 index 00000000000..b2cf111c1be --- /dev/null +++ b/plutus-ledger-api/changelog.d/20240726_125029_bezirg_modexp.md @@ -0,0 +1,3 @@ +### Added + +- Guarded the draft 'modularExponentation' builtin behind a future protocol version. diff --git a/plutus-ledger-api/src/PlutusLedgerApi/Common/Versions.hs b/plutus-ledger-api/src/PlutusLedgerApi/Common/Versions.hs index 9358e6d8996..bf350e32e89 100644 --- a/plutus-ledger-api/src/PlutusLedgerApi/Common/Versions.hs +++ b/plutus-ledger-api/src/PlutusLedgerApi/Common/Versions.hs @@ -124,7 +124,7 @@ builtinsIntroducedIn = Map.fromList [ AndByteString, OrByteString, XorByteString, ComplementByteString, ReadBit, WriteBits, ReplicateByte, ShiftByteString, RotateByteString, CountSetBits, FindFirstSetBit, - Ripemd_160 + Ripemd_160, ExpModInteger ]) ] diff --git a/plutus-ledger-api/src/PlutusLedgerApi/V3/ParamName.hs b/plutus-ledger-api/src/PlutusLedgerApi/V3/ParamName.hs index 68186fd1c59..6bb55daf086 100644 --- a/plutus-ledger-api/src/PlutusLedgerApi/V3/ParamName.hs +++ b/plutus-ledger-api/src/PlutusLedgerApi/V3/ParamName.hs @@ -266,5 +266,8 @@ data ParamName = | ByteStringToInteger'cpu'arguments'c2 | ByteStringToInteger'memory'arguments'intercept | ByteStringToInteger'memory'arguments'slope + -- not enabled yet: + -- | ExpModInteger'cpu'arguments + -- | ExpModInteger'memory'arguments deriving stock (Eq, Ord, Enum, Ix, Bounded, Generic) deriving IsParamName via (GenericParamName ParamName) diff --git a/plutus-ledger-api/testlib/PlutusLedgerApi/Test/V3/Data/EvaluationContext.hs b/plutus-ledger-api/testlib/PlutusLedgerApi/Test/V3/Data/EvaluationContext.hs index dc5c814ba6b..78d2cf263df 100644 --- a/plutus-ledger-api/testlib/PlutusLedgerApi/Test/V3/Data/EvaluationContext.hs +++ b/plutus-ledger-api/testlib/PlutusLedgerApi/Test/V3/Data/EvaluationContext.hs @@ -83,6 +83,7 @@ clearBuiltinCostModel r = r , paramCountSetBits = mempty , paramFindFirstSetBit = mempty , paramRipemd_160 = mempty + , paramExpModInteger = mempty } @@ -104,4 +105,5 @@ clearBuiltinCostModel' r = r , paramCountSetBits = mempty , paramFindFirstSetBit = mempty , paramRipemd_160 = mempty + , paramExpModInteger = mempty } diff --git a/plutus-ledger-api/testlib/PlutusLedgerApi/Test/V3/EvaluationContext.hs b/plutus-ledger-api/testlib/PlutusLedgerApi/Test/V3/EvaluationContext.hs index 91de05a908a..cc7663e0b6d 100644 --- a/plutus-ledger-api/testlib/PlutusLedgerApi/Test/V3/EvaluationContext.hs +++ b/plutus-ledger-api/testlib/PlutusLedgerApi/Test/V3/EvaluationContext.hs @@ -84,6 +84,7 @@ clearBuiltinCostModel r = r , paramCountSetBits = mempty , paramFindFirstSetBit = mempty , paramRipemd_160 = mempty + , paramExpModInteger = mempty } @@ -105,4 +106,5 @@ clearBuiltinCostModel' r = r , paramCountSetBits = mempty , paramFindFirstSetBit = mempty , paramRipemd_160 = mempty + , paramExpModInteger = mempty } diff --git a/plutus-metatheory/src/Algorithmic/CEK.lagda.md b/plutus-metatheory/src/Algorithmic/CEK.lagda.md index 4765db402b0..ba1f5fa3b9f 100644 --- a/plutus-metatheory/src/Algorithmic/CEK.lagda.md +++ b/plutus-metatheory/src/Algorithmic/CEK.lagda.md @@ -337,6 +337,9 @@ BUILTIN shiftByteString (base $ V-con s $ V-con i) = inj₂ (V-con (shiftBYTESTR BUILTIN rotateByteString (base $ V-con s $ V-con i) = inj₂ (V-con (rotateBYTESTRING s i)) BUILTIN countSetBits (base $ V-con s) = inj₂ (V-con (countSetBITS s)) BUILTIN findFirstSetBit (base $ V-con s) = inj₂ (V-con (findFirstSetBIT s)) +BUILTIN expModInteger (base $ V-con b $ V-con e $ V-con m) with expModINTEGER b e m +... | just r = inj₂ (V-con r) +... | nothing = inj₁ (con (ne (^ (atomic aInteger)))) BUILTIN' : ∀ b {A} → ∀{tn} → {pt : tn ∔ 0 ≣ fv (signature b)} diff --git a/plutus-metatheory/src/Builtin.lagda.md b/plutus-metatheory/src/Builtin.lagda.md index 700a021ee32..ff03926842c 100644 --- a/plutus-metatheory/src/Builtin.lagda.md +++ b/plutus-metatheory/src/Builtin.lagda.md @@ -145,6 +145,8 @@ data Builtin : Set where findFirstSetBit : Builtin -- Ripemd-160 ripemd-160 : Builtin + -- Modular Exponentiation + expModInteger : Builtin ``` ## Signatures @@ -325,6 +327,7 @@ sig n⋆ n♯ (t₃ ∷ t₂ ∷ t₁) tᵣ signature rotateByteString = ∙ [ bytestring ↑ , integer ↑ ]⟶ bytestring ↑ signature countSetBits = ∙ [ bytestring ↑ ]⟶ integer ↑ signature findFirstSetBit = ∙ [ bytestring ↑ ]⟶ integer ↑ + signature expModInteger = ∙ [ integer ↑ , integer ↑ , integer ↑ ]⟶ integer ↑ open SugaredSignature using (signature) public @@ -427,6 +430,7 @@ Each Agda built-in name must be mapped to a Haskell name. | CountSetBits | FindFirstSetBit | Ripemd_160 + | ExpModInteger ) #-} ``` @@ -494,6 +498,7 @@ postulate countSetBITS : ByteString -> Int findFirstSetBIT : ByteString -> Int RIPEMD-160 : ByteString → ByteString + expModINTEGER : Int -> Int -> Int -> Maybe Int ``` ### What builtin operations should be compiled to if we compile to Haskell @@ -617,6 +622,13 @@ postulate {-# COMPILE GHC findFirstSetBIT = \s -> fromIntegral $ Bitwise.findFirstSetBit s #-} {-# COMPILE GHC RIPEMD-160 = Hash.ripemd_160 #-} +{-# FOREIGN GHC import PlutusCore.Crypto.ExpMod qualified as ExpMod #-} +-- here we explicitly do a Natural-check on m; the builtin machinery in plutus does such a check usually implicitly +-- but we cannot use the builtin machinery here. +{-# COMPILE GHC expModINTEGER = \b e m -> + if m < 0 + then Nothing + else fmap fromIntegral $ builtinResultToMaybe $ ExpMod.expMod b e (fromIntegral m) #-} -- no binding needed for appendStr -- no binding needed for traceStr diff --git a/plutus-metatheory/src/Untyped/CEK.lagda.md b/plutus-metatheory/src/Untyped/CEK.lagda.md index 0065fa9c032..aeff2f50e6b 100644 --- a/plutus-metatheory/src/Untyped/CEK.lagda.md +++ b/plutus-metatheory/src/Untyped/CEK.lagda.md @@ -564,6 +564,13 @@ BUILTIN ripemd-160 = λ { (app base (V-con bytestring b)) -> inj₂ (V-con bytestring (RIPEMD-160 b)) ; _ -> inj₁ userError } +BUILTIN expModInteger = λ + { (app (app (app base (V-con integer b)) (V-con integer e)) (V-con integer m)) -> case expModINTEGER b e m of λ + { (just r) -> inj₂ (V-con integer r) + ; nothing -> inj₁ userError + } + ; _ -> inj₁ userError + } -- Take an apparently more general index and show that it is a fully applied builtin. mkFullyAppliedBuiltin : ∀ { b } diff --git a/plutus-tx-plugin/changelog.d/20240726_125023_bezirg_modexp.md b/plutus-tx-plugin/changelog.d/20240726_125023_bezirg_modexp.md new file mode 100644 index 00000000000..feac9820297 --- /dev/null +++ b/plutus-tx-plugin/changelog.d/20240726_125023_bezirg_modexp.md @@ -0,0 +1,3 @@ +### Added + +- Enabled the draft modularExponentation builtin. diff --git a/plutus-tx-plugin/src/PlutusTx/Compiler/Builtins.hs b/plutus-tx-plugin/src/PlutusTx/Compiler/Builtins.hs index 55c580342d7..e6db60bed88 100644 --- a/plutus-tx-plugin/src/PlutusTx/Compiler/Builtins.hs +++ b/plutus-tx-plugin/src/PlutusTx/Compiler/Builtins.hs @@ -291,6 +291,8 @@ builtinNames = [ , 'Builtins.rotateByteString , 'Builtins.countSetBits , 'Builtins.findFirstSetBit + + , 'Builtins.expModInteger ] defineBuiltinTerm :: CompilingDefault uni fun m ann => Ann -> TH.Name -> PIRTerm uni fun -> m () @@ -464,6 +466,8 @@ defineBuiltinTerms = do PLC.CountSetBits -> defineBuiltinInl 'Builtins.countSetBits PLC.FindFirstSetBit -> defineBuiltinInl 'Builtins.findFirstSetBit + PLC.ExpModInteger -> defineBuiltinInl 'Builtins.expModInteger + defineBuiltinTypes :: CompilingDefault uni fun m ann => m () diff --git a/plutus-tx-plugin/src/PlutusTx/Plugin.hs b/plutus-tx-plugin/src/PlutusTx/Plugin.hs index 70fea6b85c2..7da8be82147 100644 --- a/plutus-tx-plugin/src/PlutusTx/Plugin.hs +++ b/plutus-tx-plugin/src/PlutusTx/Plugin.hs @@ -378,7 +378,7 @@ emitRuntimeError codeTy e = do let shown = show $ PP.pretty (pruneContext (_posContextLevel opts) e) tcName <- thNameToGhcNameOrFail ''CompiledCode tc <- lift . lift $ GHC.lookupTyCon tcName -#if MIN_VERSION_ghc (9,6,0) +#if MIN_VERSION_ghc(9,6,0) pure $ GHC.mkImpossibleExpr (GHC.mkTyConApp tc [codeTy]) shown #else pure $ GHC.mkRuntimeErrorApp GHC.rUNTIME_ERROR_ID (GHC.mkTyConApp tc [codeTy]) shown diff --git a/plutus-tx-plugin/test/Plugin/Profiling/9.6/addInt.pir.golden b/plutus-tx-plugin/test/Plugin/Profiling/9.6/addInt.pir.golden index 5bcee06806b..d77b76dda76 100644 --- a/plutus-tx-plugin/test/Plugin/Profiling/9.6/addInt.pir.golden +++ b/plutus-tx-plugin/test/Plugin/Profiling/9.6/addInt.pir.golden @@ -13,9 +13,9 @@ program in trace {unit -> integer} - "entering addInteger-130" + "entering addInteger-131" (\(thunk : unit) -> - trace {integer} "exiting addInteger-130" (addInteger x y)) + trace {integer} "exiting addInteger-131" (addInteger x y)) () ~addInt : integer -> integer -> integer = \(x : integer) -> @@ -24,9 +24,9 @@ program in trace {unit -> integer -> integer} - "entering addInt-127" + "entering addInt-128" (\(thunk : unit) -> - trace {integer -> integer} "exiting addInt-127" (addInteger x)) + trace {integer -> integer} "exiting addInt-128" (addInteger x)) () in addInt) \ No newline at end of file diff --git a/plutus-tx-plugin/test/Plugin/Profiling/9.6/addInt3.eval.golden b/plutus-tx-plugin/test/Plugin/Profiling/9.6/addInt3.eval.golden index ad9a3684df7..66b848fa868 100644 --- a/plutus-tx-plugin/test/Plugin/Profiling/9.6/addInt3.eval.golden +++ b/plutus-tx-plugin/test/Plugin/Profiling/9.6/addInt3.eval.golden @@ -1 +1 @@ -[entering addInt-127, exiting addInt-127] \ No newline at end of file +[entering addInt-128, exiting addInt-128] \ No newline at end of file diff --git a/plutus-tx-plugin/test/Plugin/Profiling/9.6/argMismatch1.eval.golden b/plutus-tx-plugin/test/Plugin/Profiling/9.6/argMismatch1.eval.golden index 84d1bfa97c9..19f028f27ca 100644 --- a/plutus-tx-plugin/test/Plugin/Profiling/9.6/argMismatch1.eval.golden +++ b/plutus-tx-plugin/test/Plugin/Profiling/9.6/argMismatch1.eval.golden @@ -1,6 +1,6 @@ -[ entering runIdentity-130 -, exiting runIdentity-130 -, entering newtypeFunction-138 -, exiting newtypeFunction-138 -, entering `$fFoldableIdentity`-132 -, exiting `$fFoldableIdentity`-132 ] \ No newline at end of file +[ entering runIdentity-131 +, exiting runIdentity-131 +, entering newtypeFunction-139 +, exiting newtypeFunction-139 +, entering `$fFoldableIdentity`-133 +, exiting `$fFoldableIdentity`-133 ] \ No newline at end of file diff --git a/plutus-tx-plugin/test/Plugin/Profiling/9.6/argMismatch2.eval.golden b/plutus-tx-plugin/test/Plugin/Profiling/9.6/argMismatch2.eval.golden index 8247a445426..866a739a4c8 100644 --- a/plutus-tx-plugin/test/Plugin/Profiling/9.6/argMismatch2.eval.golden +++ b/plutus-tx-plugin/test/Plugin/Profiling/9.6/argMismatch2.eval.golden @@ -1 +1 @@ -[entering obscuredFunction-128, exiting obscuredFunction-128] \ No newline at end of file +[entering obscuredFunction-129, exiting obscuredFunction-129] \ No newline at end of file diff --git a/plutus-tx-plugin/test/Plugin/Profiling/9.6/fact4.eval.golden b/plutus-tx-plugin/test/Plugin/Profiling/9.6/fact4.eval.golden index 4a02cd564b2..33f55c5979c 100644 --- a/plutus-tx-plugin/test/Plugin/Profiling/9.6/fact4.eval.golden +++ b/plutus-tx-plugin/test/Plugin/Profiling/9.6/fact4.eval.golden @@ -1,36 +1,36 @@ -[ entering fact-127 -, entering equalsInteger-134 -, exiting equalsInteger-134 -, entering subtractInteger-151 -, exiting subtractInteger-151 -, entering fact-127 -, entering equalsInteger-134 -, exiting equalsInteger-134 -, entering subtractInteger-151 -, exiting subtractInteger-151 -, entering fact-127 -, entering equalsInteger-134 -, exiting equalsInteger-134 -, entering subtractInteger-151 -, exiting subtractInteger-151 -, entering fact-127 -, entering equalsInteger-134 -, exiting equalsInteger-134 -, entering subtractInteger-151 -, exiting subtractInteger-151 -, entering fact-127 -, entering equalsInteger-134 -, exiting equalsInteger-134 -, exiting fact-127 -, entering multiplyInteger-145 -, exiting multiplyInteger-145 -, exiting fact-127 -, entering multiplyInteger-145 -, exiting multiplyInteger-145 -, exiting fact-127 -, entering multiplyInteger-145 -, exiting multiplyInteger-145 -, exiting fact-127 -, entering multiplyInteger-145 -, exiting multiplyInteger-145 -, exiting fact-127 ] \ No newline at end of file +[ entering fact-128 +, entering equalsInteger-135 +, exiting equalsInteger-135 +, entering subtractInteger-152 +, exiting subtractInteger-152 +, entering fact-128 +, entering equalsInteger-135 +, exiting equalsInteger-135 +, entering subtractInteger-152 +, exiting subtractInteger-152 +, entering fact-128 +, entering equalsInteger-135 +, exiting equalsInteger-135 +, entering subtractInteger-152 +, exiting subtractInteger-152 +, entering fact-128 +, entering equalsInteger-135 +, exiting equalsInteger-135 +, entering subtractInteger-152 +, exiting subtractInteger-152 +, entering fact-128 +, entering equalsInteger-135 +, exiting equalsInteger-135 +, exiting fact-128 +, entering multiplyInteger-146 +, exiting multiplyInteger-146 +, exiting fact-128 +, entering multiplyInteger-146 +, exiting multiplyInteger-146 +, exiting fact-128 +, entering multiplyInteger-146 +, exiting multiplyInteger-146 +, exiting fact-128 +, entering multiplyInteger-146 +, exiting multiplyInteger-146 +, exiting fact-128 ] \ No newline at end of file diff --git a/plutus-tx-plugin/test/Plugin/Profiling/9.6/fib.pir.golden b/plutus-tx-plugin/test/Plugin/Profiling/9.6/fib.pir.golden index 11540b3f80f..c53e980e4c4 100644 --- a/plutus-tx-plugin/test/Plugin/Profiling/9.6/fib.pir.golden +++ b/plutus-tx-plugin/test/Plugin/Profiling/9.6/fib.pir.golden @@ -13,9 +13,9 @@ program in trace {unit -> integer} - "entering addInteger-149" + "entering addInteger-150" (\(thunk : unit) -> - trace {integer} "exiting addInteger-149" (addInteger x y)) + trace {integer} "exiting addInteger-150" (addInteger x y)) () data Bool | Bool_match where True : Bool @@ -33,11 +33,11 @@ program in trace {unit -> Bool} - "entering equalsInteger-134" + "entering equalsInteger-135" (\(thunk : unit) -> trace {Bool} - "exiting equalsInteger-134" + "exiting equalsInteger-135" (let !b : bool = equalsInteger x y in @@ -55,11 +55,11 @@ program in trace {unit -> integer} - "entering subtractInteger-155" + "entering subtractInteger-156" (\(thunk : unit) -> trace {integer} - "exiting subtractInteger-155" + "exiting subtractInteger-156" (subtractInteger x y)) () in @@ -71,11 +71,11 @@ program in trace {unit -> integer} - "entering fib-127" + "entering fib-128" (\(thunk : unit) -> trace {integer} - "exiting fib-127" + "exiting fib-128" (Bool_match (equalsInteger n 0) {all dead. integer} diff --git a/plutus-tx-plugin/test/Plugin/Profiling/9.6/fib4.eval.golden b/plutus-tx-plugin/test/Plugin/Profiling/9.6/fib4.eval.golden index ac47dd17b24..693c65f8713 100644 --- a/plutus-tx-plugin/test/Plugin/Profiling/9.6/fib4.eval.golden +++ b/plutus-tx-plugin/test/Plugin/Profiling/9.6/fib4.eval.golden @@ -1,74 +1,74 @@ -[ entering fib-127 -, entering equalsInteger-134 -, exiting equalsInteger-134 -, entering equalsInteger-134 -, exiting equalsInteger-134 -, entering subtractInteger-155 -, exiting subtractInteger-155 -, entering fib-127 -, entering equalsInteger-134 -, exiting equalsInteger-134 -, entering equalsInteger-134 -, exiting equalsInteger-134 -, entering subtractInteger-155 -, exiting subtractInteger-155 -, entering fib-127 -, entering equalsInteger-134 -, exiting equalsInteger-134 -, entering equalsInteger-134 -, exiting equalsInteger-134 -, entering subtractInteger-155 -, exiting subtractInteger-155 -, entering fib-127 -, entering equalsInteger-134 -, exiting equalsInteger-134 -, entering equalsInteger-134 -, exiting equalsInteger-134 -, exiting fib-127 -, entering subtractInteger-155 -, exiting subtractInteger-155 -, entering fib-127 -, entering equalsInteger-134 -, exiting equalsInteger-134 -, exiting fib-127 -, entering addInteger-149 -, exiting addInteger-149 -, exiting fib-127 -, entering subtractInteger-155 -, exiting subtractInteger-155 -, entering fib-127 -, entering equalsInteger-134 -, exiting equalsInteger-134 -, entering equalsInteger-134 -, exiting equalsInteger-134 -, exiting fib-127 -, entering addInteger-149 -, exiting addInteger-149 -, exiting fib-127 -, entering subtractInteger-155 -, exiting subtractInteger-155 -, entering fib-127 -, entering equalsInteger-134 -, exiting equalsInteger-134 -, entering equalsInteger-134 -, exiting equalsInteger-134 -, entering subtractInteger-155 -, exiting subtractInteger-155 -, entering fib-127 -, entering equalsInteger-134 -, exiting equalsInteger-134 -, entering equalsInteger-134 -, exiting equalsInteger-134 -, exiting fib-127 -, entering subtractInteger-155 -, exiting subtractInteger-155 -, entering fib-127 -, entering equalsInteger-134 -, exiting equalsInteger-134 -, exiting fib-127 -, entering addInteger-149 -, exiting addInteger-149 -, exiting fib-127 -, entering addInteger-149 -, exiting addInteger-149 -, exiting fib-127 ] \ No newline at end of file +[ entering fib-128 +, entering equalsInteger-135 +, exiting equalsInteger-135 +, entering equalsInteger-135 +, exiting equalsInteger-135 +, entering subtractInteger-156 +, exiting subtractInteger-156 +, entering fib-128 +, entering equalsInteger-135 +, exiting equalsInteger-135 +, entering equalsInteger-135 +, exiting equalsInteger-135 +, entering subtractInteger-156 +, exiting subtractInteger-156 +, entering fib-128 +, entering equalsInteger-135 +, exiting equalsInteger-135 +, entering equalsInteger-135 +, exiting equalsInteger-135 +, entering subtractInteger-156 +, exiting subtractInteger-156 +, entering fib-128 +, entering equalsInteger-135 +, exiting equalsInteger-135 +, entering equalsInteger-135 +, exiting equalsInteger-135 +, exiting fib-128 +, entering subtractInteger-156 +, exiting subtractInteger-156 +, entering fib-128 +, entering equalsInteger-135 +, exiting equalsInteger-135 +, exiting fib-128 +, entering addInteger-150 +, exiting addInteger-150 +, exiting fib-128 +, entering subtractInteger-156 +, exiting subtractInteger-156 +, entering fib-128 +, entering equalsInteger-135 +, exiting equalsInteger-135 +, entering equalsInteger-135 +, exiting equalsInteger-135 +, exiting fib-128 +, entering addInteger-150 +, exiting addInteger-150 +, exiting fib-128 +, entering subtractInteger-156 +, exiting subtractInteger-156 +, entering fib-128 +, entering equalsInteger-135 +, exiting equalsInteger-135 +, entering equalsInteger-135 +, exiting equalsInteger-135 +, entering subtractInteger-156 +, exiting subtractInteger-156 +, entering fib-128 +, entering equalsInteger-135 +, exiting equalsInteger-135 +, entering equalsInteger-135 +, exiting equalsInteger-135 +, exiting fib-128 +, entering subtractInteger-156 +, exiting subtractInteger-156 +, entering fib-128 +, entering equalsInteger-135 +, exiting equalsInteger-135 +, exiting fib-128 +, entering addInteger-150 +, exiting addInteger-150 +, exiting fib-128 +, entering addInteger-150 +, exiting addInteger-150 +, exiting fib-128 ] \ No newline at end of file diff --git a/plutus-tx-plugin/test/Plugin/Profiling/9.6/id.eval.golden b/plutus-tx-plugin/test/Plugin/Profiling/9.6/id.eval.golden index f676a169934..5e31f19d924 100644 --- a/plutus-tx-plugin/test/Plugin/Profiling/9.6/id.eval.golden +++ b/plutus-tx-plugin/test/Plugin/Profiling/9.6/id.eval.golden @@ -1 +1 @@ -[entering id-128, exiting id-128, entering id-128, exiting id-128] \ No newline at end of file +[entering id-129, exiting id-129, entering id-129, exiting id-129] \ No newline at end of file diff --git a/plutus-tx-plugin/test/Plugin/Profiling/9.6/idCode.pir.golden b/plutus-tx-plugin/test/Plugin/Profiling/9.6/idCode.pir.golden index 6ee433ec390..e8874d71960 100644 --- a/plutus-tx-plugin/test/Plugin/Profiling/9.6/idCode.pir.golden +++ b/plutus-tx-plugin/test/Plugin/Profiling/9.6/idCode.pir.golden @@ -6,8 +6,8 @@ program \(x : a) -> trace {unit -> a} - "entering id-128" - (\(thunk : unit) -> trace {a} "exiting id-128" x) + "entering id-129" + (\(thunk : unit) -> trace {a} "exiting id-129" x) () in id {integer} (id {integer} 1)) \ No newline at end of file diff --git a/plutus-tx-plugin/test/Plugin/Profiling/9.6/letInFun.eval.golden b/plutus-tx-plugin/test/Plugin/Profiling/9.6/letInFun.eval.golden index 0904615ba42..e598b91086d 100644 --- a/plutus-tx-plugin/test/Plugin/Profiling/9.6/letInFun.eval.golden +++ b/plutus-tx-plugin/test/Plugin/Profiling/9.6/letInFun.eval.golden @@ -1,10 +1,10 @@ -[ entering f-139 -, entering addInteger-133 -, exiting addInteger-133 -, exiting f-139 -, entering f-139 -, entering addInteger-133 -, exiting addInteger-133 -, exiting f-139 -, entering addInteger-133 -, exiting addInteger-133 ] \ No newline at end of file +[ entering f-140 +, entering addInteger-134 +, exiting addInteger-134 +, exiting f-140 +, entering f-140 +, entering addInteger-134 +, exiting addInteger-134 +, exiting f-140 +, entering addInteger-134 +, exiting addInteger-134 ] \ No newline at end of file diff --git a/plutus-tx-plugin/test/Plugin/Profiling/9.6/letInFunMoreArg.eval.golden b/plutus-tx-plugin/test/Plugin/Profiling/9.6/letInFunMoreArg.eval.golden index 748c44a94ce..42995b25478 100644 --- a/plutus-tx-plugin/test/Plugin/Profiling/9.6/letInFunMoreArg.eval.golden +++ b/plutus-tx-plugin/test/Plugin/Profiling/9.6/letInFunMoreArg.eval.golden @@ -1,12 +1,12 @@ -[ entering f-141 -, entering addInteger-135 -, exiting addInteger-135 -, exiting f-141 -, entering f-141 -, entering addInteger-135 -, exiting addInteger-135 -, exiting f-141 -, entering addInteger-135 -, exiting addInteger-135 -, entering multiplyInteger-143 -, exiting multiplyInteger-143 ] \ No newline at end of file +[ entering f-142 +, entering addInteger-136 +, exiting addInteger-136 +, exiting f-142 +, entering f-142 +, entering addInteger-136 +, exiting addInteger-136 +, exiting f-142 +, entering addInteger-136 +, exiting addInteger-136 +, entering multiplyInteger-144 +, exiting multiplyInteger-144 ] \ No newline at end of file diff --git a/plutus-tx-plugin/test/Plugin/Profiling/9.6/letRecInFun.eval.golden b/plutus-tx-plugin/test/Plugin/Profiling/9.6/letRecInFun.eval.golden index 7c287045bb2..dce946b6315 100644 --- a/plutus-tx-plugin/test/Plugin/Profiling/9.6/letRecInFun.eval.golden +++ b/plutus-tx-plugin/test/Plugin/Profiling/9.6/letRecInFun.eval.golden @@ -1,28 +1,28 @@ -[ entering f-129 -, entering equalsInteger-136 -, exiting equalsInteger-136 -, entering subtractInteger-153 -, exiting subtractInteger-153 -, entering f-129 -, entering equalsInteger-136 -, exiting equalsInteger-136 -, entering subtractInteger-153 -, exiting subtractInteger-153 -, entering f-129 -, entering equalsInteger-136 -, exiting equalsInteger-136 -, entering subtractInteger-153 -, exiting subtractInteger-153 -, entering f-129 -, entering equalsInteger-136 -, exiting equalsInteger-136 -, exiting f-129 -, entering addInteger-147 -, exiting addInteger-147 -, exiting f-129 -, entering addInteger-147 -, exiting addInteger-147 -, exiting f-129 -, entering addInteger-147 -, exiting addInteger-147 -, exiting f-129 ] \ No newline at end of file +[ entering f-130 +, entering equalsInteger-137 +, exiting equalsInteger-137 +, entering subtractInteger-154 +, exiting subtractInteger-154 +, entering f-130 +, entering equalsInteger-137 +, exiting equalsInteger-137 +, entering subtractInteger-154 +, exiting subtractInteger-154 +, entering f-130 +, entering equalsInteger-137 +, exiting equalsInteger-137 +, entering subtractInteger-154 +, exiting subtractInteger-154 +, entering f-130 +, entering equalsInteger-137 +, exiting equalsInteger-137 +, exiting f-130 +, entering addInteger-148 +, exiting addInteger-148 +, exiting f-130 +, entering addInteger-148 +, exiting addInteger-148 +, exiting f-130 +, entering addInteger-148 +, exiting addInteger-148 +, exiting f-130 ] \ No newline at end of file diff --git a/plutus-tx-plugin/test/Plugin/Profiling/9.6/swap.eval.golden b/plutus-tx-plugin/test/Plugin/Profiling/9.6/swap.eval.golden index 84c6df802db..ea3312abd43 100644 --- a/plutus-tx-plugin/test/Plugin/Profiling/9.6/swap.eval.golden +++ b/plutus-tx-plugin/test/Plugin/Profiling/9.6/swap.eval.golden @@ -1 +1 @@ -[entering swap-134, exiting swap-134] \ No newline at end of file +[entering swap-135, exiting swap-135] \ No newline at end of file diff --git a/plutus-tx-plugin/test/Plugin/Profiling/9.6/typeclass.eval.golden b/plutus-tx-plugin/test/Plugin/Profiling/9.6/typeclass.eval.golden index 608ce6329ed..5698abc5173 100644 --- a/plutus-tx-plugin/test/Plugin/Profiling/9.6/typeclass.eval.golden +++ b/plutus-tx-plugin/test/Plugin/Profiling/9.6/typeclass.eval.golden @@ -1,12 +1,12 @@ -[ entering useTypeclass-136 -, entering methodA-150 -, exiting methodA-150 -, entering addInteger-143 -, exiting addInteger-143 -, entering methodB-161 -, exiting methodB-161 -, entering subtractInteger-173 -, exiting subtractInteger-173 -, entering addInteger-143 -, exiting addInteger-143 -, exiting useTypeclass-136 ] \ No newline at end of file +[ entering useTypeclass-137 +, entering methodA-151 +, exiting methodA-151 +, entering addInteger-144 +, exiting addInteger-144 +, entering methodB-162 +, exiting methodB-162 +, entering subtractInteger-174 +, exiting subtractInteger-174 +, entering addInteger-144 +, exiting addInteger-144 +, exiting useTypeclass-137 ] \ No newline at end of file diff --git a/plutus-tx/changelog.d/20240726_125008_bezirg_modexp.md b/plutus-tx/changelog.d/20240726_125008_bezirg_modexp.md new file mode 100644 index 00000000000..feac9820297 --- /dev/null +++ b/plutus-tx/changelog.d/20240726_125008_bezirg_modexp.md @@ -0,0 +1,3 @@ +### Added + +- Enabled the draft modularExponentation builtin. diff --git a/plutus-tx/src/PlutusTx/Builtins.hs b/plutus-tx/src/PlutusTx/Builtins.hs index 2c66e6ac03c..78a39fe09e2 100644 --- a/plutus-tx/src/PlutusTx/Builtins.hs +++ b/plutus-tx/src/PlutusTx/Builtins.hs @@ -39,6 +39,7 @@ module PlutusTx.Builtins ( , lessThanInteger , lessThanEqualsInteger , equalsInteger + , expModInteger -- * Error , error -- * Data @@ -851,3 +852,18 @@ replicateByte :: Integer -> BuiltinByteString replicateByte = BI.replicateByte + + +-- | FIXME +-- +-- = See also +-- +-- * [Operation +-- description](https://github.com/cardano-foundation/CIPs/tree/master/CIP-0109) +{-# INLINEABLE expModInteger #-} +expModInteger :: + Integer -> + Integer -> + Integer -> + Integer +expModInteger = BI.expModInteger diff --git a/plutus-tx/src/PlutusTx/Builtins/Internal.hs b/plutus-tx/src/PlutusTx/Builtins/Internal.hs index 527a7f0a26e..e817ea6a552 100644 --- a/plutus-tx/src/PlutusTx/Builtins/Internal.hs +++ b/plutus-tx/src/PlutusTx/Builtins/Internal.hs @@ -38,6 +38,7 @@ import PlutusCore.Crypto.BLS12_381.G1 qualified as BLS12_381.G1 import PlutusCore.Crypto.BLS12_381.G2 qualified as BLS12_381.G2 import PlutusCore.Crypto.BLS12_381.Pairing qualified as BLS12_381.Pairing import PlutusCore.Crypto.Ed25519 qualified +import PlutusCore.Crypto.ExpMod as ExpMod import PlutusCore.Crypto.Hash qualified as Hash import PlutusCore.Crypto.Secp256k1 qualified import PlutusCore.Data qualified as PLC @@ -818,3 +819,18 @@ replicateByte n w8 = Haskell.error "byteStringReplicate errored." BuiltinSuccess bs -> BuiltinByteString bs BuiltinSuccessWithLogs logs bs -> traceAll logs $ BuiltinByteString bs + +{-# NOINLINE expModInteger #-} +expModInteger :: + BuiltinInteger -> + BuiltinInteger -> + BuiltinInteger -> + BuiltinInteger +expModInteger b e m = + -- (fromInteger @Rational) correctly throws an underflow exception upon negative integer + -- both for GHC8.10 and GHC>=9 + case ExpMod.expMod b e (fromInteger m) of + BuiltinFailure logs err -> traceAll (logs <> pure (display err)) $ + Haskell.error "expModInteger errored." + BuiltinSuccess bs -> toInteger bs + BuiltinSuccessWithLogs logs bs -> traceAll logs $ toInteger bs diff --git a/plutus-tx/src/PlutusTx/Prelude.hs b/plutus-tx/src/PlutusTx/Prelude.hs index 448dbfa2e62..1fcb9b96a21 100644 --- a/plutus-tx/src/PlutusTx/Prelude.hs +++ b/plutus-tx/src/PlutusTx/Prelude.hs @@ -49,6 +49,7 @@ module PlutusTx.Prelude ( remainder, even, odd, + expMod, -- * Maybe module Maybe, -- * Either @@ -214,6 +215,12 @@ divide = Builtins.divideInteger modulo :: Integer -> Integer -> Integer modulo = Builtins.modInteger + +{-# INLINABLE expMod #-} +-- | FIXME +expMod :: Integer -> Integer -> Integer -> Integer +expMod = Builtins.expModInteger + {-# INLINABLE quotient #-} -- | Integer division, rouding towards zero -- diff --git a/stubs/plutus-ghc-stub/src/Plugins.hs b/stubs/plutus-ghc-stub/src/Plugins.hs index 24f6c532031..abf47a9a91d 100644 --- a/stubs/plutus-ghc-stub/src/Plugins.hs +++ b/stubs/plutus-ghc-stub/src/Plugins.hs @@ -1,4 +1,3 @@ -{-# LANGUAGE CPP #-} {-# LANGUAGE Rank2Types #-} module Plugins ( FrontendPlugin(..), defaultFrontendPlugin, FrontendPluginAction @@ -110,9 +109,7 @@ instance Semigroup PluginRecompile where instance Monoid PluginRecompile where mempty = NoForceRecompile -#if __GLASGOW_HASKELL__ < 840 mappend = (Data.Semigroup.<>) -#endif type CorePlugin = [CommandLineOption] -> [CoreToDo] -> CoreM [CoreToDo] type TcPlugin = [CommandLineOption] -> Maybe TcRnTypes.TcPlugin