Skip to content

Commit 560acbd

Browse files
committed
Implement Sonic protocol
0 parents  commit 560acbd

17 files changed

+917
-0
lines changed

.gitignore

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
.stack-work/
2+
sonic.cabal
3+
*~
4+
TAGS

README.md

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
<p align="center">
2+
<a href="http://www.adjoint.io"><img src="https://www.adjoint.io/assets/img/[email protected]" width="250"/></a>
3+
</p>
4+
5+
Sonic
6+
-----
7+
8+
Zero-Knowledge SNARKs from Linear-Size Universal and Updatable Structured Reference Strings
9+
10+
License
11+
-------
12+
13+
```
14+
Copyright (c) 2018-2019 Adjoint Inc.
15+
16+
Permission is hereby granted, free of charge, to any person obtaining a copy
17+
of this software and associated documentation files (the "Software"), to deal
18+
in the Software without restriction, including without limitation the rights
19+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
20+
copies of the Software, and to permit persons to whom the Software is
21+
furnished to do so, subject to the following conditions:
22+
23+
The above copyright notice and this permission notice shall be included in all
24+
copies or substantial portions of the Software.
25+
26+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
27+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
28+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
29+
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
30+
DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
31+
OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE
32+
OR OTHER DEALINGS IN THE SOFTWARE.
33+
```

Setup.hs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
import Distribution.Simple
2+
main = defaultMain

package.yaml

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
name: sonic
2+
version: 0.1.0
3+
github: "adjoint-io/sonic"
4+
license: MIT
5+
maintainer: "Adjoint Inc ([email protected])"
6+
category: Cryptography
7+
8+
extra-source-files:
9+
- README.md
10+
- ChangeLog.md
11+
12+
description: Please see the README on GitHub at <https://github.com/adjoint-io/sonic#readme>
13+
14+
dependencies:
15+
- base
16+
- pairing
17+
- protolude
18+
- cryptonite
19+
- bulletproofs
20+
- wl-pprint-text
21+
- polynomial
22+
23+
default-extensions:
24+
- LambdaCase
25+
- RecordWildCards
26+
- OverloadedStrings
27+
- NoImplicitPrelude
28+
- FlexibleInstances
29+
- FlexibleContexts
30+
- ScopedTypeVariables
31+
- RankNTypes
32+
33+
library:
34+
source-dirs: src
35+
exposed-modules:
36+
- Sonic.CommitmentScheme
37+
- Sonic.Constraints
38+
- Sonic.Protocol
39+
- Sonic.SRS
40+
- Sonic.Signature
41+
- Sonic.Utils
42+
43+
44+
tests:
45+
sonic-test:
46+
main: Driver.hs
47+
source-dirs: test
48+
dependencies:
49+
- sonic
50+
- tasty
51+
- tasty-discover
52+
- tasty-hunit
53+
- tasty-quickcheck
54+
- QuickCheck

