/ tests / TestGoldilocks.hs
TestGoldilocks.hs
  1  
  2  
  3  module TestGoldilocks where
  4  
  5  --------------------------------------------------------------------------------
  6  
  7  import Semantics
  8  
  9  import Common
 10  
 11  --------------------------------------------------------------------------------
 12  -- global parameters
 13  
 14  circomFile :: FilePath
 15  circomFile = circuitSourceDir </> "test_wrapper.circom"
 16  
 17  data Op
 18    = Neg
 19    | Add
 20    | Sub
 21    | Sqr
 22    | Mul
 23    | Inv
 24    | Div
 25    deriving (Eq,Show,Bounded,Enum)
 26  
 27  enumerateOps :: [Op]
 28  enumerateOps = enumFromTo minBound maxBound
 29  
 30  ----------------------------------------
 31  
 32  mainComponent :: Op -> MainComponent
 33  mainComponent op = 
 34    case op of
 35      Neg -> unary  "Neg"
 36      Add -> binary "Add"
 37      Sub -> binary "Sub"
 38      Sqr -> unary  "Sqr"
 39      Mul -> binary "Mul"
 40      Inv -> unary  "Inv"
 41      Div -> binary "Div"
 42    where
 43  
 44      unary name = MainComponent 
 45        { _templateName   = name ++ "Wrapper"
 46        , _templateParams = []
 47        , _publicInputs   = ["A"]
 48        }
 49  
 50      binary name = MainComponent 
 51        { _templateName   = name ++ "Wrapper"
 52        , _templateParams = []
 53        , _publicInputs   = ["A","B"]
 54        }
 55  
 56  --------------------------------------------------------------------------------
 57  -- test cases and expected semantics
 58  
 59  type TestCase1 = Int
 60  type TestCase2 = (Int,Int)
 61  
 62  type Output = Int
 63  
 64  testCasesUnary :: [TestCase1]
 65  testCasesUnary = [0..fieldPrime-1]
 66  
 67  testCasesBinary :: [TestCase2]
 68  testCasesBinary = [ (a,b) | a<-testCasesUnary , b<-testCasesUnary ]
 69  
 70  -- | Multiplication and division is too slow to test exhaustively
 71  testCasesBinarySmall :: [TestCase2]
 72  testCasesBinarySmall = [ (a,b) | a<-testset, b<-testset ] where
 73    testset = [0..17] ++ [63,64,65] ++ [127,128,129] ++ [191,192,193] ++ [fieldPrime-18..fieldPrime-1]
 74  
 75  ----------------------------------------
 76  
 77  semantics_neg :: F -> Expected F
 78  semantics_neg x = Expecting $ Semantics.neg x
 79  
 80  semantics_add :: (F,F) -> Expected F
 81  semantics_add (x,y) = Expecting $ Semantics.add x y
 82  
 83  semantics_sub :: (F,F) -> Expected F
 84  semantics_sub (x,y) = Expecting $ Semantics.sub x y
 85  
 86  semantics_sqr :: F -> Expected F
 87  semantics_sqr x = Expecting $ Semantics.sqr x 
 88  
 89  semantics_mul :: (F,F) -> Expected F
 90  semantics_mul (x,y) = Expecting $ Semantics.mul x y
 91  
 92  semantics_inv :: F -> Expected F
 93  semantics_inv x = Expecting $ Semantics.inv x
 94  
 95  semantics_div :: (F,F) -> Expected F
 96  semantics_div (x,y) = Expecting $ Semantics.div x y
 97  
 98  --------------------------------------------------------------------------------
 99  -- inputs and outputs
100  
101  inputsA :: TestCase1 -> Inputs Name Integer
102  inputsA a = Inputs $  toMapping "A" a
103                      
104  inputsAB :: TestCase2 -> Inputs Name Integer
105  inputsAB (a,b) = Inputs $  toMapping "A" a
106                          <> toMapping "B" b
107  
108  outputsC :: Output -> Outputs Name Integer
109  outputsC y = Outputs $ toMapping "C" y
110  
111  --------------------------------------------------------------------------------
112  
113  specUnary :: Op -> (F -> Expected F) -> TestSpec TestCase1 Output
114  specUnary op semantics = TestSpec circomFile (mainComponent op) inputsA outputsC semantics testCasesUnary
115  
116  specBinary :: Op -> ((F,F) -> Expected F) -> TestSpec TestCase2 Output
117  specBinary op semantics = TestSpec circomFile (mainComponent op) inputsAB outputsC semantics testCasesBinary
118  
119  specBinarySmall :: Op -> ((F,F) -> Expected F) -> TestSpec TestCase2 Output
120  specBinarySmall op semantics = TestSpec circomFile (mainComponent op) inputsAB outputsC semantics testCasesBinarySmall
121  
122  --------------------------------------------------------------------------------
123  
124  input :: TestCase1 -> Inputs Name Integer
125  input x = Inputs $  toMapping "inp" x
126  
127  output :: Output -> Outputs Name Integer
128  output y = Outputs $ toMapping "out" y
129  
130  
131  semantics_toGoldi :: Int -> Expected Int
132  semantics_toGoldi k
133    | k < 0            = ShouldFail
134    | k >= fieldPrime  = ShouldFail
135    | otherwise        = Expecting k
136  
137  main_toGoldi :: MainComponent
138  main_toGoldi = MainComponent 
139    { _templateName   = "ToGoldilocksWrapper"
140    , _templateParams = []
141    , _publicInputs   = ["inp"]
142    }
143  
144  specToGoldi :: TestSpec TestCase1 Output
145  specToGoldi = TestSpec circomFile main_toGoldi input output semantics_toGoldi [-10..300] 
146  
147  --------------------------------------------------------------------------------
148  
149  semantics_isZero :: Int -> Expected Int
150  semantics_isZero k = Expecting (if k == 0 then 1 else 0)
151  
152  main_isZero :: MainComponent
153  main_isZero = MainComponent 
154    { _templateName   = "IsZero"
155    , _templateParams = []
156    , _publicInputs   = ["inp"]
157    }
158  
159  specIsZero :: TestSpec Int Int
160  specIsZero = TestSpec circomFile main_isZero input output semantics_isZero [-50..300] 
161  
162  --------------------------------------------------------------------------------
163