Skip to content
New issue

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

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

Already on GitHub? Sign in to your account

Add encodeUtf8/decodeUtf8 for bytestrings and strings. #3288

Merged
merged 3 commits into from
Jun 3, 2021
Merged
Show file tree
Hide file tree
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
21 changes: 21 additions & 0 deletions plutus-core/plutus-core/src/PlutusCore/Builtins.hs
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ import Codec.Serialise
import Control.DeepSeq
import Crypto
import qualified Data.ByteString as BS
import qualified Data.ByteString.Char8 as BSC
import qualified Data.ByteString.Hash as Hash
import Data.Ix
import Data.Word (Word8)
Expand Down Expand Up @@ -74,6 +75,8 @@ data DefaultFun
| CharToString
| Append
| EqualsString
| EncodeUtf8
| DecodeUtf8
| Trace
| Nop1 -- TODO. These are only used for costing calibration and shouldn't be included in the defaults.
| Nop2
Expand Down Expand Up @@ -108,6 +111,8 @@ instance Pretty DefaultFun where
pretty CharToString = "charToString"
pretty Append = "append"
pretty EqualsString = "equalsString"
pretty EncodeUtf8 = "encodeUtf8"
pretty DecodeUtf8 = "decodeUtf8"
Comment on lines +114 to +115
Copy link
Contributor

Choose a reason for hiding this comment

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

Tangential: @michaelpj I'm so annoyed that we don't derive Pretty in terms of Show for DefaultFun, because of stuff like

pretty GreaterThanEqInteger = "greaterThanEqualsInteger"

Adding that pretty EncodeUtf8 = "encodeUtf8" line (and the other one) manually is stupid redundant work. Should we rename the constructors of DefaultFun to match with the Pretty instance or should we change the Pretty instance to be derived in terms of Show (with the first letter lowered) even if that breaks backwards compatibility?

Copy link
Contributor

Choose a reason for hiding this comment

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

Backwards compatibility for whom? Nobody uses the parser. I say change it. Not in this PR, though.