src/Sonic/CommitmentScheme.hs

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
{-# LANGUAGE RecordWildCards #-}
2+
module Sonic.CommitmentScheme where
3+
4+
import Protolude
5+
import Data.List ((!!))
6+
import Pairing.Group as Group (G1, G2, GT, g1, g2, expn)
7+
import Pairing.Fr as Fr (Fr, random, frInv, new)
8+
import Pairing.Pairing (reducedPairing)
9+
import Pairing.CyclicGroup (AsInteger(..))
10+
import Pairing.Point (gMul)
11+
12+
import qualified Math.Polynomial as Poly
13+
import Math.Polynomial.Laurent
14+
15+
import Sonic.Utils
16+
import Sonic.SRS
17+
18+
type Commitment = G1
19+
type Opening f = (f, G1)
20+
21+
commitPoly
22+
:: (AsInteger f, Num f, Eq f, Fractional f)
23+
=> SRS
24+
-> Integer
25+
-> f
26+
-> f
27+
-> Laurent f
28+
-> Commitment
29+
commitPoly SRS{..} maxm alpha x poly
30+
= if diff >= 0
31+
then g1 `expn` (alpha * (x ^ (d - maxm)) * (evalLaurent poly x))
32+
else g1 `expn` (alpha * (recip x ^ (abs (d - maxm))) * (evalLaurent poly x))
33+
where
34+
diff = fromInteger (d - maxm)
35+
36+
openPoly
37+
:: (AsInteger f, Num f, Eq f, Fractional f)
38+
=> SRS
39+
-> Commitment
40+
-> f
41+
-> f
42+
-> Laurent f
43+
-> Opening f
44+
openPoly srs _commitment x z fX
45+
= let fz = evalLaurent fX z
46+
wPoly = (fX - newLaurent 0 [fz]) `quotLaurent` (newLaurent 0 [-z, 1])
47+
w = g1 `expn` (evalLaurent wPoly x)
48+
in (fz, w)
49+
50+
pcV
51+
:: (AsInteger f, Num f, Eq f, Fractional f)
52+
=> SRS
53+
-> Integer
54+
-> Commitment
55+
-> f
56+
-> Opening f
57+
-> Bool
58+
pcV srs@SRS{..} maxm commitment z (v, w)
59+
= reducedPairing w (hPositiveAlphaX !! 1) -- when i = 1
60+
<>
61+
(reducedPairing ((g1 `expn` v) <> (w `expn` (negate z))) (hPositiveAlphaX !! 0)) -- when i = 0
62+
==
63+
(reducedPairing commitment hxi)
64+
where
65+
diff = fromInteger (-d + maxm)
66+
hxi = if diff >= 0
67+
then hPositiveX !! diff
68+
else hNegativeX !! (abs diff - 1)
69+

src/Sonic/Constraints.hs

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
{-# LANGUAGE RecordWildCards, FlexibleInstances, OverlappingInstances, RankNTypes #-}
2+
module Sonic.Constraints where
3+
4+
import Protolude hiding (head)
5+
import Data.List (zipWith4, head)
6+
import Pairing.CyclicGroup (CyclicGroup(..))
7+
import Pairing.Fr as Fr (Fr, new)
8+
import Bulletproofs.ArithmeticCircuit
9+
import Math.Polynomial (poly, Endianness(..))
10+
import Math.Polynomial.Laurent
11+
-- import Poly
12+
import Sonic.Utils
13+
14+
compressMulConstraints :: Assignment Fr -> Fr -> Fr
15+
compressMulConstraints Assignment{..} y = sum $ zipWith4 f aL aR aO [1..]
16+
where
17+
f ai bi ci i = (ai * bi - ci) * ((y ^ i) + y ^ (-i))
18+
19+
rPoly
20+
:: (Eq f, Num f)
21+
=> Assignment f
22+
-> Laurent (Laurent f)
23+
rPoly Assignment{..} =
24+
newLaurent (negate (2 * n)) (reorder $ newLaurent 0 [] : (concat $ zipWith4 f aL aR aO [1..]))
25+
where
26+
f ai bi ci i = [newLaurent i [ai], newLaurent (-i) [bi], newLaurent (-i - n) [ci]]
27+
reorder = sortBy (\l1 l2 -> compare (expLaurent l1) (expLaurent l2))
28+
n = length aL
29+
30+
sPoly
31+
:: (Eq f, Num f)
32+
=> GateWeights f
33+
-> Laurent (Laurent f)
34+
sPoly GateWeights{..}
35+
= addLaurent
36+
(addLaurent
37+
(newLaurent (negate n) (zipWith f (reverse wL) [1..]))
38+
(newLaurent 1 (zipWith f wR [1..]))
39+
)
40+
(newLaurent (n+1) (zipWith g wO [1..]))
41+
where
42+
f wi i = newLaurent (n+1) wi
43+
g wi i = addLaurent
44+
(addLaurent (newLaurent i [-1]) (newLaurent (-i) [-1]))
45+
(newLaurent (n+1) wi)
46+
n = length $ head wL
47+
-- ^ size(wL) = Q x n
48+
49+
tPoly
50+
:: (Eq f, Num f, Fractional f)
51+
=> Laurent (Laurent f)
52+
-> Laurent (Laurent f)
53+
-> Laurent f
54+
-> Laurent (Laurent f)
55+
tPoly rP sP kP
56+
-- r(X, 1) * (r(X,Y) + s(X, Y)) - k(Y)
57+
= addLaurent
58+
(multLaurent
59+
(convertToTwoVariateX $ evalOnY 1 rP)
60+
(addLaurent rP sP)
61+
)
62+
(convertToTwoVariateY $ negate kP)
63+
64+
polyK
65+
:: (Eq f, Num f)
66+
=> [f]
67+
-> Int
68+
-> Laurent f
69+
polyK k n = newLaurent (n+1) k

src/Sonic/Protocol.hs

Lines changed: 109 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,109 @@
1+
{-# LANGUAGE RecordWildCards #-}
2+
module Sonic.Protocol where
3+
4+
import Protolude hiding (head)
5+
import Data.List (head)
6+
import Crypto.Random (MonadRandom)
7+
import Crypto.Number.Generate (generateMax)
8+
import Pairing.Group as Group (G1, G2, GT, g1, g2, expn)
9+
import Pairing.CyclicGroup (AsInteger(..))
10+
import Bulletproofs.ArithmeticCircuit
11+
import Math.Polynomial.Laurent
12+
13+
-- import Text.Pretty.Simple
14+
import Text.PrettyPrint.Leijen.Text as PP (pretty, Pretty(..))
15+
-- import Poly
16+
import Sonic.SRS
17+
import Sonic.Constraints
18+
import Sonic.CommitmentScheme
19+
import Sonic.Signature
20+
import Sonic.Utils as Utils
21+
22+
data Proof f = Proof
23+
{ prR :: G1
24+
, prT :: G1
25+
, prA :: f
26+
, prWa :: G1
27+
, prB :: f
28+
, prWb :: G1
29+
, prWt :: G1
30+
, prS :: f
31+
, prHscProof :: HscProof f
32+
, prt' :: f
33+
}
34+
35+
prover
36+
:: (Num f, Eq f, Fractional f, AsInteger f, MonadRandom m)
37+
=> SRS
38+
-> Assignment f
39+
-> ArithCircuit f
40+
-> f
41+
-> f
42+
-> m (Proof f, f, f, [f])
43+
prover srs assignment@Assignment{..} arithCircuit@ArithCircuit{..} alpha x = do
44+
cns <- replicateM 4 Utils.random
45+
let rXY = rPoly assignment
46+
sumcXY = newLaurent
47+
(negate (2 * n + 4))
48+
(reverse $ zipWith (\cni i -> newLaurent (negate (2 * n + i)) [cni]) cns [1..])
49+
polyR' = addLaurent rXY sumcXY
50+
commitR = commitPoly srs (fromIntegral n) alpha x (evalOnY 1 polyR')
51+
-- zkV -> zkP: Send y to prover
52+
-- (Random oracle)
53+
y <- Utils.random
54+
let ky = polyK cs n
55+
let sP = sPoly weights
56+
let tP = tPoly polyR' sP ky
57+
let commitT = commitPoly srs (d srs) alpha x (evalOnY y tP)
58+
-- zkV -> zkP: Send y to prover
59+
-- (Random oracle)
60+
z <- Utils.random
61+
let (a, wa) = openPoly srs commitR x z (evalOnY 1 polyR')
62+
(b, wb) = openPoly srs commitR x (y * z) (evalOnY 1 polyR')
63+
(t', wt) = openPoly srs commitT x z (evalOnY y tP)
64+
65+
let s = evalLaurent (evalOnY y sP) z
66+
ys <- replicateM m Utils.random
67+
hscProof <- hscP srs weights alpha x ys
68+
69+
pure ( Proof
70+
{ prR = commitR
71+
, prT = commitT
72+
, prA = a
73+
, prWa = wa
74+
, prB = b
75+
, prWb = wb
76+
, prWt = wt
77+
, prS = s
78+
, prHscProof = hscProof
79+
}
80+
, y
81+
, z
82+
, ys
83+
)
84+
where
85+
n :: Int
86+
n = length aL
87+
m :: Int
88+
m = length . wL $ weights
89+
90+
verifier
91+
:: (Num f, Eq f, Fractional f, AsInteger f)
92+
=> SRS
93+
-> ArithCircuit f
94+
-> Proof f
95+
-> f
96+
-> f
97+
-> [f]
98+
-> Bool
99+
verifier srs@SRS{..} ArithCircuit{..} Proof{..} y z ys
100+
= let t = (prA * (prB + prS)) + (negate $ evalLaurent ky y)
101+
checks = [ hscV srs ys weights prHscProof
102+
, pcV srs (fromIntegral n) prR z (prA, prWa)
103+
, pcV srs (fromIntegral n) prR (y * z) (prB, prWb)
104+
, pcV srs d prT z (t, prWt)
105+
]
106+
in and checks
107+
where
108+
n = length . head . wL $ weights
109+
ky = polyK cs n

src/Sonic/SRS.hs

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
module Sonic.SRS where
2+
3+
import Protolude
4+
import Pairing.Group as Group (G1, G2, GT, g1, g2, expn)
5+
import Pairing.CyclicGroup (AsInteger(..))
6+
import Pairing.Fr as Fr (Fr, frInv)
7+
import Pairing.Pairing (reducedPairing)
8+
9+
data SRS = SRS
10+
{ d :: Integer
11+
, gNegativeX :: [G1]
12+
, gPositiveX :: [G1]
13+
, hNegativeX :: [G2]
14+
, hPositiveX :: [G2]
15+
, gNegativeAlphaX :: [G1]
16+
, gPositiveAlphaX :: [G1]
17+
, hNegativeAlphaX :: [G2]
18+
, hPositiveAlphaX :: [G2]
19+
, srsPairing :: GT
20+
}
21+
22+
new :: (Num f, Eq f, Fractional f, AsInteger f) => Integer -> f -> f -> SRS
23+
new d x alpha
24+
= let xInv = recip x
25+
in SRS
26+
{ d = d
27+
, gNegativeX = (\i -> expn g1 (xInv ^ i)) <$> [1..d]
28+
, gPositiveX = (\i -> expn g1 (x ^ i)) <$> [0..d]
29+
, hNegativeX = (\i -> expn g2 (xInv ^ i)) <$> [1..d]
30+
, hPositiveX = (\i -> expn g2 (x ^ i)) <$> [0..d]
31+
-- Notice that we omit g^alpha, i.e. when i=0
32+
, gNegativeAlphaX = (\i -> expn g1 (alpha * (xInv ^ i))) <$> [1..d]
33+
, gPositiveAlphaX = (\i -> expn g1 (alpha * (x ^ i))) <$> [1..d]
34+
, hNegativeAlphaX = (\i -> expn g2 (alpha * (xInv ^ i))) <$> [1..d]
35+
, hPositiveAlphaX = (\i -> expn g2 (alpha * (x ^ i))) <$> [0..d]
36+
, srsPairing = reducedPairing g1 (expn g2 alpha)
37+
}
38+

0 commit comments

Comments
 (0)