From b7f036848dabe2e043e1f0ad8890bb29a601be86 Mon Sep 17 00:00:00 2001 From: Balazs Komuves Date: Fri, 14 Mar 2025 17:05:39 +0100 Subject: [PATCH] parse JSON input files (in Haskell) --- README.md | 18 ++++++++++------ haskell/src/JSON.hs | 52 +++++++++++++++++++++++++++++++++++++++++++++ haskell/src/Main.hs | 11 +++++++--- 3 files changed, 71 insertions(+), 10 deletions(-) create mode 100644 haskell/src/JSON.hs diff --git a/README.md b/README.md index b5ff5df..7df50b8 100644 --- a/README.md +++ b/README.md @@ -6,27 +6,31 @@ The original idea behind this small project was to take the "computation graph" files generated by [`circom-witnesscalc`](https://github.com/iden3/circom-witnesscalc), and either interprets or compiles them to various algebra backends. -While this is quite straightforward in principle, and seems to work on small -examples, it turns out that `circom-witnesscalc` itself is completely broken, -in the sense that it doesn't seem to be able to handle nontrivial circuits using any -kind of meaningful metaprogramming (that being the only thing which makes `circom` -borderline useful). +While this is quite straightforward in principle, and seems to work on particular +examples, it turns out that `circom-witnesscalc` itself has some serious limitations. -And this doesn't look fixable without something like a full rewrite of `circom-witnesscalc` (?). +The biggest one is that it doesn't support any kind of dynamic computation (which should +be obvious from the fact that it produces a static graph). But even if one uses only +static computations, there are further very annoying things which just don't work. + +However at the end this is still a useful thing. ### Implementation status Compiler (in Haskell): - [x] parsing the graph file +- [x] parsing json input - [x] naive interpreter +- [ ] exporting the witness - [ ] constantine backend - [ ] zikkurat backend - [ ] arkworks backend -Nim witness generator: +Nim witness generator (to be used with [`nim-groth16`](https://github.com/codex-storage/nim-groth16)) - [x] parsing the graph file +- [ ] parsing json input - [ ] generating the witness - [ ] proper error handling diff --git a/haskell/src/JSON.hs b/haskell/src/JSON.hs new file mode 100644 index 0000000..9bdb9b2 --- /dev/null +++ b/haskell/src/JSON.hs @@ -0,0 +1,52 @@ + +-- | Parse JSON input files + +module JSON where + +-------------------------------------------------------------------------------- + +import Data.List +import Data.Foldable as F +import Data.Foldable.WithIndex as FI + +import Data.Map (Map) +import qualified Data.Map as Map + +import qualified Data.Text as T +import qualified Data.ByteString as B + +import Data.Aeson +import Data.Aeson.Key as Key +import Data.Scientific + +-------------------------------------------------------------------------------- + +parseInputJsonValue :: Value -> Map String [Integer] +parseInputJsonValue val = + case val of + Object obj -> Map.fromList (map worker (FI.itoList obj)) + _ -> error "parseInputJsonValue: expecting a JSON object" + where + + worker (key,value) = (Key.toString key, flatten value) + + flatten :: Value -> [Integer] + flatten val = case val of + Number num -> numberToInteger num + Array arr -> F.concatMap flatten arr + String txt -> [read (T.unpack txt)] + _ -> error "parseInputJsonValue/flatten: expecting a number or an array" + + numberToInteger x = case floatingOrInteger x of + Right y -> [y] + Left _ -> error "parseInputJsonValue/numberToInteger: expecting an integer" + +-------------------------------------------------------------------------------- + +loadInputJsonFile :: FilePath -> IO (Map String [Integer]) +loadInputJsonFile fpath = do + text <- B.readFile fpath + let Just value = decodeStrict text + return $ parseInputJsonValue value + +-------------------------------------------------------------------------------- diff --git a/haskell/src/Main.hs b/haskell/src/Main.hs index e4db71d..f27f58f 100644 --- a/haskell/src/Main.hs +++ b/haskell/src/Main.hs @@ -8,8 +8,11 @@ import qualified Data.Map as Map import Witness import Parser +import Graph +import JSON -------------------------------------------------------------------------------- +{- (~>) :: String -> a -> (String, a) (~>) = (,) @@ -22,13 +25,15 @@ testInputs = Map.fromList , "b" ~> [0xff02] ] +-} -------------------------------------------------------------------------------- main :: IO () main = do - Right graph <- parseGraphFile "../tmp/graph2.bin" + Right graph <- parseGraphFile "../../tmp/graph4.bin" putStrLn "" - print graph - let wtns = witnessCalc testInputs graph + inputs <- loadInputJsonFile "../../tmp/input4.json" + print (inputSignals $ graphMeta graph) + let wtns = witnessCalc inputs graph putStrLn "" print wtns \ No newline at end of file