Skip to content

Commit 50d44f4

Browse files
committed
add fv translation
1 parent ddeb817 commit 50d44f4

File tree

8 files changed

+77
-2
lines changed

8 files changed

+77
-2
lines changed

docs/en/pact-properties-api.md

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -814,6 +814,19 @@ BLAKE2b 256-bit hash of lists
814814

815815
Supported in properties only.
816816

817+
### keccak {#FKeccak256Hash}
818+
819+
```lisp
820+
(keccak256 xs)
821+
```
822+
823+
* takes `xs`: [`string`]
824+
* produces `string`
825+
826+
Compute the hash of a list of base64-encoded inputs. The hash is computed incrementally over all of the base64-decoded inputs.
827+
828+
Supported in properties only.
829+
817830
## String operators {#String}
818831

819832
### length {#FStringLength}

src-tool/Pact/Analyze/Eval/Core.hs

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,9 +47,11 @@ import Pact.Types.Util (AsString(asString))
4747
import Data.Text.Encoding (encodeUtf8)
4848
import qualified Pact.Types.Lang as Pact
4949
import qualified Pact.Types.PactValue as Pact
50+
import Crypto.Hash.Keccak256Native
5051
import qualified Data.ByteString as BS
5152
import Data.Functor ((<&>))
5253
import qualified Data.Vector as V
54+
import Data.Default
5355

5456
import qualified Pact.JSON.Encode as J
5557

@@ -312,6 +314,17 @@ evalCore (ListHash ty' xs) = do
312314
SList t' -> Pact.PList . V.fromList <$> traverse (reify t') c
313315
_ -> throwErrorNoLoc (FailureMessage "Unsupported type, currently we support integer, decimal, string, and bool")
314316