pretty Trace = "trace"
pretty Nop1 = "nop1"
pretty Nop2 = "nop2"
Expand Down Expand Up @@ -225,6 +230,14 @@ instance (GShow uni, GEq uni, DefaultUni <: uni) => ToBuiltinMeaning uni Default
makeBuiltinMeaning
((==) @String)
mempty -- TODO: budget.
toBuiltinMeaning EncodeUtf8 =
makeBuiltinMeaning
(BSC.pack :: String -> BS.ByteString)
mempty -- TODO: budget.
toBuiltinMeaning DecodeUtf8 =
makeBuiltinMeaning
(BSC.unpack :: BS.ByteString -> String)
mempty -- TODO: budget.
toBuiltinMeaning Trace =
makeBuiltinMeaning
(emit :: String -> Emitter ())
Expand Down Expand Up @@ -270,6 +283,8 @@ instance Serialise DefaultFun where
CharToString -> 22
Append -> 23
EqualsString -> 28
EncodeUtf8 -> 29
DecodeUtf8 -> 30
Trace -> 24
Nop1 -> 25
Nop2 -> 26
Expand Down Expand Up @@ -301,6 +316,8 @@ instance Serialise DefaultFun where
go 22 = pure CharToString
go 23 = pure Append
go 28 = pure EqualsString
go 29 = pure EncodeUtf8
go 30 = pure DecodeUtf8
go 24 = pure Trace
go 25 = pure Nop1
go 26 = pure Nop2
Expand Down Expand Up @@ -348,6 +365,8 @@ instance Flat DefaultFun where
CharToString -> 22
Append -> 23
EqualsString -> 28
EncodeUtf8 -> 29
DecodeUtf8 -> 30
Trace -> 24
Nop1 -> 25
Nop2 -> 26
Expand Down Expand Up @@ -379,6 +398,8 @@ instance Flat DefaultFun where
go 22 = pure CharToString
go 23 = pure Append
go 28 = pure EqualsString
go 29 = pure EncodeUtf8
go 30 = pure DecodeUtf8
go 24 = pure Trace
go 25 = pure Nop1
go 26 = pure Nop2
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
(fun (con bytestring) (con string))
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
(fun (con string) (con bytestring))
9 changes: 8 additions & 1 deletion plutus-tx-plugin/src/PlutusTx/Compiler/Builtins.hs
Original file line number Diff line number Diff line change
Expand Up @@ -176,6 +176,7 @@ builtinNames = [
, 'Builtins.lessThanByteString
, 'Builtins.greaterThanByteString
, 'Builtins.emptyByteString
, 'Builtins.decodeUtf8

, 'Builtins.verifySignature

Expand All @@ -200,6 +201,7 @@ builtinNames = [
, 'Builtins.emptyString
, 'Builtins.charToString
, 'Builtins.equalsString
, 'Builtins.encodeUtf8
, 'String.stringToBuiltinString

, 'Builtins.trace
Expand Down Expand Up @@ -273,10 +275,12 @@ defineBuiltinTerms = do
do
term <- wrapRel bsTy 2 $ mkBuiltin PLC.GtByteString
defineBuiltinTerm 'Builtins.greaterThanByteString term [bs, bool]

do
let term = PIR.mkConstant () BS.empty
defineBuiltinTerm 'Builtins.emptyByteString term [bs]
do
let term = mkBuiltin PLC.DecodeUtf8
defineBuiltinTerm 'Builtins.decodeUtf8 term [bs]

-- Integer builtins
do
Expand Down Expand Up @@ -343,6 +347,9 @@ defineBuiltinTerms = do
do
term <- wrapUnitFun strTy $ mkBuiltin PLC.Trace
defineBuiltinTerm 'Builtins.trace term [str, unit]
do
let term = mkBuiltin PLC.EncodeUtf8
defineBuiltinTerm 'Builtins.encodeUtf8 term [bs]

defineBuiltinTypes
:: CompilingDefault uni fun m
Expand Down
8 changes: 8 additions & 0 deletions plutus-tx-plugin/test/Plugin/Primitives/Spec.hs
Original file line number Diff line number Diff line change
Expand Up @@ -52,11 +52,13 @@ primitives = testNested "Primitives" [
, goldenUEval "sha2_256" [ getPlc sha2, liftProgram ("hello" :: Builtins.ByteString)]
, goldenUEval "equalsByteString" [ getPlc bsEquals, liftProgram ("hello" :: Builtins.ByteString), liftProgram ("hello" :: Builtins.ByteString)]
, goldenUEval "ltByteString" [ getPlc bsLt, liftProgram ("hello" :: Builtins.ByteString), liftProgram ("world" :: Builtins.ByteString)]
, goldenUEval "decodeUtf8" [ getPlc bsDecode, liftProgram ("hello" :: Builtins.ByteString)]
, goldenPir "verify" verify
, goldenPir "trace" trace
, goldenPir "stringLiteral" stringLiteral
, goldenPir "stringConvert" stringConvert
, goldenUEval "equalsString" [ getPlc stringEquals, liftProgram ("hello" :: String), liftProgram ("hello" :: String)]
, goldenPir "encodeUtf8" stringEncode
]

string :: CompiledCode String
Expand Down Expand Up @@ -120,6 +122,9 @@ bsEquals = plc (Proxy @"bs32Equals") (\(x :: Builtins.ByteString) (y :: Builtins
bsLt :: CompiledCode (Builtins.ByteString -> Builtins.ByteString -> Bool)
bsLt = plc (Proxy @"bsLt") (\(x :: Builtins.ByteString) (y :: Builtins.ByteString) -> Builtins.lessThanByteString x y)

bsDecode :: CompiledCode (Builtins.ByteString -> Builtins.String)
bsDecode = plc (Proxy @"bsDecode") (\(x :: Builtins.ByteString) -> Builtins.decodeUtf8 x)

verify :: CompiledCode (Builtins.ByteString -> Builtins.ByteString -> Builtins.ByteString -> Bool)
verify = plc (Proxy @"verify") (\(x::Builtins.ByteString) (y::Builtins.ByteString) (z::Builtins.ByteString) -> Builtins.verifySignature x y z)

Expand All @@ -134,3 +139,6 @@ stringConvert = plc (Proxy @"stringConvert") ((noinline P.stringToBuiltinString)

stringEquals :: CompiledCode (String -> String -> Bool)
stringEquals = plc (Proxy @"string32Equals") (\(x :: String) (y :: String) -> Builtins.equalsString (P.stringToBuiltinString x) (P.stringToBuiltinString y))

stringEncode :: CompiledCode (Builtins.ByteString)
stringEncode = plc (Proxy @"stringEncode") (Builtins.encodeUtf8 "abc")
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
(con string "hello")
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
(program [ (builtin encodeUtf8) (con string "abc") ])
12 changes: 12 additions & 0 deletions plutus-tx/src/PlutusTx/Builtins.hs
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ module PlutusTx.Builtins (
, sha2_256
, sha3_256
, verifySignature
, decodeUtf8
-- * Integer builtins
, addInteger
, subtractInteger
Expand All @@ -41,6 +42,7 @@ module PlutusTx.Builtins (
, emptyString
, charToString
, equalsString
, encodeUtf8
-- * Tracing
, trace
) where
Expand Down Expand Up @@ -113,6 +115,11 @@ lessThanByteString = (<)
greaterThanByteString :: ByteString -> ByteString -> Bool
greaterThanByteString = (>)

{-# NOINLINE decodeUtf8 #-}
-- | Converts a ByteString to a String.
decodeUtf8 :: ByteString -> String
Copy link
Contributor

Choose a reason for hiding this comment

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

haddock for these. Yes, it's somewhat obvious, but it never hurts.

decodeUtf8 = mustBeReplaced "decodeUtf8"

{-# NOINLINE addInteger #-}
-- | Add two 'Integer's.
addInteger :: Integer -> Integer -> Integer
Expand Down Expand Up @@ -225,3 +232,8 @@ equalsString = mustBeReplaced "equalsString"
-- | Logs the given 'String' to the evaluation log.
trace :: String -> ()
trace _ = () --mustBeReplaced "trace"

{-# NOINLINE encodeUtf8 #-}
-- | Convert a String into a ByteString.
encodeUtf8 :: String -> ByteString
encodeUtf8 = mustBeReplaced "encodeUtf8"