|
|
@ -3,6 +3,7 @@ package bulletproofs |
|
|
|
import ( |
|
|
|
"crypto/rand" |
|
|
|
"cwtch.im/tapir/primitives/core" |
|
|
|
"encoding/binary" |
|
|
|
"git.openprivacy.ca/openprivacy/libricochet-go/log" |
|
|
|
ristretto "github.com/gtank/ristretto255" |
|
|
|
"math/big" |
|
|
@ -18,7 +19,7 @@ type RangeProof struct { |
|
|
|
InnerProduct *ristretto.Scalar |
|
|
|
Mu *ristretto.Scalar |
|
|
|
IPP InnerProductProof |
|
|
|
V *ristretto.Element |
|
|
|
V []*ristretto.Element |
|
|
|
} |
|
|
|
|
|
|
|
// CommitmentsParams encapsulates the commitment parameters for a given range proof
|
|
|
@ -57,6 +58,14 @@ func GenerateRangeProof(value int32, c CommitmentsParams, transcript *core.Trans |
|
|
|
two.Add(one, one) |
|
|
|
two_n := core.PowerVector(two, c.max) |
|
|
|
|
|
|
|
transcript.AddToTranscript("dom-sep", []byte("rangeproof v1")) |
|
|
|
b := make([]byte, 8) |
|
|
|
binary.LittleEndian.PutUint64(b, uint64(c.max)) |
|
|
|
transcript.AddToTranscript("n", b) |
|
|
|
b = make([]byte, 8) |
|
|
|
binary.LittleEndian.PutUint64(b, 1) |
|
|
|
transcript.AddToTranscript("m", b) |
|
|
|
|
|
|
|
// Generate a prng to from this transcript and some external randomness
|
|
|
|
// We use this to generate the rest of our private scalars
|
|
|
|
// TODO: move to transcript
|
|
|
@ -73,11 +82,14 @@ func GenerateRangeProof(value int32, c CommitmentsParams, transcript *core.Trans |
|
|
|
alpha := prng.Next() |
|
|
|
|
|
|
|
vs := new(ristretto.Scalar) |
|
|
|
b := make([]byte, 32) |
|
|
|
b = make([]byte, 32) |
|
|
|
copy(b, big.NewInt(int64(value)).Bytes()) |
|
|
|
vs.Decode(b) |
|
|
|
|
|
|
|
V := core.MultiExp(core.ScalarVector{gamma, vs}, core.GeneratorVector{c.h, c.g}) |
|
|
|
|
|
|
|
transcript.AddElementToTranscript("V", V) |
|
|
|
|
|
|
|
A := core.MultiExp(append(aL.Join(aR), alpha), append(c.G.Join(c.H), c.h)) |
|
|
|
log.Debugf("vs: %v", vs) |
|
|
|
|
|
|
@ -91,8 +103,8 @@ func GenerateRangeProof(value int32, c CommitmentsParams, transcript *core.Trans |
|
|
|
|
|
|
|
S := core.MultiExp(append(Sl.Join(Sr), p), append(c.G.Join(c.H), c.h)) |
|
|
|
|
|
|
|
transcript.AddToTranscript("A", []byte(A.String())) |
|
|
|
transcript.AddToTranscript("S", []byte(S.String())) |
|
|
|
transcript.AddElementToTranscript("A", A) |
|
|
|
transcript.AddElementToTranscript("S", S) |
|
|
|
|
|
|
|
y := transcript.CommitToTranscriptScalar("y") |
|
|
|
z := transcript.CommitToTranscriptScalar("z") |
|
|
@ -116,8 +128,8 @@ func GenerateRangeProof(value int32, c CommitmentsParams, transcript *core.Trans |
|
|
|
T1 := core.MultiExp(core.ScalarVector{t1, tau1}, core.GeneratorVector{c.g, c.h}) |
|
|
|
T2 := core.MultiExp(core.ScalarVector{t2, tau2}, core.GeneratorVector{c.g, c.h}) |
|
|
|
|
|
|
|
transcript.AddToTranscript("T1", []byte(T1.String())) |
|
|
|
transcript.AddToTranscript("T2", []byte(T2.String())) |
|
|
|
transcript.AddElementToTranscript("T_1", T1) |
|
|
|
transcript.AddElementToTranscript("T_2", T2) |
|
|
|
|
|
|
|
x := transcript.CommitToTranscriptScalar("x") |
|
|
|
|
|
|
@ -147,18 +159,26 @@ func GenerateRangeProof(value int32, c CommitmentsParams, transcript *core.Trans |
|
|
|
P := core.MultiExp(l.Join(r), c.G.Join(H_)) |
|
|
|
log.Debugf("P: %v", P) |
|
|
|
|
|
|
|
uP := new(ristretto.Element).Add(P, new(ristretto.Element).ScalarMult(iplr, c.u)) |
|
|
|
log.Debugf("uP: %v", uP) |
|
|
|
ipp := ProveInnerProduct(l, r, c.u, new(ristretto.Element).Add(new(ristretto.Element).Zero(), uP), core.CopyVector(c.G), core.CopyVector(H_), transcript) |
|
|
|
mu := new(ristretto.Scalar) |
|
|
|
mu.Add(alpha, new(ristretto.Scalar).Multiply(p, x)) |
|
|
|
|
|
|
|
taux := new(ristretto.Scalar) |
|
|
|
taux.Multiply(tau2, new(ristretto.Scalar).Multiply(x, x)) |
|
|
|
taux.Add(taux, new(ristretto.Scalar).Multiply(tau1, x)) |
|
|
|
taux.Add(taux, new(ristretto.Scalar).Multiply(z2, gamma)) |
|
|
|
|
|
|
|
mu := new(ristretto.Scalar) |
|
|
|
mu.Add(alpha, new(ristretto.Scalar).Multiply(p, x)) |
|
|
|
return RangeProof{A, S, T1, T2, taux, iplr, mu, ipp, V}, gamma |
|
|
|
transcript.AddToTranscript("t_x", iplr.Encode([]byte{})) |
|
|
|
transcript.AddToTranscript("t_x_blinding", taux.Encode([]byte{})) |
|
|
|
transcript.AddToTranscript("e_blinding", mu.Encode([]byte{})) |
|
|
|
w := transcript.CommitToTranscriptScalar("w") |
|
|
|
|
|
|
|
U := new(ristretto.Element).ScalarMult(w, c.g) |
|
|
|
|
|
|
|
uP := new(ristretto.Element).Add(P, new(ristretto.Element).ScalarMult(iplr, U)) |
|
|
|
log.Debugf("uP: %v", uP) |
|
|
|
ipp := ProveInnerProduct(l, r, U, new(ristretto.Element).Add(new(ristretto.Element).Zero(), uP), core.CopyVector(c.G), core.CopyVector(H_), transcript) |
|
|
|
|
|
|
|
return RangeProof{A, S, T1, T2, taux, iplr, mu, ipp, []*ristretto.Element{V}}, gamma |
|
|
|
} |
|
|
|
|
|
|
|
// VerifyRangeProof returns true if the given proof passes all the checks for a given set of commitment parameters
|
|
|
@ -169,13 +189,32 @@ func VerifyRangeProof(proof RangeProof, c CommitmentsParams, transcript *core.Tr |
|
|
|
two.Add(one, one) |
|
|
|
two_n := core.PowerVector(two, c.max) |
|
|
|
|
|
|
|
transcript.AddToTranscript("A", []byte(proof.A.String())) |
|
|
|
transcript.AddToTranscript("S", []byte(proof.S.String())) |
|
|
|
transcript.AddToTranscript("dom-sep", []byte("rangeproof v1")) |
|
|
|
b := make([]byte, 8) |
|
|
|
binary.LittleEndian.PutUint64(b, uint64(c.max)) |
|
|
|
transcript.AddToTranscript("n", b) |
|
|
|
b = make([]byte, 8) |
|
|
|
binary.LittleEndian.PutUint64(b, 1) |
|
|
|
transcript.AddToTranscript("m", b) |
|
|
|
|
|
|
|
for _, v := range proof.V { |
|
|
|
transcript.AddElementToTranscript("V", v) |
|
|
|
} |
|
|
|
|
|
|
|
transcript.AddElementToTranscript("A", proof.A) |
|
|
|
transcript.AddElementToTranscript("S", proof.S) |
|
|
|
y := transcript.CommitToTranscriptScalar("y") |
|
|
|
z := transcript.CommitToTranscriptScalar("z") |
|
|
|
transcript.AddToTranscript("T1", []byte(proof.T1.String())) |
|
|
|
transcript.AddToTranscript("T2", []byte(proof.T2.String())) |
|
|
|
transcript.AddElementToTranscript("T_1", proof.T1) |
|
|
|
transcript.AddElementToTranscript("T_2", proof.T2) |
|
|
|
x := transcript.CommitToTranscriptScalar("x") |
|
|
|
|
|
|
|
transcript.AddToTranscript("t_x", proof.InnerProduct.Encode([]byte{})) |
|
|
|
transcript.AddToTranscript("t_x_blinding", proof.TauX.Encode([]byte{})) |
|
|
|
transcript.AddToTranscript("e_blinding", proof.Mu.Encode([]byte{})) |
|
|
|
log.Debugf("mu: %x", proof.Mu.Encode([]byte{})) |
|
|
|
|
|
|
|
log.Debugf("x: %x", x.Encode([]byte{})) |
|
|
|
y_n := core.PowerVector(y, c.max) |
|
|
|
// generate h'
|
|
|
|
H_ := make(core.GeneratorVector, c.max) |
|
|
@ -193,7 +232,7 @@ func VerifyRangeProof(proof RangeProof, c CommitmentsParams, transcript *core.Tr |
|
|
|
x2 := new(ristretto.Scalar) |
|
|
|
x2.Multiply(x, x) |
|
|
|
|
|
|
|
rhs := core.MultiExp(core.ScalarVector{z2, delta(y_n, z, c.max), x, x2}, core.GeneratorVector{proof.V, c.g, proof.T1, proof.T2}) |
|
|
|
rhs := core.MultiExp(core.ScalarVector{z2, delta(y_n, z, c.max), x, x2}, core.GeneratorVector(proof.V).Join(core.GeneratorVector{c.g, proof.T1, proof.T2})) |
|
|
|
log.Debugf("lhs: %v", lhs) |
|
|
|
log.Debugf("rhs: %v", rhs) |
|
|
|
log.Debugf("equal: %v", lhs.Equal(rhs)) |
|
|
@ -218,12 +257,15 @@ func VerifyRangeProof(proof RangeProof, c CommitmentsParams, transcript *core.Tr |
|
|
|
Pl := new(ristretto.Element).Subtract(Pr, new(ristretto.Element).ScalarMult(proof.Mu, c.h)) |
|
|
|
// check inner product
|
|
|
|
|
|
|
|
uP := new(ristretto.Element).Add(Pl, new(ristretto.Element).ScalarMult(proof.InnerProduct, c.u)) |
|
|
|
w := transcript.CommitToTranscriptScalar("w") |
|
|
|
U := new(ristretto.Element).ScalarMult(w, c.g) |
|
|
|
|
|
|
|
uP := new(ristretto.Element).Add(Pl, new(ristretto.Element).ScalarMult(proof.InnerProduct, U)) |
|
|
|
|
|
|
|
log.Debugf("P: %v", Pl) |
|
|
|
log.Debugf("uP: %v", uP) |
|
|
|
|
|
|
|
return Verify(proof.IPP, c.max, c.u, new(ristretto.Element).Add(new(ristretto.Element).Zero(), uP), core.CopyVector(c.G), core.CopyVector(H_), transcript) |
|
|
|
return Verify(proof.IPP, c.max, U, new(ristretto.Element).Add(new(ristretto.Element).Zero(), uP), core.CopyVector(c.G), core.CopyVector(H_), transcript) |
|
|
|
} |
|
|
|
return false |
|
|
|
} |
|
|
|