317+
evalCore (Keccak256Hash xs) = eval xs <&> unliteralS >>= \case
318+
Nothing ->do
319+
-- (keccak256 [])
320+
let h = "xdJGAYb3IzySfn2y3McDwOUAtlPKgic7e/rYBF2FpHA="
321+
emitWarning (FVShimmedStaticContent "keccac256" ("of type '[string]', substitute '" <> T.pack h <> "')"))
322+
pure (literalS (Str h))
323+
Just (xs':: [Str]) -> do
324+
let tm = fmap (\x -> Pact.TLiteral (Pact.LString $ T.pack $ unStr x) def) xs'
325+
h = keccak256 (V.fromList tm)
326+
pure (literalS . Str . T.unpack $ h)
327+
315328
evalCore (ListContains ty needle haystack) = withSymVal ty $ do
316329
S _ needle' <- withSing ty $ eval needle
317330
S _ haystack' <- withSing ty $ eval haystack

src-tool/Pact/Analyze/Feature.hs

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -133,6 +133,7 @@ data Feature
133133
| FNumericalHash
134134
| FBoolHash
135135
| FListHash
136+
| FKeccak256Hash
136137
-- Temporal operators
137138
| FTemporalAddition
138139
| FTemporalDiff
@@ -1303,6 +1304,21 @@ doc FListHash = Doc
13031304
]
13041305
(TyCon str)
13051306
]
1307+
doc FKeccak256Hash = Doc
1308+
"keccak"
1309+
CList
1310+
PropOnly
1311+
"Compute the hash of a list of base64-encoded inputs. The hash is computed incrementally over all of the base64-decoded inputs."
1312+
[ Usage
1313+
"(keccak256 xs)"
1314+
Map.empty
1315+
$ Fun
1316+
Nothing
1317+
[ ("xs", TyList' (TyCon str))
1318+
]
1319+
(TyCon str)
1320+
]
1321+
13061322
-- Temporal features
13071323

13081324
doc FTemporalAddition = Doc
@@ -1894,6 +1910,7 @@ PAT(SStringHash, FStringHash)
18941910
PAT(SNumericalHash, FNumericalHash)
18951911
PAT(SBoolHash, FBoolHash)
18961912
PAT(SListHash, FListHash)
1913+
PAT(SKeccak256Hash, FKeccak256Hash)
18971914
PAT(STemporalAddition, FTemporalAddition)
18981915
PAT(STemporalDiff, FTemporalDiff)
18991916
PAT(SUniversalQuantification, FUniversalQuantification)

src-tool/Pact/Analyze/Patterns.hs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -189,6 +189,10 @@ pattern AST_ParseTime formatStr timeStr <-
189189
pattern AST_Hash :: forall a. AST a -> AST a
190190
pattern AST_Hash val <- App _node (NativeFunc "hash") [val]
191191

192+
pattern AST_Keccak :: forall a. AST a -> AST a
193+
pattern AST_Keccak val <- App _node (NativeFunc "keccak256") [val]
194+
195+
192196
pattern AST_AddTime :: forall a. AST a -> AST a -> AST a
193197
pattern AST_AddTime time seconds <- App _ (NativeFunc STemporalAddition) [time, seconds]
194198

src-tool/Pact/Analyze/PrenexNormalize.hs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -109,6 +109,7 @@ singFloat ty p = case p of
109109
CoreProp (BoolHash s) -> CoreProp . BoolHash <$> float s
110110
CoreProp (DecHash s) -> CoreProp . DecHash <$> float s
111111
CoreProp (ListHash ty' s) -> CoreProp . ListHash ty' <$> singFloat (SList ty') s
112+
CoreProp (Keccak256Hash s) -> CoreProp . Keccak256Hash <$> float s
112113
-- time
113114
CoreProp (IntAddTime time int) -> PIntAddTime <$> float time <*> float int
114115
CoreProp (DecAddTime time dec) -> PDecAddTime <$> float time <*> float dec

src-tool/Pact/Analyze/Translate.hs

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1007,7 +1007,7 @@ translateNode astNode = withAstContext astNode $ case astNode of
10071007
notStaticShim = do
10081008
addWarning' (UnsupportedNonFatal "Call to `hash` is only implemented for string, bool, and integer, substituting hash of `hello pact`")
10091009
wrap (StrHash (Lit' (Str "hello pact")))
1010-
1010+
10111011
case ty of
10121012
SStr -> wrap (StrHash val')
10131013
SBool -> wrap (BoolHash val')
@@ -1022,6 +1022,10 @@ translateNode astNode = withAstContext astNode $ case astNode of
10221022
_otherwise -> notStaticShim
10231023
_otherwise -> notStaticShim
10241024

1025+
AST_Keccak val -> translateNode val >>= \case
1026+
Some (SList SStr) val' -> pure $ Some SStr $ CoreTerm $ Keccak256Hash val'
1027+
_ -> unexpectedNode astNode
1028+
10251029
AST_ReadKeyset nameA -> translateNode nameA >>= \case
10261030
Some SStr nameT -> return $ Some SGuard $ ReadKeySet nameT
10271031
_ -> unexpectedNode astNode

src-tool/Pact/Analyze/Types/Languages.hs

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -213,6 +213,9 @@ data Core (t :: Ty -> K.Type) (a :: Ty) where
213213
DecHash :: t 'TyDecimal -> Core t 'TyStr
214214
ListHash :: SingTy a -> t ('TyList a) -> Core t 'TyStr
215215

216+
-- | Keccak256 hash
217+
Keccak256Hash :: t ('TyList 'TyStr) -> Core t 'TyStr
218+
216219
Enumerate :: t 'TyInteger -> t 'TyInteger -> t 'TyInteger -> Core t ('TyList 'TyInteger)
217220

218221
-- numeric ops
@@ -765,6 +768,7 @@ showsPrecCore ty p core = showParen (p > 10) $ case core of
765768
BoolHash a -> showString "BoolHash " . showsTm 11 a
766769
DecHash a -> showString "DecimalHash " . showsTm 11 a
767770
ListHash ty' a -> showString "ListHash " . showsPrec 11 ty' . showChar ' ' . singShowsTmList ty' 11 a
771+
Keccak256Hash a -> showString "Keccak256" . showsTm 11 a
768772
Enumerate a b c -> showString "Enumerate " . showsTm 11 a . showChar ' ' . showsTm 11 b . showChar ' ' . showsTm 11 c
769773
Numerical a -> showString "Numerical " . showsNumerical ty 11 a
770774
IntAddTime a b -> showString "IntAddTime " . showsTm 11 a . showChar ' ' . showsTm 11 b
@@ -1024,7 +1028,7 @@ prettyCore ty = \case
10241028
BoolHash x -> parensSep [pretty SBoolHash, prettyTm x]
10251029
DecHash x -> parensSep [pretty SNumericalHash, prettyTm x]
10261030
ListHash ty' x -> parensSep [pretty SListHash, singPrettyTmList ty' x]
1027-
1031+
Keccak256Hash x -> parensSep [pretty SKeccak256Hash, prettyTm x]
10281032
Enumerate x y z -> parensSep [pretty SEnumerate, prettyTm x, prettyTm y, prettyTm z]
10291033
Numerical tm -> prettyNumerical ty tm
10301034
IntAddTime x y -> parensSep [pretty STemporalAddition, prettyTm x, prettyTm y]
@@ -1911,6 +1915,8 @@ propToInvariant (CoreProp core) = CoreInvariant <$> case core of
19111915
BoolHash <$> f tm1
19121916
ListHash ty tm1 ->
19131917
ListHash ty <$> f tm1
1918+
Keccak256Hash tm ->
1919+
Keccak256Hash <$> f tm
19141920
Enumerate tm1 tm2 tm3 ->
19151921
Enumerate <$> f tm1 <*> f tm2 <*> f tm3
19161922
Numerical num ->

tests/AnalyzeSpec.hs

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2814,6 +2814,23 @@ spec = describe "analyze" $ do
28142814
|]
28152815
expectPass code $ Valid Success'
28162816

2817+
describe "keccak256" $ do
2818+
let code =
2819+
[text|
2820+
(defun test:bool (arg:[string])
2821+
;; (enforce (=
2822+
;; (keccak256 [""])
2823+
;; "xdJGAYb3IzySfn2y3McDwOUAtlPKgic7e/rYBF2FpHA=") "should match empty")
2824+
2825+
(enforce (=
2826+
(keccak256 [""])
2827+
(keccak256 arg)) "should match empty")
2828+
2829+
2830+
)
2831+
|]
2832+
expectPass code $ Valid Success'
2833+
28172834
describe "validate-principal" $ do
28182835
let code =
28192836
[text| (defun test:bool (ks: keyset)

0 commit comments

Comments
 (0)