Skip to content
New issue

Have a question about this project? # for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “#”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? # to your account

Add new builtin hashing function ripemd_160 #6147

Closed
wants to merge 2 commits into from
Closed
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion cabal.project
Original file line number Diff line number Diff line change
@@ -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
@@ -82,3 +82,4 @@ allow-newer:
, inline-r:bytestring
, inline-r:containers
, inline-r:primitive

6 changes: 3 additions & 3 deletions flake.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

9 changes: 5 additions & 4 deletions nix/project.nix
Original file line number Diff line number Diff line change
@@ -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
2 changes: 1 addition & 1 deletion plutus-benchmark/plutus-benchmark.cabal
Original file line number Diff line number Diff line change
@@ -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
Original file line number Diff line number Diff line change
@@ -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)
]
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
({cpu: 2388508
| mem: 805})
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
(program 1.0.0 (con bool True))
Original file line number Diff line number Diff line change
@@ -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)
]
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
({cpu: 2636077
| mem: 805})
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
(program 1.0.0 (con bool True))
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

JFYI: I advocate for not using golden file machinery for programs that are expected to evaluate to a simple value like boolean True and instead verify expected result directly in the test code.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm happy to refactor this out if that is the way to go. Could you please point me to a place where I should put such a test case?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

JFYI: I advocate for not using golden file machinery for programs that are expected to evaluate to a simple value like boolean True and instead verify expected result directly in the test code.

I don't think that necessarily applies here. This is in the conformance tests and by design all of those are golden tests whose input and output are textual UPLC so that they can be run by other evaluators, in particular by the Agda evaluator in plutus-metatheory.

Original file line number Diff line number Diff line change
@@ -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
Original file line number Diff line number Diff line change
@@ -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
}
Original file line number Diff line number Diff line change
@@ -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 {..}

13 changes: 13 additions & 0 deletions plutus-core/cost-model/data/builtinCostModel.json
Original file line number Diff line number Diff line change
@@ -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,
5 changes: 4 additions & 1 deletion plutus-core/cost-model/data/models.R
Original file line number Diff line number Diff line change
@@ -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,
3 changes: 3 additions & 0 deletions plutus-core/cost-model/test/TestCostModels.hs
Original file line number Diff line number Diff line change
@@ -414,5 +414,8 @@ main =
-- Bitwise operations
, $(genTest 3 "integerToByteString")
, $(genTest 2 "byteStringToInteger") Everywhere

-- Ripemd_160
, $(genTest 1 "ripemd_160")
]

3 changes: 2 additions & 1 deletion plutus-core/plutus-core.cabal
Original file line number Diff line number Diff line change
@@ -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
6 changes: 6 additions & 0 deletions plutus-core/plutus-core/src/PlutusCore/Crypto/Hash.hs
Original file line number Diff line number Diff line change
@@ -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)
15 changes: 15 additions & 0 deletions plutus-core/plutus-core/src/PlutusCore/Default/Builtins.hs
Original file line number Diff line number Diff line change
@@ -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
Original file line number Diff line number Diff line change
@@ -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)
Original file line number Diff line number Diff line change
@@ -234,5 +234,7 @@ unitCostBuiltinCostModel = BuiltinCostModelBase
-- Bitwise operations
, paramIntegerToByteString = unitCostThreeArguments
, paramByteStringToInteger = unitCostTwoArguments
-- Ripemd_160
, paramRipemd_160 = unitCostOneArgument
}

Original file line number Diff line number Diff line change
@@ -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,
Original file line number Diff line number Diff line change
@@ -79,6 +79,7 @@ isCommutative = \case
Blake2b_224 -> False
Blake2b_256 -> False
Keccak_256 -> False
Ripemd_160 -> False
VerifyEd25519Signature -> False
VerifyEcdsaSecp256k1Signature -> False
VerifySchnorrSecp256k1Signature -> False
Original file line number Diff line number Diff line change
@@ -140,5 +140,6 @@ typedBuiltins
. insertBuiltin Blake2b_224
. insertBuiltin Blake2b_256
. insertBuiltin Keccak_256
. insertBuiltin Ripemd_160
. insertBuiltin EqualsByteString
$ DenotationContext mempty
2 changes: 1 addition & 1 deletion plutus-core/testlib/PlutusCore/Generators/NEAT/Term.hs
Original file line number Diff line number Diff line change
@@ -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))
Original file line number Diff line number Diff line change
@@ -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
3 changes: 2 additions & 1 deletion plutus-ledger-api/src/PlutusLedgerApi/Common/Versions.hs
Original file line number Diff line number Diff line change
@@ -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
])
]

Loading