Skip to content

Commit 0604658

Browse files
committed
added CircomProgram type
1 parent 191e890 commit 0604658

File tree

10 files changed

+86
-43
lines changed

10 files changed

+86
-43
lines changed

Diff for: arithmetic-circuits.cabal

+2
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@ common deps
4444
build-depends:
4545
aeson >=1.4
4646
, base >=4.10 && <5
47+
, binary >=0.8.9 && <0.9
4748
, containers >=0.6.0
4849
, filepath >=1.4.2
4950
, finite-typelits >=0.1.0
@@ -111,6 +112,7 @@ library circom-compat
111112
hs-source-dirs: circom-compat/src
112113
build-depends:
113114
arithmetic-circuits
115+
, arithmetic-circuits:language
114116
, binary
115117
, bytestring
116118
, vector

Diff for: cabal.project

+1-1
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ source-repository-package
1313
source-repository-package
1414
type: git
1515
location: https://github.com/l-adic/galois-fields.git
16-
tag: b0867ffdebda5043c80315a51b15e82ed25acba6
16+
tag: 33ee3d68dc9c118e88e8842d9f423a9f4f9851cf
1717
--sha256: j/zGFd2aeowzJfgCCBmJYmG8mDsfF0irqj/cPOw9ulE=
1818

1919
source-repository-package

Diff for: circom-compat/app/Main.hs

+14-12
Original file line numberDiff line numberDiff line change
@@ -2,24 +2,26 @@ module Main where
22

33
import Circuit
44
import Circuit.Language
5-
import Data.Binary (encodeFile)
5+
import Circuit.Solver.Circom (CircomProgram (..), mkCircomProgram, nativeGenWitness)
6+
import Data.Binary (encodeFile, decodeFile)
67
import Data.Field.Galois (Prime)
7-
import Data.IntMap qualified as IntMap
8-
import Data.IntSet qualified as IntSet
8+
import Data.Map qualified as Map
99
import Protolude
10-
import R1CS (Inputs (..), calculateWitness, isValidWitness)
11-
import R1CS.Circom (r1csToCircomR1CS, witnessToCircomWitness)
10+
import R1CS (toR1CS)
11+
import R1CS.Circom (r1csToCircomR1CS)
1212

1313
main :: IO ()
1414
main = do
1515
let BuilderState {..} = snd $ runCircuitBuilder program
16-
publicInputs = IntMap.fromList $ zip (IntSet.toAscList $ cvPublicInputs bsVars) [6]
17-
privateInputs = IntMap.fromList $ zip (IntSet.toAscList $ cvPrivateInputs bsVars) [2, 3]
18-
inputs = publicInputs <> privateInputs
19-
(r1cs, wtns) = calculateWitness bsVars bsCircuit (Inputs inputs)
20-
unless (isValidWitness wtns r1cs) $ panic "Invalid witness"
21-
encodeFile "circom-compat/examples/factors/circuit.r1cs" $ r1csToCircomR1CS r1cs
22-
encodeFile "circom-compat/examples/factors/witness.wtns" $ witnessToCircomWitness wtns
16+
prog = mkCircomProgram bsVars bsCircuit
17+
r1cs = r1csToCircomR1CS $ toR1CS (cpVars prog) (cpCircuit prog)
18+
inputs = Map.fromList [("n", 6), ("a", 2), ("b", 3)]
19+
wtns = nativeGenWitness prog inputs
20+
encodeFile "circom-compat/examples/factors/circuit.r1cs" r1cs
21+
encodeFile "circom-compat/examples/factors/circuit.bin" prog
22+
encodeFile "circom-compat/examples/factors/witness.wtns" wtns
23+
prog' <- decodeFile "circom-compat/examples/factors/circuit.bin"
24+
print $ nativeGenWitness prog' inputs == wtns
2325

2426
type Fr = Prime 21888242871839275222246405745257275088548364400416034343698204186575808495617
2527

Diff for: circom-compat/examples/factors/circuit.bin

546 Bytes
Binary file not shown.

Diff for: circom-compat/examples/factors/circuit.r1cs

856 Bytes
Binary file not shown.

Diff for: circom-compat/examples/factors/witness.wtns

364 Bytes
Binary file not shown.

Diff for: circom-compat/src/Circuit/Solver/Circom.hs

