diff --git a/cabal.project b/cabal.project index 7e637e1f1ca..e30749208da 100644 --- a/cabal.project +++ b/cabal.project @@ -71,6 +71,16 @@ source-repository-package location: https://github.com/jaccokrijnen/plutus-cert tag: e814b9171398cbdfecdc6823067156a7e9fc76a3 +-- Add srp to a custom fork of cardano-base that adds BLS12_381 multi scalar multiplication +source-repository-package + type: git + location: https://github.com/perturbing/cardano-base + tag: 03c0c4e7438af3c720da9c45a78483cc22104e47 + --sha256: sha256-29wheArgCVCFBMi+Ot2iAcr9JD6YQN6K9GtGgzoaels= + subdir: + cardano-crypto-class + cardano-crypto-praos + allow-newer: -- https://github.com/tweag/HaskellR/pull/420 , inline-r:singletons-th diff --git a/plutus-core/changelog.d/20250515_113742_thomas.vellekoop_blsmsm.md b/plutus-core/changelog.d/20250515_113742_thomas.vellekoop_blsmsm.md new file mode 100644 index 00000000000..d29228e385f --- /dev/null +++ b/plutus-core/changelog.d/20250515_113742_thomas.vellekoop_blsmsm.md @@ -0,0 +1,3 @@ +### Added + +- in #7074 added the bls12_381_G1_multiScalarMul and bls12_381_G2_multiScalarMul builtins as per CIP 133 diff --git a/plutus-core/plutus-core/src/PlutusCore/Crypto/BLS12_381/G1.hs b/plutus-core/plutus-core/src/PlutusCore/Crypto/BLS12_381/G1.hs index 9e907bc0bd2..fdcc83bb301 100644 --- a/plutus-core/plutus-core/src/PlutusCore/Crypto/BLS12_381/G1.hs +++ b/plutus-core/plutus-core/src/PlutusCore/Crypto/BLS12_381/G1.hs @@ -16,6 +16,7 @@ module PlutusCore.Crypto.BLS12_381.G1 , compressed_generator , memSizeBytes , compressedSizeBytes + , multiScalarMul ) where import Cardano.Crypto.EllipticCurve.BLS12_381 qualified as BlstBindings @@ -170,3 +171,7 @@ memSizeBytes = BlstBindings.Internal.sizePoint (Proxy @BlstBindings.Curve1) -- | Compressed size of a G1 point (48 bytes) compressedSizeBytes :: Int compressedSizeBytes = BlstBindings.Internal.compressedSizePoint (Proxy @BlstBindings.Curve1) + +-- | Multi-scalar multiplication of G1 points. +multiScalarMul :: [Integer] -> [Element] -> Element +multiScalarMul = coerce (BlstBindings.blsMSM @BlstBindings.Curve1 10) diff --git a/plutus-core/plutus-core/src/PlutusCore/Crypto/BLS12_381/G2.hs b/plutus-core/plutus-core/src/PlutusCore/Crypto/BLS12_381/G2.hs index 93804907bd4..f2e240fced1 100644 --- a/plutus-core/plutus-core/src/PlutusCore/Crypto/BLS12_381/G2.hs +++ b/plutus-core/plutus-core/src/PlutusCore/Crypto/BLS12_381/G2.hs @@ -16,6 +16,7 @@ module PlutusCore.Crypto.BLS12_381.G2 , compressed_generator , memSizeBytes , compressedSizeBytes + , multiScalarMul ) where import Cardano.Crypto.EllipticCurve.BLS12_381 qualified as BlstBindings @@ -127,3 +128,7 @@ memSizeBytes = BlstBindings.Internal.sizePoint (Proxy @BlstBindings.Curve2) -- | Compressed size of a G2 point (96 bytes) compressedSizeBytes :: Int compressedSizeBytes = BlstBindings.Internal.compressedSizePoint (Proxy @BlstBindings.Curve2) + +-- | Multi-scalar multiplication of G2 points. +multiScalarMul :: [Integer] -> [Element] -> Element +multiScalarMul = coerce (BlstBindings.blsMSM @BlstBindings.Curve2 10) diff --git a/plutus-core/plutus-core/src/PlutusCore/Default/Builtins.hs b/plutus-core/plutus-core/src/PlutusCore/Default/Builtins.hs index 33ecb4dd03a..c3044022896 100644 --- a/plutus-core/plutus-core/src/PlutusCore/Default/Builtins.hs +++ b/plutus-core/plutus-core/src/PlutusCore/Default/Builtins.hs @@ -185,6 +185,9 @@ data DefaultFun | LengthOfArray | ListToArray | IndexArray + -- BLS12_381 multiscalar multiplication + | Bls12_381_G1_multiScalarMul + | Bls12_381_G2_multiScalarMul deriving stock (Show, Eq, Ord, Enum, Bounded, Generic, Ix) deriving anyclass (NFData, Hashable, PrettyBy PrettyConfigPlc) @@ -2139,6 +2142,24 @@ instance uni ~ DefaultUni => ToBuiltinMeaning uni DefaultFun where {-# INLINE indexArrayDenotation #-} in makeBuiltinMeaning indexArrayDenotation (runCostingFunTwoArguments . paramIndexArray) + toBuiltinMeaning _semvar Bls12_381_G1_multiScalarMul = + let bls12_381_G1_multiScalarMulDenotation + :: [Integer] -> [BLS12_381.G1.Element] -> BLS12_381.G1.Element + bls12_381_G1_multiScalarMulDenotation = BLS12_381.G1.multiScalarMul + {-# INLINE bls12_381_G1_multiScalarMulDenotation #-} + in makeBuiltinMeaning + bls12_381_G1_multiScalarMulDenotation + (runCostingFunTwoArguments . unimplementedCostingFun) + + toBuiltinMeaning _semvar Bls12_381_G2_multiScalarMul = + let bls12_381_G2_multiScalarMulDenotation + :: [Integer] -> [BLS12_381.G2.Element] -> BLS12_381.G2.Element + bls12_381_G2_multiScalarMulDenotation = BLS12_381.G2.multiScalarMul + {-# INLINE bls12_381_G2_multiScalarMulDenotation #-} + in makeBuiltinMeaning + bls12_381_G2_multiScalarMulDenotation + (runCostingFunTwoArguments . unimplementedCostingFun) + -- See Note [Inlining meanings of builtins]. {-# INLINE toBuiltinMeaning #-} @@ -2290,6 +2311,9 @@ instance Flat DefaultFun where ListToArray -> 92 IndexArray -> 93 + Bls12_381_G1_multiScalarMul -> 94 + Bls12_381_G2_multiScalarMul -> 95 + decode = go =<< decodeBuiltin where go 0 = pure AddInteger go 1 = pure SubtractInteger @@ -2385,6 +2409,8 @@ instance Flat DefaultFun where go 91 = pure LengthOfArray go 92 = pure ListToArray go 93 = pure IndexArray + go 94 = pure Bls12_381_G1_multiScalarMul + go 95 = pure Bls12_381_G2_multiScalarMul go t = fail $ "Failed to decode builtin tag, got: " ++ show t size _ n = n + builtinTagWidth diff --git a/plutus-core/plutus-core/test/TypeSynthesis/Golden/DefaultFun/Bls12_381_G1_multiScalarMul.plc.golden b/plutus-core/plutus-core/test/TypeSynthesis/Golden/DefaultFun/Bls12_381_G1_multiScalarMul.plc.golden new file mode 100644 index 00000000000..66a4d3528a9 --- /dev/null +++ b/plutus-core/plutus-core/test/TypeSynthesis/Golden/DefaultFun/Bls12_381_G1_multiScalarMul.plc.golden @@ -0,0 +1 @@ +list integer -> list bls12_381_G1_element -> bls12_381_G1_element \ No newline at end of file diff --git a/plutus-core/plutus-core/test/TypeSynthesis/Golden/DefaultFun/Bls12_381_G2_multiScalarMul.plc.golden b/plutus-core/plutus-core/test/TypeSynthesis/Golden/DefaultFun/Bls12_381_G2_multiScalarMul.plc.golden new file mode 100644 index 00000000000..be61240fdd0 --- /dev/null +++ b/plutus-core/plutus-core/test/TypeSynthesis/Golden/DefaultFun/Bls12_381_G2_multiScalarMul.plc.golden @@ -0,0 +1 @@ +list integer -> list bls12_381_G2_element -> bls12_381_G2_element \ No newline at end of file diff --git a/plutus-core/plutus-core/test/TypeSynthesis/Golden/Signatures/DefaultFun/Bls12_381_G1_multiScalarMul.sig.golden b/plutus-core/plutus-core/test/TypeSynthesis/Golden/Signatures/DefaultFun/Bls12_381_G1_multiScalarMul.sig.golden new file mode 100644 index 00000000000..c1aa616c465 --- /dev/null +++ b/plutus-core/plutus-core/test/TypeSynthesis/Golden/Signatures/DefaultFun/Bls12_381_G1_multiScalarMul.sig.golden @@ -0,0 +1 @@ +[Integer] -> [Element] -> Element \ No newline at end of file diff --git a/plutus-core/plutus-core/test/TypeSynthesis/Golden/Signatures/DefaultFun/Bls12_381_G2_multiScalarMul.sig.golden b/plutus-core/plutus-core/test/TypeSynthesis/Golden/Signatures/DefaultFun/Bls12_381_G2_multiScalarMul.sig.golden new file mode 100644 index 00000000000..c1aa616c465 --- /dev/null +++ b/plutus-core/plutus-core/test/TypeSynthesis/Golden/Signatures/DefaultFun/Bls12_381_G2_multiScalarMul.sig.golden @@ -0,0 +1 @@ +[Integer] -> [Element] -> Element \ 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 a171a769e8f..53d92524317 100644 --- a/plutus-core/plutus-ir/src/PlutusIR/Transform/RewriteRules/CommuteFnWithConst.hs +++ b/plutus-core/plutus-ir/src/PlutusIR/Transform/RewriteRules/CommuteFnWithConst.hs @@ -148,5 +148,7 @@ isCommutative = \case RotateByteString -> False CountSetBits -> False FindFirstSetBit -> False - ExpModInteger -> False - DropList -> False + ExpModInteger -> False + DropList -> False + Bls12_381_G1_multiScalarMul -> False + Bls12_381_G2_multiScalarMul -> False diff --git a/plutus-tx/changelog.d/20250515_113505_thomas.vellekoop_blsmsm.md b/plutus-tx/changelog.d/20250515_113505_thomas.vellekoop_blsmsm.md new file mode 100644 index 00000000000..d29228e385f --- /dev/null +++ b/plutus-tx/changelog.d/20250515_113505_thomas.vellekoop_blsmsm.md @@ -0,0 +1,3 @@ +### Added + +- in #7074 added the bls12_381_G1_multiScalarMul and bls12_381_G2_multiScalarMul builtins as per CIP 133 diff --git a/plutus-tx/src/PlutusTx/Builtins.hs b/plutus-tx/src/PlutusTx/Builtins.hs index 3d916e0b107..b7938cf3c05 100644 --- a/plutus-tx/src/PlutusTx/Builtins.hs +++ b/plutus-tx/src/PlutusTx/Builtins.hs @@ -100,6 +100,7 @@ module PlutusTx.Builtins ( , bls12_381_G1_equals , bls12_381_G1_add , bls12_381_G1_scalarMul + , bls12_381_G1_multiScalarMul , bls12_381_G1_neg , bls12_381_G1_compress , bls12_381_G1_uncompress @@ -110,6 +111,7 @@ module PlutusTx.Builtins ( , bls12_381_G2_equals , bls12_381_G2_add , bls12_381_G2_scalarMul + , bls12_381_G2_multiScalarMul , bls12_381_G2_neg , bls12_381_G2_compress , bls12_381_G2_uncompress @@ -587,6 +589,10 @@ bls12_381_G1_scalarMul :: Integer -> BuiltinBLS12_381_G1_Element -> BuiltinBLS12 bls12_381_G1_scalarMul = BI.bls12_381_G1_scalarMul {-# INLINABLE bls12_381_G1_scalarMul #-} +bls12_381_G1_multiScalarMul :: BI.BuiltinList Integer -> BI.BuiltinList BuiltinBLS12_381_G1_Element -> BuiltinBLS12_381_G1_Element +bls12_381_G1_multiScalarMul = BI.bls12_381_G1_multiScalarMul +{-# INLINABLE bls12_381_G1_multiScalarMul #-} + bls12_381_G1_neg :: BuiltinBLS12_381_G1_Element -> BuiltinBLS12_381_G1_Element bls12_381_G1_neg = BI.bls12_381_G1_neg {-# INLINABLE bls12_381_G1_neg #-} @@ -624,6 +630,10 @@ bls12_381_G2_scalarMul :: Integer -> BuiltinBLS12_381_G2_Element -> BuiltinBLS12 bls12_381_G2_scalarMul = BI.bls12_381_G2_scalarMul {-# INLINABLE bls12_381_G2_scalarMul #-} +bls12_381_G2_multiScalarMul :: BI.BuiltinList Integer -> BI.BuiltinList BuiltinBLS12_381_G2_Element -> BuiltinBLS12_381_G2_Element +bls12_381_G2_multiScalarMul = BI.bls12_381_G2_multiScalarMul +{-# INLINABLE bls12_381_G2_multiScalarMul #-} + bls12_381_G2_neg :: BuiltinBLS12_381_G2_Element -> BuiltinBLS12_381_G2_Element bls12_381_G2_neg = BI.bls12_381_G2_neg {-# INLINABLE bls12_381_G2_neg #-} diff --git a/plutus-tx/src/PlutusTx/Builtins/Internal.hs b/plutus-tx/src/PlutusTx/Builtins/Internal.hs index cd5d60fb8c8..3dcebe5794b 100644 --- a/plutus-tx/src/PlutusTx/Builtins/Internal.hs +++ b/plutus-tx/src/PlutusTx/Builtins/Internal.hs @@ -739,6 +739,11 @@ bls12_381_G1_scalarMul :: BuiltinInteger -> BuiltinBLS12_381_G1_Element -> Built bls12_381_G1_scalarMul n (BuiltinBLS12_381_G1_Element a) = BuiltinBLS12_381_G1_Element (BLS12_381.G1.scalarMul n a) {-# OPAQUE bls12_381_G1_scalarMul #-} +bls12_381_G1_multiScalarMul :: BuiltinList BuiltinInteger -> BuiltinList BuiltinBLS12_381_G1_Element -> BuiltinBLS12_381_G1_Element +bls12_381_G1_multiScalarMul (BuiltinList i) (BuiltinList e) = + BuiltinBLS12_381_G1_Element $ BLS12_381.G1.multiScalarMul i (fmap (\(BuiltinBLS12_381_G1_Element x) -> x) e) +{-# OPAQUE bls12_381_G1_multiScalarMul #-} + -- | Compresses a G1 element to a bytestring and never fails. bls12_381_G1_compress :: BuiltinBLS12_381_G1_Element -> BuiltinByteString bls12_381_G1_compress (BuiltinBLS12_381_G1_Element a) = BuiltinByteString (BLS12_381.G1.compress a) @@ -804,6 +809,11 @@ bls12_381_G2_scalarMul :: BuiltinInteger -> BuiltinBLS12_381_G2_Element -> Built bls12_381_G2_scalarMul n (BuiltinBLS12_381_G2_Element a) = BuiltinBLS12_381_G2_Element (BLS12_381.G2.scalarMul n a) {-# OPAQUE bls12_381_G2_scalarMul #-} +bls12_381_G2_multiScalarMul :: BuiltinList BuiltinInteger -> BuiltinList BuiltinBLS12_381_G2_Element -> BuiltinBLS12_381_G2_Element +bls12_381_G2_multiScalarMul (BuiltinList i) (BuiltinList e) = + BuiltinBLS12_381_G2_Element $ BLS12_381.G2.multiScalarMul i (fmap (\(BuiltinBLS12_381_G2_Element x) -> x) e) +{-# OPAQUE bls12_381_G2_multiScalarMul #-} + -- | Compresses a G2 element to a bytestring and never fails. bls12_381_G2_compress :: BuiltinBLS12_381_G2_Element -> BuiltinByteString bls12_381_G2_compress (BuiltinBLS12_381_G2_Element a) = BuiltinByteString (BLS12_381.G2.compress a)