From 0478059b23cc4dcda32699be91e2db357a88466a Mon Sep 17 00:00:00 2001 From: Tomasz Rybarczyk Date: Wed, 29 May 2024 12:07:43 +0200 Subject: [PATCH 1/2] Add ripemd-160 builtin with artificial cost model (copy of keccak_256) --- cabal.project | 10 +++++++++ nix/project.nix | 9 ++++---- plutus-benchmark/plutus-benchmark.cabal | 2 +- .../budgeting-bench/Benchmarks/Crypto.hs | 2 +- .../create-cost-model/BuiltinMemoryModels.hs | 1 + .../CreateBuiltinCostModel.hs | 3 +++ .../cost-model/data/builtinCostModel.json | 13 +++++++++++ plutus-core/cost-model/data/models.R | 5 ++++- plutus-core/cost-model/test/TestCostModels.hs | 3 +++ plutus-core/plutus-core.cabal | 3 ++- .../plutus-core/src/PlutusCore/Crypto/Hash.hs | 6 +++++ .../src/PlutusCore/Default/Builtins.hs | 15 +++++++++++++ .../Evaluation/Machine/BuiltinCostModel.hs | 2 ++ .../Evaluation/Machine/ExBudgetingDefaults.hs | 2 ++ .../defaultCostModelParams.json | 3 +++ .../RewriteRules/CommuteFnWithConst.hs | 1 + .../Generators/Hedgehog/Denotation.hs | 1 + .../PlutusCore/Generators/NEAT/Term.hs | 2 +- .../test/Evaluation/Builtins/Definition.hs | 22 ++++++++++++++----- .../src/PlutusLedgerApi/Common/Versions.hs | 3 ++- .../src/PlutusLedgerApi/V3/ParamName.hs | 3 +++ .../test/Spec/CostModelParams.hs | 4 ++-- .../src/Algorithmic/CEK.lagda.md | 1 + plutus-metatheory/src/Builtin.lagda.md | 7 ++++++ plutus-metatheory/src/Untyped/CEK.lagda.md | 4 ++++ .../src/PlutusTx/Compiler/Builtins.hs | 2 ++ plutus-tx/src/PlutusTx/Builtins.hs | 6 +++++ plutus-tx/src/PlutusTx/Builtins/Internal.hs | 4 ++++ plutus-tx/src/PlutusTx/Prelude.hs | 5 +++-- 29 files changed, 125 insertions(+), 19 deletions(-) diff --git a/cabal.project b/cabal.project index fbdc55dea12..1af7d4ff28b 100644 --- a/cabal.project +++ b/cabal.project @@ -82,3 +82,13 @@ allow-newer: , inline-r:bytestring , inline-r:containers , inline-r:primitive + +source-repository-package + type: git + location: https://github.com/paluh/cardano-base + tag: ea31e27ae4c9715232fa20e2e91f23e5bd967d65 + subdir: + base-deriving-via + cardano-crypto-class + cardano-crypto-praos + cardano-crypto-tests diff --git a/nix/project.nix b/nix/project.nix index 9945c6c116f..dff91c489b3 100644 --- a/nix/project.nix +++ b/nix/project.nix @@ -1,4 +1,4 @@ -# editorconfig-checker-disable-file +# editorconfig-checker-disable-file { repoRoot, inputs, pkgs, system, lib }: @@ -8,7 +8,7 @@ let { name = "plutus"; - # We need the mkDefault here since compiler-nix-name will be overridden + # We need the mkDefault here since compiler-nix-name will be overridden # in the flake variants. compiler-nix-name = lib.mkDefault "ghc96"; @@ -37,6 +37,7 @@ let sha256map = { "https://github.com/jaccokrijnen/plutus-cert"."e814b9171398cbdfecdc6823067156a7e9fc76a3" = "0srqvx0b819b5crrbsa9hz2fnr50ahqizvvm0wdmyq2bbpk2rka7"; + "https://github.com/paluh/cardano-base"."ea31e27ae4c9715232fa20e2e91f23e5bd967d65" = "sha256-R/uqcScLbkFhYL8x0FL7eQ2UIJY30o6ec312I/E7KdU="; }; # TODO: move this into the cabalib.project using the new conditional support? @@ -58,7 +59,7 @@ let modules = [ - # Cross Compiling + # Cross Compiling (lib.mkIf isCrossCompiling { packages = { # Things that need plutus-tx-plugin @@ -77,7 +78,7 @@ let reinstallableLibGhc = false; }) - # Common + # Common { packages = { # Packages we just don't want docs for diff --git a/plutus-benchmark/plutus-benchmark.cabal b/plutus-benchmark/plutus-benchmark.cabal index 35a906f7ddf..c0ae5d6448c 100644 --- a/plutus-benchmark/plutus-benchmark.cabal +++ b/plutus-benchmark/plutus-benchmark.cabal @@ -470,7 +470,7 @@ library marlowe-internal build-depends: , base , bytestring - , cardano-crypto-class >=2.0.0.1 && <2.3 + , cardano-crypto-class >=2.1.5 && <2.3 , directory , filepath , mtl diff --git a/plutus-core/cost-model/budgeting-bench/Benchmarks/Crypto.hs b/plutus-core/cost-model/budgeting-bench/Benchmarks/Crypto.hs index fab8b7ce884..7afe1b4f672 100644 --- a/plutus-core/cost-model/budgeting-bench/Benchmarks/Crypto.hs +++ b/plutus-core/cost-model/budgeting-bench/Benchmarks/Crypto.hs @@ -317,5 +317,5 @@ makeBenchmarks gen = [ benchVerifyEd25519Signature , benchVerifyEcdsaSecp256k1Signature , benchVerifySchnorrSecp256k1Signature ] - <> (benchByteStringOneArgOp <$> [Sha2_256, Sha3_256, Blake2b_224, Blake2b_256, Keccak_256]) + <> (benchByteStringOneArgOp <$> [Sha2_256, Sha3_256, Blake2b_224, Blake2b_256, Keccak_256, Ripemd_160]) <> blsBenchmarks gen diff --git a/plutus-core/cost-model/create-cost-model/BuiltinMemoryModels.hs b/plutus-core/cost-model/create-cost-model/BuiltinMemoryModels.hs index 74f5e3b48dd..f352046abba 100644 --- a/plutus-core/cost-model/create-cost-model/BuiltinMemoryModels.hs +++ b/plutus-core/cost-model/create-cost-model/BuiltinMemoryModels.hs @@ -150,4 +150,5 @@ builtinMemoryModels = BuiltinCostModelBase -- a special memory costing function to handle that. , paramIntegerToByteString = Id $ ModelThreeArgumentsLiteralInYOrLinearInZ $ OneVariableLinearFunction 0 1 , paramByteStringToInteger = Id $ ModelTwoArgumentsLinearInY $ OneVariableLinearFunction 0 1 + , paramRipemd_160 = Id $ hashMemModel Hash.ripemd_160 } diff --git a/plutus-core/cost-model/create-cost-model/CreateBuiltinCostModel.hs b/plutus-core/cost-model/create-cost-model/CreateBuiltinCostModel.hs index 776ef174ed6..8d6050d4afc 100644 --- a/plutus-core/cost-model/create-cost-model/CreateBuiltinCostModel.hs +++ b/plutus-core/cost-model/create-cost-model/CreateBuiltinCostModel.hs @@ -112,6 +112,7 @@ builtinCostModelNames = BuiltinCostModelBase , paramKeccak_256 = "keccak_256Model" , paramIntegerToByteString = "integerToByteStringModel" , paramByteStringToInteger = "byteStringToIntegerModel" + , paramRipemd_160 = "ripemd_160Model" } @@ -238,6 +239,8 @@ createBuiltinCostModel bmfile rfile = do -- Bitwise operations paramByteStringToInteger <- getParams readCF2 paramByteStringToInteger paramIntegerToByteString <- getParams readCF3 paramIntegerToByteString + -- And another hash function + paramRipemd_160 <- getParams readCF1 paramRipemd_160 pure $ BuiltinCostModelBase {..} diff --git a/plutus-core/cost-model/data/builtinCostModel.json b/plutus-core/cost-model/data/builtinCostModel.json index 567a97f3a5f..fd83943a464 100644 --- a/plutus-core/cost-model/data/builtinCostModel.json +++ b/plutus-core/cost-model/data/builtinCostModel.json @@ -527,6 +527,19 @@ "type": "constant_cost" } }, + "ripemd_160": { + "cpu": { + "arguments": { + "intercept": 1927926, + "slope": 82523 + }, + "type": "linear_in_x" + }, + "memory": { + "arguments": 4, + "type": "constant_cost" + } + }, "lengthOfByteString": { "cpu": { "arguments": 1000, diff --git a/plutus-core/cost-model/data/models.R b/plutus-core/cost-model/data/models.R index 069e3c5af3f..2a14b5a5b2c 100644 --- a/plutus-core/cost-model/data/models.R +++ b/plutus-core/cost-model/data/models.R @@ -131,7 +131,8 @@ arity <- function(name) { "Keccak_256" = 1, "Blake2b_224" = 1, "IntegerToByteString" = 3, - "ByteStringToInteger" = 2 + "ByteStringToInteger" = 2, + "Ripemd_160" = 1 ) } @@ -554,6 +555,7 @@ modelFun <- function(path) { blake2b_224Model <- linearInX ("Blake2b_224") blake2b_256Model <- linearInX ("Blake2b_256") keccak_256Model <- linearInX ("Keccak_256") + ripemd_160Model <- linearInX ("Ripemd_160") ###### Signature verification ##### @@ -764,6 +766,7 @@ modelFun <- function(path) { blake2b_224Model = blake2b_224Model, blake2b_256Model = blake2b_256Model, keccak_256Model = keccak_256Model, + ripemd_160Model = ripemd_160Model, verifyEd25519SignatureModel = verifyEd25519SignatureModel, verifyEcdsaSecp256k1SignatureModel = verifyEcdsaSecp256k1SignatureModel, verifySchnorrSecp256k1SignatureModel = verifySchnorrSecp256k1SignatureModel, diff --git a/plutus-core/cost-model/test/TestCostModels.hs b/plutus-core/cost-model/test/TestCostModels.hs index cfb75c798b1..e32b106ec2c 100644 --- a/plutus-core/cost-model/test/TestCostModels.hs +++ b/plutus-core/cost-model/test/TestCostModels.hs @@ -414,5 +414,8 @@ main = -- Bitwise operations , $(genTest 3 "integerToByteString") , $(genTest 2 "byteStringToInteger") Everywhere + + -- Ripemd_160 + , $(genTest 1 "ripemd_160") ] diff --git a/plutus-core/plutus-core.cabal b/plutus-core/plutus-core.cabal index a8d4bfff1c2..998bdb3c054 100644 --- a/plutus-core/plutus-core.cabal +++ b/plutus-core/plutus-core.cabal @@ -286,7 +286,7 @@ library , bytestring , bytestring-strict-builder , cardano-crypto - , cardano-crypto-class ^>=2.1.2 + , cardano-crypto-class ^>=2.1.5 , cassava , cborg , composition-prelude >=1.1.0.1 @@ -433,6 +433,7 @@ test-suite untyped-plutus-core-test build-depends: , base >=4.9 && <5 + , base16-bytestring , bytestring , cardano-crypto-class , dlist diff --git a/plutus-core/plutus-core/src/PlutusCore/Crypto/Hash.hs b/plutus-core/plutus-core/src/PlutusCore/Crypto/Hash.hs index c956927be49..9d311f60e58 100644 --- a/plutus-core/plutus-core/src/PlutusCore/Crypto/Hash.hs +++ b/plutus-core/plutus-core/src/PlutusCore/Crypto/Hash.hs @@ -6,11 +6,13 @@ module PlutusCore.Crypto.Hash , blake2b_224 , blake2b_256 , keccak_256 + , ripemd_160 ) where import Cardano.Crypto.Hash.Blake2b import Cardano.Crypto.Hash.Class import Cardano.Crypto.Hash.Keccak256 +import Cardano.Crypto.Hash.RIPEMD160 import Cardano.Crypto.Hash.SHA256 import Cardano.Crypto.Hash.SHA3_256 import Data.ByteString qualified as BS @@ -35,3 +37,7 @@ blake2b_256 = digest (Proxy @Blake2b_256) -- | Hash a `ByteString` using the Keccak-256 hash function. keccak_256 :: BS.ByteString -> BS.ByteString keccak_256 = digest (Proxy @Keccak256) + +-- | Hash a `ByteString` using the RIPEMD-160 hash function. +ripemd_160 :: BS.ByteString -> BS.ByteString +ripemd_160 = digest (Proxy @RIPEMD160) diff --git a/plutus-core/plutus-core/src/PlutusCore/Default/Builtins.hs b/plutus-core/plutus-core/src/PlutusCore/Default/Builtins.hs index 33c46234256..ec5ac358593 100644 --- a/plutus-core/plutus-core/src/PlutusCore/Default/Builtins.hs +++ b/plutus-core/plutus-core/src/PlutusCore/Default/Builtins.hs @@ -152,6 +152,8 @@ data DefaultFun -- Conversions | IntegerToByteString | ByteStringToInteger + -- Ripemd_160 + | Ripemd_160 deriving stock (Show, Eq, Ord, Enum, Bounded, Generic, Ix) deriving anyclass (NFData, Hashable, PrettyBy PrettyConfigPlc) @@ -1820,6 +1822,16 @@ instance uni ~ DefaultUni => ToBuiltinMeaning uni DefaultFun where in makeBuiltinMeaning byteStringToIntegerDenotation (runCostingFunTwoArguments . paramByteStringToInteger) + + toBuiltinMeaning _semvar Ripemd_160 = + let ripemd_160Denotation :: BS.ByteString -> BS.ByteString + ripemd_160Denotation = Hash.ripemd_160 + {-# INLINE ripemd_160Denotation #-} + in makeBuiltinMeaning + ripemd_160Denotation + (runCostingFunOneArgument . paramRipemd_160) + + -- See Note [Inlining meanings of builtins]. {-# INLINE toBuiltinMeaning #-} @@ -1947,6 +1959,8 @@ instance Flat DefaultFun where IntegerToByteString -> 73 ByteStringToInteger -> 74 + Ripemd_160 -> 75 + decode = go =<< decodeBuiltin where go 0 = pure AddInteger go 1 = pure SubtractInteger @@ -2023,6 +2037,7 @@ instance Flat DefaultFun where go 72 = pure Blake2b_224 go 73 = pure IntegerToByteString go 74 = pure ByteStringToInteger + go 75 = pure Ripemd_160 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 a5855efff28..07132486010 100644 --- a/plutus-core/plutus-core/src/PlutusCore/Evaluation/Machine/BuiltinCostModel.hs +++ b/plutus-core/plutus-core/src/PlutusCore/Evaluation/Machine/BuiltinCostModel.hs @@ -162,6 +162,8 @@ data BuiltinCostModelBase f = -- Bitwise operations , paramIntegerToByteString :: f ModelThreeArguments , paramByteStringToInteger :: f ModelTwoArguments + -- Ripemd_160 + , paramRipemd_160 :: f ModelOneArgument } 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 309095f60db..e777670e2f9 100644 --- a/plutus-core/plutus-core/src/PlutusCore/Evaluation/Machine/ExBudgetingDefaults.hs +++ b/plutus-core/plutus-core/src/PlutusCore/Evaluation/Machine/ExBudgetingDefaults.hs @@ -234,5 +234,7 @@ unitCostBuiltinCostModel = BuiltinCostModelBase -- Bitwise operations , paramIntegerToByteString = unitCostThreeArguments , paramByteStringToInteger = unitCostTwoArguments + -- Ripemd_160 + , paramRipemd_160 = unitCostOneArgument } diff --git a/plutus-core/plutus-core/test/CostModelInterface/defaultCostModelParams.json b/plutus-core/plutus-core/test/CostModelInterface/defaultCostModelParams.json index 075a87e260f..8f3145ba7b3 100644 --- a/plutus-core/plutus-core/test/CostModelInterface/defaultCostModelParams.json +++ b/plutus-core/plutus-core/test/CostModelInterface/defaultCostModelParams.json @@ -130,6 +130,9 @@ "keccak_256-cpu-arguments-intercept": 1927926, "keccak_256-cpu-arguments-slope": 82523, "keccak_256-memory-arguments": 4, + "ripemd_160-cpu-arguments-intercept": 1927926, + "ripemd_160-cpu-arguments-slope": 82523, + "ripemd_160-memory-arguments": 4, "lengthOfByteString-cpu-arguments": 1000, "lengthOfByteString-memory-arguments": 10, "lessThanByteString-cpu-arguments-intercept": 197145, 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 1f52b55900a..0e383a39b87 100644 --- a/plutus-core/plutus-ir/src/PlutusIR/Transform/RewriteRules/CommuteFnWithConst.hs +++ b/plutus-core/plutus-ir/src/PlutusIR/Transform/RewriteRules/CommuteFnWithConst.hs @@ -79,6 +79,7 @@ isCommutative = \case Blake2b_224 -> False Blake2b_256 -> False Keccak_256 -> False + Ripemd_160 -> False VerifyEd25519Signature -> False VerifyEcdsaSecp256k1Signature -> False VerifySchnorrSecp256k1Signature -> False diff --git a/plutus-core/testlib/PlutusCore/Generators/Hedgehog/Denotation.hs b/plutus-core/testlib/PlutusCore/Generators/Hedgehog/Denotation.hs index dfebec2c7f9..3dbf0e7fd20 100644 --- a/plutus-core/testlib/PlutusCore/Generators/Hedgehog/Denotation.hs +++ b/plutus-core/testlib/PlutusCore/Generators/Hedgehog/Denotation.hs @@ -140,5 +140,6 @@ typedBuiltins . insertBuiltin Blake2b_224 . insertBuiltin Blake2b_256 . insertBuiltin Keccak_256 + . insertBuiltin Ripemd_160 . insertBuiltin EqualsByteString $ DenotationContext mempty diff --git a/plutus-core/testlib/PlutusCore/Generators/NEAT/Term.hs b/plutus-core/testlib/PlutusCore/Generators/NEAT/Term.hs index 67323f53617..8b748b7d810 100644 --- a/plutus-core/testlib/PlutusCore/Generators/NEAT/Term.hs +++ b/plutus-core/testlib/PlutusCore/Generators/NEAT/Term.hs @@ -399,7 +399,7 @@ defaultFunTypes = Map.fromList [(TyFunG (TyBuiltinG TyIntegerG) (TyFunG (TyBuilt ,(TyFunG (TyBuiltinG TyByteStringG) (TyFunG (TyBuiltinG TyIntegerG) (TyBuiltinG TyIntegerG)) ,[IndexByteString]) ,(TyFunG (TyBuiltinG TyByteStringG) (TyBuiltinG TyByteStringG) - ,[Sha2_256,Sha3_256,Blake2b_224,Blake2b_256,Keccak_256]) + ,[Sha2_256,Sha3_256,Blake2b_224,Blake2b_256,Keccak_256,Ripemd_160]) ,(TyFunG (TyBuiltinG TyByteStringG) (TyFunG (TyBuiltinG TyByteStringG) (TyFunG (TyBuiltinG TyByteStringG) (TyBuiltinG TyBoolG))) ,[VerifyEd25519Signature]) ,(TyFunG (TyBuiltinG TyByteStringG) (TyFunG (TyBuiltinG TyByteStringG) (TyBuiltinG TyBoolG)) 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 25ccd044ea2..23a6ff64de3 100644 --- a/plutus-core/untyped-plutus-core/test/Evaluation/Builtins/Definition.hs +++ b/plutus-core/untyped-plutus-core/test/Evaluation/Builtins/Definition.hs @@ -49,10 +49,13 @@ import Evaluation.Builtins.SignatureVerification (ecdsaSecp256k1Prop, ed25519_Va import Control.Exception import Data.ByteString (ByteString, pack) +import Data.ByteString.Base16 qualified as Base16 import Data.DList qualified as DList import Data.Proxy import Data.String (IsString (fromString)) import Data.Text (Text) +import Data.Text qualified as Text +import Data.Text.Encoding qualified as Text import Hedgehog hiding (Opaque, Size, Var) import Hedgehog.Gen qualified as Gen import Hedgehog.Range qualified as Range @@ -670,6 +673,14 @@ test_Crypto = testCase "Crypto" $ do -- hex output: 47173285a8d7341e5e972fc677286384f802f8ef42a5ec5f03bbfa254cb01fad evals @ByteString "G\ETB2\133\168\215\&4\RS^\151/\198w(c\132\248\STX\248\239B\165\236_\ETX\187\250%L\176\US\173" Keccak_256 [cons @ByteString "hello world"] + -- independently verified by the calculator at https://emn178.github.io/online-tools/ripemd_160.html + let + hashHex = "98c615784ccb5fe5936fbc0cbe9dfdb408d92f0f" + ripemd_160Hash = case Base16.decode $ Text.encodeUtf8 hashHex of + Right res -> res + Left _ -> error $ "Unexpected error during hex decoding: " <> Text.unpack hashHex + evals @ByteString ripemd_160Hash + Ripemd_160 [cons @ByteString "hello world"] -- Tests for blake2b_224: output obtained using the b2sum program from https://github.com/BLAKE2/BLAKE2 evals (pack [ 0x83, 0x6c, 0xc6, 0x89, 0x31, 0xc2, 0xe4, 0xe3, 0xe8, 0x38, 0x60, 0x2e, 0xca, 0x19 , 0x02, 0x59, 0x1d, 0x21, 0x68, 0x37, 0xba, 0xfd, 0xdf, 0xe6, 0xf0, 0xc8, 0xcb, 0x07 ]) @@ -749,11 +760,12 @@ test_HashSize hashFun expectedNumBits = test_HashSizes :: TestTree test_HashSizes = testGroup "Hash sizes" - [ test_HashSize Sha2_256 256 - , test_HashSize Sha3_256 256 - , test_HashSize Blake2b_256 256 - , test_HashSize Keccak_256 256 - , test_HashSize Blake2b_224 224 + [ test_HashSize Sha2_256 256 + , test_HashSize Sha3_256 256 + , test_HashSize Blake2b_256 256 + , test_HashSize Keccak_256 256 + , test_HashSize Blake2b_224 224 + , test_HashSize Ripemd_160 160 ] -- Test all remaining builtins of the default universe diff --git a/plutus-ledger-api/src/PlutusLedgerApi/Common/Versions.hs b/plutus-ledger-api/src/PlutusLedgerApi/Common/Versions.hs index 24a553dd651..0e7eecf94f8 100644 --- a/plutus-ledger-api/src/PlutusLedgerApi/Common/Versions.hs +++ b/plutus-ledger-api/src/PlutusLedgerApi/Common/Versions.hs @@ -117,7 +117,8 @@ builtinsIntroducedIn = Map.fromList [ Bls12_381_G2_equal, Bls12_381_G2_hashToGroup, Bls12_381_G2_compress, Bls12_381_G2_uncompress, Bls12_381_millerLoop, Bls12_381_mulMlResult, Bls12_381_finalVerify, - Keccak_256, Blake2b_224, IntegerToByteString, ByteStringToInteger + Keccak_256, Blake2b_224, IntegerToByteString, ByteStringToInteger, + Ripemd_160 ]) ] diff --git a/plutus-ledger-api/src/PlutusLedgerApi/V3/ParamName.hs b/plutus-ledger-api/src/PlutusLedgerApi/V3/ParamName.hs index 9deda39345e..208f3e2b593 100644 --- a/plutus-ledger-api/src/PlutusLedgerApi/V3/ParamName.hs +++ b/plutus-ledger-api/src/PlutusLedgerApi/V3/ParamName.hs @@ -248,5 +248,8 @@ data ParamName = | ByteStringToInteger'cpu'arguments'c2 | ByteStringToInteger'memory'arguments'intercept | ByteStringToInteger'memory'arguments'slope + | Ripemd_160'cpu'arguments'intercept + | Ripemd_160'cpu'arguments'slope + | Ripemd_160'memory'arguments deriving stock (Eq, Ord, Enum, Ix, Bounded, Generic) deriving IsParamName via (GenericParamName ParamName) diff --git a/plutus-ledger-api/test/Spec/CostModelParams.hs b/plutus-ledger-api/test/Spec/CostModelParams.hs index 3edb933edc4..5b29cef5915 100644 --- a/plutus-ledger-api/test/Spec/CostModelParams.hs +++ b/plutus-ledger-api/test/Spec/CostModelParams.hs @@ -32,8 +32,8 @@ tests = 166 @=? length V1.costModelParamsForTesting 185 @=? length v2_ParamNames 185 @=? length V2.costModelParamsForTesting - 233 @=? length v3_ParamNames - 233 @=? length V3.costModelParamsForTesting + 236 @=? length v3_ParamNames + 236 @=? length V3.costModelParamsForTesting , testCase "tripping paramname" $ do for_ v1_ParamNames $ \ p -> assertBool "tripping v1 cm params failed" $ Just p == readParamName (showParamName p) diff --git a/plutus-metatheory/src/Algorithmic/CEK.lagda.md b/plutus-metatheory/src/Algorithmic/CEK.lagda.md index 321dae4a290..18930234d91 100644 --- a/plutus-metatheory/src/Algorithmic/CEK.lagda.md +++ b/plutus-metatheory/src/Algorithmic/CEK.lagda.md @@ -222,6 +222,7 @@ BUILTIN sha3-256 (base $ V-con b) = inj₂ (V-con (SHA3-256 b)) BUILTIN blake2b-224 (base $ V-con b) = inj₂ (V-con (BLAKE2B-224 b)) BUILTIN blake2b-256 (base $ V-con b) = inj₂ (V-con (BLAKE2B-256 b)) BUILTIN keccak-256 (base $ V-con b) = inj₂ (V-con (KECCAK-256 b)) +BUILTIN ripemd-160 (base $ V-con b) = inj₂ (V-con (RIPEMD-160 b)) BUILTIN verifyEd25519Signature (base $ V-con k $ V-con d $ V-con c) with (verifyEd25519Sig k d c) ... | just b = inj₂ (V-con b) ... | nothing = inj₁ (con (ne (^ (atomic aBool)))) diff --git a/plutus-metatheory/src/Builtin.lagda.md b/plutus-metatheory/src/Builtin.lagda.md index f216d83f945..fb65afa8ad7 100644 --- a/plutus-metatheory/src/Builtin.lagda.md +++ b/plutus-metatheory/src/Builtin.lagda.md @@ -132,6 +132,8 @@ data Builtin : Set where -- Bitwise operations byteStringToInteger : Builtin integerToByteString : Builtin + -- Ripemd-160 + ripemd-160 : Builtin ``` ## Signatures @@ -248,6 +250,7 @@ sig n⋆ n♯ (t₃ ∷ t₂ ∷ t₁) tᵣ signature blake2b-224 = ∙ [ bytestring ↑ ]⟶ bytestring ↑ signature blake2b-256 = ∙ [ bytestring ↑ ]⟶ bytestring ↑ signature keccak-256 = ∙ [ bytestring ↑ ]⟶ bytestring ↑ + signature ripemd-160 = ∙ [ bytestring ↑ ]⟶ bytestring ↑ signature verifyEd25519Signature = ∙ [ bytestring ↑ , bytestring ↑ , bytestring ↑ ]⟶ bool ↑ signature verifyEcdsaSecp256k1Signature = ∙ [ bytestring ↑ , bytestring ↑ , bytestring ↑ ]⟶ bool ↑ signature verifySchnorrSecp256k1Signature = ∙ [ bytestring ↑ , bytestring ↑ , bytestring ↑ ]⟶ bool ↑ @@ -390,6 +393,7 @@ Each Agda built-in name must be mapped to a Haskell name. | Blake2b_224 | ByteStringToInteger | IntegerToByteString + | Ripemd_160 ) #-} ``` @@ -445,6 +449,7 @@ postulate BLAKE2B-224 : ByteString → ByteString BStoI : Bool -> ByteString -> Int ItoBS : Bool -> Int -> Int -> Maybe ByteString + RIPEMD-160 : ByteString → ByteString ``` ### What builtin operations should be compiled to if we compile to Haskell @@ -539,6 +544,8 @@ postulate {-# COMPILE GHC BStoI = Convert.byteStringToIntegerWrapper #-} {-# COMPILE GHC ItoBS = \e w n -> builtinResultToMaybe $ Convert.integerToByteStringWrapper e w n #-} +{-# COMPILE GHC RIPEMD-160 = Hash.ripemd_160 #-} + -- 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 f3915779ca4..92ab21b240f 100644 --- a/plutus-metatheory/src/Untyped/CEK.lagda.md +++ b/plutus-metatheory/src/Untyped/CEK.lagda.md @@ -506,6 +506,10 @@ BUILTIN integerToByteString = λ } ; _ -> inj₁ userError } +BUILTIN ripemd-160 = λ + { (app base (V-con bytestring b)) -> inj₂ (V-con bytestring (RIPEMD-160 b)) + ; _ -> 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/src/PlutusTx/Compiler/Builtins.hs b/plutus-tx-plugin/src/PlutusTx/Compiler/Builtins.hs index e75dde029ec..7b090cdbff1 100644 --- a/plutus-tx-plugin/src/PlutusTx/Compiler/Builtins.hs +++ b/plutus-tx-plugin/src/PlutusTx/Compiler/Builtins.hs @@ -172,6 +172,7 @@ builtinNames = [ , 'Builtins.blake2b_224 , 'Builtins.blake2b_256 , 'Builtins.keccak_256 + , 'Builtins.ripemd_160 , 'Builtins.equalsByteString , 'Builtins.lessThanByteString , 'Builtins.lessThanEqualsByteString @@ -349,6 +350,7 @@ defineBuiltinTerms = do PLC.Blake2b_224 -> defineBuiltinInl 'Builtins.blake2b_224 PLC.Blake2b_256 -> defineBuiltinInl 'Builtins.blake2b_256 PLC.Keccak_256 -> defineBuiltinInl 'Builtins.keccak_256 + PLC.Ripemd_160 -> defineBuiltinInl 'Builtins.ripemd_160 PLC.EqualsByteString -> defineBuiltinInl 'Builtins.equalsByteString PLC.LessThanByteString -> defineBuiltinInl 'Builtins.lessThanByteString PLC.LessThanEqualsByteString -> defineBuiltinInl 'Builtins.lessThanEqualsByteString diff --git a/plutus-tx/src/PlutusTx/Builtins.hs b/plutus-tx/src/PlutusTx/Builtins.hs index 5e9550d9bb6..83db1a1bd55 100644 --- a/plutus-tx/src/PlutusTx/Builtins.hs +++ b/plutus-tx/src/PlutusTx/Builtins.hs @@ -20,6 +20,7 @@ module PlutusTx.Builtins ( , blake2b_224 , blake2b_256 , keccak_256 + , ripemd_160 , verifyEd25519Signature , verifyEcdsaSecp256k1Signature , verifySchnorrSecp256k1Signature @@ -180,6 +181,11 @@ blake2b_256 = BI.blake2b_256 keccak_256 :: BuiltinByteString -> BuiltinByteString keccak_256 = BI.keccak_256 +{-# INLINABLE ripemd_160 #-} +-- | The RIPEMD-160 hash of a 'ByteString' +ripemd_160 :: BuiltinByteString -> BuiltinByteString +ripemd_160 = BI.ripemd_160 + {-# INLINABLE verifyEd25519Signature #-} -- | Ed25519 signature verification. Verify that the signature is a signature of -- the message by the public key. This will fail if key or the signature are not diff --git a/plutus-tx/src/PlutusTx/Builtins/Internal.hs b/plutus-tx/src/PlutusTx/Builtins/Internal.hs index 843b63ccc4c..3e7b26b8cf3 100644 --- a/plutus-tx/src/PlutusTx/Builtins/Internal.hs +++ b/plutus-tx/src/PlutusTx/Builtins/Internal.hs @@ -254,6 +254,10 @@ blake2b_256 (BuiltinByteString b) = BuiltinByteString $ Hash.blake2b_256 b keccak_256 :: BuiltinByteString -> BuiltinByteString keccak_256 (BuiltinByteString b) = BuiltinByteString $ Hash.keccak_256 b +{-# NOINLINE ripemd_160 #-} +ripemd_160 :: BuiltinByteString -> BuiltinByteString +ripemd_160 (BuiltinByteString b) = BuiltinByteString $ Hash.ripemd_160 b + {-# NOINLINE verifyEd25519Signature #-} verifyEd25519Signature :: BuiltinByteString -> BuiltinByteString -> BuiltinByteString -> BuiltinBool verifyEd25519Signature (BuiltinByteString vk) (BuiltinByteString msg) (BuiltinByteString sig) = diff --git a/plutus-tx/src/PlutusTx/Prelude.hs b/plutus-tx/src/PlutusTx/Prelude.hs index c31ac38ce51..10d7a9c3311 100644 --- a/plutus-tx/src/PlutusTx/Prelude.hs +++ b/plutus-tx/src/PlutusTx/Prelude.hs @@ -70,6 +70,7 @@ module PlutusTx.Prelude ( blake2b_224, blake2b_256, keccak_256, + ripemd_160, verifyEd25519Signature, verifyEcdsaSecp256k1Signature, verifySchnorrSecp256k1Signature, @@ -135,8 +136,8 @@ import PlutusTx.Builtins (BuiltinBLS12_381_G1_Element, BuiltinBLS12_381_G2_Eleme emptyByteString, emptyString, encodeUtf8, equalsByteString, equalsString, error, fromBuiltin, fromOpaque, greaterThanByteString, indexByteString, integerToByteString, keccak_256, lengthOfByteString, lessThanByteString, - sha2_256, sha3_256, sliceByteString, toBuiltin, toOpaque, trace, - verifyEcdsaSecp256k1Signature, verifyEd25519Signature, + ripemd_160, sha2_256, sha3_256, sliceByteString, toBuiltin, toOpaque, + trace, verifyEcdsaSecp256k1Signature, verifyEd25519Signature, verifySchnorrSecp256k1Signature) import PlutusTx.Builtins qualified as Builtins From d7470ca8cc4e664c7e21ec79de1c0a961ad1c6b7 Mon Sep 17 00:00:00 2001 From: Tomasz Rybarczyk Date: Tue, 4 Jun 2024 10:14:10 +0200 Subject: [PATCH 2/2] Add conformance tests --- cabal.project | 11 +---------- flake.lock | 6 +++--- .../ripemd_160-empty/ripemd_160-empty.uplc | 14 ++++++++++++++ .../ripemd_160-empty.uplc.budget.expected | 2 ++ .../ripemd_160-empty.uplc.expected | 1 + .../ripemd_160-length-200.uplc | 14 ++++++++++++++ .../ripemd_160-length-200.uplc.budget.expected | 2 ++ .../ripemd_160-length-200.uplc.expected | 1 + 8 files changed, 38 insertions(+), 13 deletions(-) create mode 100644 plutus-conformance/test-cases/uplc/evaluation/builtin/semantics/ripemd_160/ripemd_160-empty/ripemd_160-empty.uplc create mode 100644 plutus-conformance/test-cases/uplc/evaluation/builtin/semantics/ripemd_160/ripemd_160-empty/ripemd_160-empty.uplc.budget.expected create mode 100644 plutus-conformance/test-cases/uplc/evaluation/builtin/semantics/ripemd_160/ripemd_160-empty/ripemd_160-empty.uplc.expected create mode 100644 plutus-conformance/test-cases/uplc/evaluation/builtin/semantics/ripemd_160/ripemd_160-length-200/ripemd_160-length-200.uplc create mode 100644 plutus-conformance/test-cases/uplc/evaluation/builtin/semantics/ripemd_160/ripemd_160-length-200/ripemd_160-length-200.uplc.budget.expected create mode 100644 plutus-conformance/test-cases/uplc/evaluation/builtin/semantics/ripemd_160/ripemd_160-length-200/ripemd_160-length-200.uplc.expected diff --git a/cabal.project b/cabal.project index 1af7d4ff28b..987c942f6a1 100644 --- a/cabal.project +++ b/cabal.project @@ -16,7 +16,7 @@ index-state: -- Bump both the following dates if you need newer packages from Hackage , hackage.haskell.org 2024-01-08T22:38:30Z -- Bump this if you need newer packages from CHaP - , cardano-haskell-packages 2024-01-16T11:00:00Z + , cardano-haskell-packages 2024-06-03T14:31:53Z packages: doc/read-the-docs-site plutus-benchmark @@ -83,12 +83,3 @@ allow-newer: , inline-r:containers , inline-r:primitive -source-repository-package - type: git - location: https://github.com/paluh/cardano-base - tag: ea31e27ae4c9715232fa20e2e91f23e5bd967d65 - subdir: - base-deriving-via - cardano-crypto-class - cardano-crypto-praos - cardano-crypto-tests diff --git a/flake.lock b/flake.lock index 43f8ceb9b73..6b7c7393200 100644 --- a/flake.lock +++ b/flake.lock @@ -3,11 +3,11 @@ "CHaP": { "flake": false, "locked": { - "lastModified": 1708970955, - "narHash": "sha256-k6Y9WjDej7wCkUowVi/tdsWP6EWUMZTSRU9r+4lMJmU=", + "lastModified": 1717443429, + "narHash": "sha256-5+LkyhERvcVanS91rAsri0W5oGCJDW7VVAY1Vo9GWVQ=", "owner": "IntersectMBO", "repo": "cardano-haskell-packages", - "rev": "f09964311e8894a5f09e258f308a9c3d4221f029", + "rev": "212e176e7c73853ebdfce11d62f78c4fcdd2dff2", "type": "github" }, "original": { diff --git a/plutus-conformance/test-cases/uplc/evaluation/builtin/semantics/ripemd_160/ripemd_160-empty/ripemd_160-empty.uplc b/plutus-conformance/test-cases/uplc/evaluation/builtin/semantics/ripemd_160/ripemd_160-empty/ripemd_160-empty.uplc new file mode 100644 index 00000000000..35088a1c4d8 --- /dev/null +++ b/plutus-conformance/test-cases/uplc/evaluation/builtin/semantics/ripemd_160/ripemd_160-empty/ripemd_160-empty.uplc @@ -0,0 +1,14 @@ +-- Test vector (0-bit input) for Ripemd_160. +-- Output obtained using the online tool https://emn178.github.io/online-tools/ripemd_160.html +(program 1.0.0 + [ + [ + (builtin equalsByteString) + [ + (builtin ripemd_160) + (con bytestring #) + ] + ] + (con bytestring #9c1185a5c5e9fc54612808977ee8f548b2258d31) + ] +) diff --git a/plutus-conformance/test-cases/uplc/evaluation/builtin/semantics/ripemd_160/ripemd_160-empty/ripemd_160-empty.uplc.budget.expected b/plutus-conformance/test-cases/uplc/evaluation/builtin/semantics/ripemd_160/ripemd_160-empty/ripemd_160-empty.uplc.budget.expected new file mode 100644 index 00000000000..a22f578fc22 --- /dev/null +++ b/plutus-conformance/test-cases/uplc/evaluation/builtin/semantics/ripemd_160/ripemd_160-empty/ripemd_160-empty.uplc.budget.expected @@ -0,0 +1,2 @@ +({cpu: 2388508 +| mem: 805}) \ No newline at end of file diff --git a/plutus-conformance/test-cases/uplc/evaluation/builtin/semantics/ripemd_160/ripemd_160-empty/ripemd_160-empty.uplc.expected b/plutus-conformance/test-cases/uplc/evaluation/builtin/semantics/ripemd_160/ripemd_160-empty/ripemd_160-empty.uplc.expected new file mode 100644 index 00000000000..3760fc7a698 --- /dev/null +++ b/plutus-conformance/test-cases/uplc/evaluation/builtin/semantics/ripemd_160/ripemd_160-empty/ripemd_160-empty.uplc.expected @@ -0,0 +1 @@ +(program 1.0.0 (con bool True)) \ No newline at end of file diff --git a/plutus-conformance/test-cases/uplc/evaluation/builtin/semantics/ripemd_160/ripemd_160-length-200/ripemd_160-length-200.uplc b/plutus-conformance/test-cases/uplc/evaluation/builtin/semantics/ripemd_160/ripemd_160-length-200/ripemd_160-length-200.uplc new file mode 100644 index 00000000000..61017a9a98c --- /dev/null +++ b/plutus-conformance/test-cases/uplc/evaluation/builtin/semantics/ripemd_160/ripemd_160-length-200/ripemd_160-length-200.uplc @@ -0,0 +1,14 @@ +-- Test vector (0-bit input) for Ripemd_160. +-- Output obtained using the online tool https://emn178.github.io/online-tools/ripemd_160.html +(program 1.0.0 + [ + [ + (builtin equalsByteString) + [ + (builtin ripemd_160) + (con bytestring #2e7ea84da4bc4d7cfb463e3f2c8647057afff3fbececa1d200) + ] + ] + (con bytestring #f18921115370b049e99dfdd49fc92b371dd7c7e9) + ] +) diff --git a/plutus-conformance/test-cases/uplc/evaluation/builtin/semantics/ripemd_160/ripemd_160-length-200/ripemd_160-length-200.uplc.budget.expected b/plutus-conformance/test-cases/uplc/evaluation/builtin/semantics/ripemd_160/ripemd_160-length-200/ripemd_160-length-200.uplc.budget.expected new file mode 100644 index 00000000000..77f6686bf05 --- /dev/null +++ b/plutus-conformance/test-cases/uplc/evaluation/builtin/semantics/ripemd_160/ripemd_160-length-200/ripemd_160-length-200.uplc.budget.expected @@ -0,0 +1,2 @@ +({cpu: 2636077 +| mem: 805}) \ No newline at end of file diff --git a/plutus-conformance/test-cases/uplc/evaluation/builtin/semantics/ripemd_160/ripemd_160-length-200/ripemd_160-length-200.uplc.expected b/plutus-conformance/test-cases/uplc/evaluation/builtin/semantics/ripemd_160/ripemd_160-length-200/ripemd_160-length-200.uplc.expected new file mode 100644 index 00000000000..3760fc7a698 --- /dev/null +++ b/plutus-conformance/test-cases/uplc/evaluation/builtin/semantics/ripemd_160/ripemd_160-length-200/ripemd_160-length-200.uplc.expected @@ -0,0 +1 @@ +(program 1.0.0 (con bool True)) \ No newline at end of file