+33-11
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,9 @@
11
module Circuit.Solver.Circom
2-
( ProgramEnv (..),
2+
( CircomProgram,
3+
cpVars,
4+
cpCircuit,
5+
mkCircomProgram,
6+
ProgramEnv (..),
37
mkProgramEnv,
48
ProgramState (..),
59
mkProgramState,
@@ -15,11 +19,12 @@ module Circuit.Solver.Circom
1519
_setInputSignal,
1620
_getWitnessSize,
1721
_getWitness,
18-
standardSolver,
22+
nativeGenWitness,
1923
)
2024
where
2125

2226
import Circuit
27+
import Data.Binary (Binary)
2328
import Data.Field.Galois (GaloisField, PrimeField (fromP), char)
2429
import Data.IORef (IORef, readIORef, writeIORef)
2530
import Data.IntMap qualified as IntMap
@@ -31,9 +36,28 @@ import Data.Vector.Mutable qualified as MV
3136
import FNV (FNVHash (..), hashText, mkFNV)
3237
import Protolude
3338
import R1CS (Inputs (..), Witness (..), oneVar)
34-
import R1CS.Circom (CircomWitness, FieldSize (..), integerFromLittleEndian, integerToLittleEndian, n32, witnessToCircomWitness)
39+
import R1CS.Circom (CircomWitness, FieldSize (..), circomReindexMap, integerFromLittleEndian, integerToLittleEndian, n32, witnessToCircomWitness)
3540
import Text.PrettyPrint.Leijen.Text (Pretty (pretty), (<+>))
3641

42+
data CircomProgram f = CircomProgram
43+
{ cpVars :: CircuitVars Text,
44+
cpCircuit :: ArithCircuit f
45+
}
46+
deriving (Generic)
47+
48+
instance (Binary f) => Binary (CircomProgram f)
49+
50+
mkCircomProgram ::
51+
CircuitVars Text ->
52+
ArithCircuit f ->
53+
CircomProgram f
54+
mkCircomProgram vars circ =
55+
let f = circomReindexMap vars
56+
in CircomProgram
57+
{ cpVars = reindex f vars,
58+
cpCircuit = reindex f circ
59+
}
60+
3761
-- WASM Solver
3862

3963
data ProgramEnv f = ProgramEnv
@@ -49,10 +73,9 @@ data ProgramEnv f = ProgramEnv
4973
mkProgramEnv ::
5074
forall f.
5175
(GaloisField f) =>
52-
CircuitVars Text ->
53-
ArithCircuit f ->
76+
CircomProgram f ->
5477
ProgramEnv f
55-
mkProgramEnv vars circ =
78+
mkProgramEnv CircomProgram {cpVars = vars, cpCircuit = circ} =
5679
ProgramEnv
5780
{ peFieldSize = FieldSize 32,
5881
peRawPrime = toInteger $ char (1 :: f),
@@ -163,22 +186,21 @@ _getWitness env stRef i = do
163186
--------------------------------------------------------------------------------
164187
-- Standard Solver (to be used as native executable)
165188

166-
standardSolver ::
189+
nativeGenWitness ::
167190
forall f.
168191
(PrimeField f) =>
169-
CircuitVars Text ->
170-
ArithCircuit f ->
192+
CircomProgram f ->
171193
Map Text f ->
172194
CircomWitness f
173-
standardSolver vars circ inputs =
195+
nativeGenWitness CircomProgram {cpVars = vars, cpCircuit = circ} inputs =
174196
let initAssignments = assignInputs vars inputs
175197
wtns =
176198
evalArithCircuit
177199
(\w a -> IntMap.lookup (wireName w) a)
178200
(\w a -> safeAssign (wireName w) a)
179201
circ
180202
initAssignments
181-
in witnessToCircomWitness $ Witness $ IntMap.insert oneVar 1 wtns
203+
in witnessToCircomWitness $ Witness wtns
182204

183205
--------------------------------------------------------------------------------
184206

Diff for: circom-compat/src/R1CS/Circom.hs

+18-17
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ import Data.IntSet qualified as IntSet
2828
import Data.Vector (Vector)
2929
import Data.Vector qualified as V
3030
import Protolude
31-
import R1CS (LinearPoly (..), R1C (..), R1CS (..), Witness (..))
31+
import R1CS (LinearPoly (..), R1C (..), R1CS (..), Witness (..), oneVar)
3232
import Prelude (fail)
3333

3434
--------------------------------------------------------------------------------
@@ -343,22 +343,23 @@ data CircomWitness f = CircomWitness
343343
deriving (Show, Eq)
344344

345345
witnessToCircomWitness :: forall f. (PrimeField f) => Witness f -> CircomWitness f
346-
witnessToCircomWitness (Witness m) =
347-
CircomWitness
348-
{ wtnsPreamble =
349-
Preamble
350-
{ magic = 0x736e7477,
351-
version = 1,
352-
nSections = 2
353-
},
354-
wtnsHeader =
355-
WitnessHeader
356-
{ whFieldSize = FieldSize 32,
357-
whPrime = fromIntegral $ char (1 :: f),
358-
whWitnessSize = fromIntegral $ IntMap.size m
359-
},
360-
wtnsValues = snd <$> IntMap.toAscList m
361-
}
346+
witnessToCircomWitness (Witness _m) =
347+
let m = IntMap.insert oneVar 1 _m
348+
in CircomWitness
349+
{ wtnsPreamble =
350+
Preamble
351+
{ magic = 0x736e7477,
352+
version = 1,
353+
nSections = 2
354+
},
355+
wtnsHeader =
356+
WitnessHeader
357+
{ whFieldSize = FieldSize 32,
358+
whPrime = fromIntegral $ char (1 :: f),
359+
whWitnessSize = fromIntegral $ IntMap.size m
360+
},
361+
wtnsValues = snd <$> IntMap.toAscList m
362+
}
362363

363364
witnessFromCircomWitness :: CircomWitness f -> Witness f
364365
witnessFromCircomWitness (CircomWitness {wtnsValues}) =

Diff for: circuit/src/Circuit/Affine.hs

+3
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ module Circuit.Affine
1111
where
1212

1313
import Data.Aeson (FromJSON, ToJSON)
14+
import Data.Binary (Binary)
1415
import Data.Map qualified as Map
1516
import Protolude
1617
import Text.PrettyPrint.Leijen.Text
@@ -30,6 +31,8 @@ data AffineCircuit f i
3031
| Var i
3132
deriving (Read, Eq, Ord, Show, Generic, NFData)
3233

34+
instance (Binary i, Binary f) => Binary (AffineCircuit f i)
35+
3336
instance (FromJSON i, FromJSON f) => FromJSON (AffineCircuit f i)
3437

3538
instance (ToJSON i, ToJSON f) => ToJSON (AffineCircuit f i)

Diff for: circuit/src/Circuit/Arithmetic.hs

+15-2
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ import Circuit.Affine
3131
evalAffineCircuit,
3232
)
3333
import Data.Aeson (FromJSON, ToJSON)
34+
import Data.Binary (Binary)
3435
import Data.Field.Galois (PrimeField, fromP)
3536
import Data.IntMap qualified as IntMap
3637
import Data.IntSet qualified as IntSet
@@ -54,6 +55,8 @@ instance FromJSON InputType
5455

5556
instance ToJSON InputType
5657

58+
instance Binary InputType
59+
5760
-- | Wires are can be labeled in the ways given in this data type
5861
data Wire
5962
= InputWire Text InputType Int
@@ -68,6 +71,8 @@ instance ToJSON Wire
6871
instance Hashable Wire where
6972
hashWithSalt s w = s `hashWithSalt` (0 :: Int) `hashWithSalt` (wireName w)
7073

74+
instance Binary Wire
75+
7176
instance Pretty Wire where
7277
pretty (InputWire label t v) =
7378
let a = case t of
@@ -109,6 +114,8 @@ deriving instance Foldable (Gate f)
109114

110115
deriving instance Traversable (Gate f)
111116

117+
instance (Binary i, Binary f) => Binary (Gate f i)
118+
112119
instance Bifunctor Gate where
113120
bimap f g = \case
114121
Mul l r o -> Mul (bimap f g l) (bimap f g r) (g o)
@@ -211,6 +218,8 @@ instance (FromJSON f) => FromJSON (ArithCircuit f)
211218

212219
instance (ToJSON f) => ToJSON (ArithCircuit f)
213220

221+
instance (Binary f) => Binary (ArithCircuit f)
222+
214223
instance Functor ArithCircuit where
215224
fmap f (ArithCircuit gates) = ArithCircuit $ map (first f) gates
216225

@@ -287,7 +296,9 @@ data CircuitVars label = CircuitVars
287296
cvOutputs :: IntSet,
288297
cvInputsLabels :: InputBidings label
289298
}
290-
deriving (Show)
299+
deriving (Show, Generic, NFData)
300+
301+
instance (Binary label) => Binary (CircuitVars label)
291302

292303
instance (Pretty label) => Pretty (CircuitVars label) where
293304
pretty CircuitVars {cvVars, cvPrivateInputs, cvPublicInputs, cvOutputs, cvInputsLabels} =
@@ -392,7 +403,9 @@ data InputBidings label = InputBidings
392403
{ labelToVar :: Map label Int,
393404
varToLabel :: IntMap label
394405
}
395-
deriving (Show)
406+
deriving (Show, Generic, NFData)
407+
408+
instance (Binary label) => Binary (InputBidings label)
396409

397410
mapLabels :: (Ord l2) => (l1 -> l2) -> InputBidings l1 -> InputBidings l2
398411
mapLabels f InputBidings {labelToVar, varToLabel} =

0 commit comments

Comments
 (0)