diff --git a/core/vm/contracts.go b/core/vm/contracts.go index b07cce9fc29b..1f03559e2a87 100644 --- a/core/vm/contracts.go +++ b/core/vm/contracts.go @@ -22,8 +22,6 @@ import ( "errors" "math/big" - "github.com/XinFinOrg/XDPoSChain/core/vm/privacy" - "github.com/XinFinOrg/XDPoSChain/common" "github.com/XinFinOrg/XDPoSChain/common/math" "github.com/XinFinOrg/XDPoSChain/crypto" @@ -63,8 +61,6 @@ var PrecompiledContractsByzantium = map[common.Address]PrecompiledContract{ common.BytesToAddress([]byte{6}): &bn256AddByzantium{}, common.BytesToAddress([]byte{7}): &bn256ScalarMulByzantium{}, common.BytesToAddress([]byte{8}): &bn256PairingByzantium{}, - common.BytesToAddress([]byte{30}): &ringSignatureVerifier{}, - common.BytesToAddress([]byte{40}): &bulletproofVerifier{}, common.BytesToAddress([]byte{41}): &XDCxLastPrice{}, common.BytesToAddress([]byte{42}): &XDCxEpochPrice{}, } @@ -81,8 +77,6 @@ var PrecompiledContractsIstanbul = map[common.Address]PrecompiledContract{ common.BytesToAddress([]byte{7}): &bn256ScalarMulIstanbul{}, common.BytesToAddress([]byte{8}): &bn256PairingIstanbul{}, common.BytesToAddress([]byte{9}): &blake2F{}, - common.BytesToAddress([]byte{30}): &ringSignatureVerifier{}, - common.BytesToAddress([]byte{40}): &bulletproofVerifier{}, common.BytesToAddress([]byte{41}): &XDCxLastPrice{}, common.BytesToAddress([]byte{42}): &XDCxEpochPrice{}, } @@ -426,42 +420,6 @@ func runBn256Pairing(input []byte) ([]byte, error) { return false32Byte, nil } -type ringSignatureVerifier struct{} -type bulletproofVerifier struct{} - -func (c *bulletproofVerifier) RequiredGas(input []byte) uint64 { - //the gas should depends on the ringsize - return 100000 -} - -func (c *ringSignatureVerifier) RequiredGas(input []byte) uint64 { - //the gas should depends on the ringsize - return 100000 -} - -func (c *ringSignatureVerifier) Run(proof []byte) ([]byte, error) { - der, err := privacy.Deserialize(proof) - if err != nil { - return []byte{}, errors.New("Fail to deserialize proof") - } - if !privacy.Verify(der, false) { - return []byte{}, errors.New("Fail to verify ring signature") - } - return []byte{}, nil -} - -func (c *bulletproofVerifier) Run(proof []byte) ([]byte, error) { - mrp := new(privacy.MultiRangeProof) - if mrp.Deserialize(proof) != nil { - return []byte{}, errors.New("failed to deserialize bulletproofs") - } - - if !privacy.MRPVerify(mrp) { - return []byte{}, errors.New("failed to verify bulletproof") - } - return []byte{}, nil -} - // bn256PairingIstanbul implements a pairing pre-compile for the bn256 curve // conforming to Istanbul consensus rules. type bn256PairingIstanbul struct{} @@ -488,6 +446,7 @@ func (c *bn256PairingByzantium) Run(input []byte) ([]byte, error) { return runBn256Pairing(input) } + type blake2F struct{} func (c *blake2F) RequiredGas(input []byte) uint64 { diff --git a/core/vm/privacy/bulletproof.go b/core/vm/privacy/bulletproof.go deleted file mode 100644 index f620d230b2ca..000000000000 --- a/core/vm/privacy/bulletproof.go +++ /dev/null @@ -1,1400 +0,0 @@ -package privacy - -import ( - "crypto/ecdsa" - "crypto/elliptic" - "crypto/rand" - "crypto/sha256" - "encoding/binary" - "errors" - "fmt" - "math" - "math/big" - "strconv" - - "github.com/XinFinOrg/XDPoSChain/common" - "github.com/XinFinOrg/XDPoSChain/log" - - "github.com/XinFinOrg/XDPoSChain/crypto" - "github.com/btcsuite/btcd/btcec" -) - -type Bulletproof struct { - proofData []byte -} - -var EC CryptoParams -var VecLength = 512 // support maximum 8 spending value, each 64 bit (gwei is unit) -var curve elliptic.Curve = crypto.S256() - -/* -Implementation of BulletProofs -*/ -type ECPoint struct { - X, Y *big.Int -} - -func (p *ECPoint) toECPubKey() *ecdsa.PublicKey { - return &ecdsa.PublicKey{curve, p.X, p.Y} -} - -func toECPoint(key *ecdsa.PublicKey) *ECPoint { - return &ECPoint{key.X, key.Y} -} - -// Equal returns true if points p (self) and p2 (arg) are the same. -func (p ECPoint) Equal(p2 ECPoint) bool { - if p.X.Cmp(p2.X) == 0 && p2.Y.Cmp(p2.Y) == 0 { - return true - } - return false -} - -// Mult multiplies point p by scalar s and returns the resulting point -func (p ECPoint) Mult(s *big.Int) ECPoint { - modS := new(big.Int).Mod(s, EC.N) - X, Y := EC.C.ScalarMult(p.X, p.Y, modS.Bytes()) - return ECPoint{X, Y} -} - -// Add adds points p and p2 and returns the resulting point -func (p ECPoint) Add(p2 ECPoint) ECPoint { - X, Y := EC.C.Add(p.X, p.Y, p2.X, p2.Y) - return ECPoint{X, Y} -} - -// Neg returns the additive inverse of point p -func (p ECPoint) Neg() ECPoint { - negY := new(big.Int).Neg(p.Y) - modValue := negY.Mod(negY, EC.C.Params().P) // mod P is fine here because we're describing a curve point - return ECPoint{p.X, modValue} -} - -type CryptoParams struct { - C elliptic.Curve // curve - KC *btcec.KoblitzCurve // curve - BPG []ECPoint // slice of gen 1 for BP - BPH []ECPoint // slice of gen 2 for BP - N *big.Int // scalar prime - U ECPoint // a point that is a fixed group element with an unknown discrete-log relative to g,h - V int // Vector length - G ECPoint // G value for commitments of a single value - H ECPoint // H value for commitments of a single value -} - -func (c CryptoParams) Zero() ECPoint { - return ECPoint{big.NewInt(0), big.NewInt(0)} -} - -func check(e error) { - if e != nil { - panic(e) - } -} - -/* -Vector Pedersen Commitment -Given an array of values, we commit the array with different generators -for each element and for each randomness. -*/ -func VectorPCommit(value []*big.Int) (ECPoint, []*big.Int) { - R := make([]*big.Int, EC.V) - - commitment := EC.Zero() - - for i := 0; i < EC.V; i++ { - r, err := rand.Int(rand.Reader, EC.N) - check(err) - - R[i] = r - - modValue := new(big.Int).Mod(value[i], EC.N) - - // mG, rH - lhsX, lhsY := EC.C.ScalarMult(EC.BPG[i].X, EC.BPG[i].Y, modValue.Bytes()) - rhsX, rhsY := EC.C.ScalarMult(EC.BPH[i].X, EC.BPH[i].Y, r.Bytes()) - - commitment = commitment.Add(ECPoint{lhsX, lhsY}).Add(ECPoint{rhsX, rhsY}) - } - - return commitment, R -} - -/* -Two Vector P Commit -Given an array of values, we commit the array with different generators -for each element and for each randomness. -*/ -func TwoVectorPCommit(a []*big.Int, b []*big.Int) ECPoint { - if len(a) != len(b) { - log.Debug("TwoVectorPCommit: Arrays not of the same length", "len(a)", len(a), "len(b)", len(b)) - } - - commitment := EC.Zero() - - for i := 0; i < EC.V; i++ { - commitment = commitment.Add(EC.BPG[i].Mult(a[i])).Add(EC.BPH[i].Mult(b[i])) - } - - return commitment -} - -/* -Vector Pedersen Commitment with Gens -Given an array of values, we commit the array with different generators -for each element and for each randomness. -We also pass in the Generators we want to use -*/ -func TwoVectorPCommitWithGens(G, H []ECPoint, a, b []*big.Int) ECPoint { - if len(G) != len(H) || len(G) != len(a) || len(a) != len(b) { - log.Debug("TwoVectorPCommitWithGens: Arrays not of the same length", "len(G)", len(G), "len(H)", len(H), "len(a)", len(a), "len(b)", len(b)) - } - - commitment := EC.Zero() - - for i := 0; i < len(G); i++ { - modA := new(big.Int).Mod(a[i], EC.N) - modB := new(big.Int).Mod(b[i], EC.N) - - commitment = commitment.Add(G[i].Mult(modA)).Add(H[i].Mult(modB)) - } - - return commitment -} - -// The length here always has to be a power of two -func InnerProduct(a []*big.Int, b []*big.Int) *big.Int { - if len(a) != len(b) { - log.Debug("InnerProduct: Arrays not of the same length", "len(a)", len(a), "len(b", len(b)) - } - - c := big.NewInt(0) - - for i := range a { - tmp1 := new(big.Int).Mul(a[i], b[i]) - c = new(big.Int).Add(c, new(big.Int).Mod(tmp1, EC.N)) - } - - return new(big.Int).Mod(c, EC.N) -} - -func VectorAdd(v []*big.Int, w []*big.Int) []*big.Int { - if len(v) != len(w) { - log.Debug("VectorAdd: Arrays not of the same length", "len(v)", len(v), "len(w)", len(w)) - } - result := make([]*big.Int, len(v)) - - for i := range v { - result[i] = new(big.Int).Mod(new(big.Int).Add(v[i], w[i]), EC.N) - } - - return result -} - -func VectorHadamard(v, w []*big.Int) []*big.Int { - if len(v) != len(w) { - log.Debug("VectorHadamard: Arrays not of the same length", "len(v)", len(v), "len(w)", len(w)) - } - - result := make([]*big.Int, len(v)) - - for i := range v { - result[i] = new(big.Int).Mod(new(big.Int).Mul(v[i], w[i]), EC.N) - } - - return result -} - -func VectorAddScalar(v []*big.Int, s *big.Int) []*big.Int { - result := make([]*big.Int, len(v)) - - for i := range v { - result[i] = new(big.Int).Mod(new(big.Int).Add(v[i], s), EC.N) - } - - return result -} - -func ScalarVectorMul(v []*big.Int, s *big.Int) []*big.Int { - result := make([]*big.Int, len(v)) - - for i := range v { - result[i] = new(big.Int).Mod(new(big.Int).Mul(v[i], s), EC.N) - } - - return result -} - -func HashPointsToBytes(points []ECPoint) []byte { - input := []byte{} - - for index := 0; index < len(points); index++ { - pointInByte := append(PadTo32Bytes(points[index].X.Bytes()), PadTo32Bytes(points[index].Y.Bytes())...) - input = append(input, pointInByte...) - } - - return crypto.Keccak256(input) -} - -/* -InnerProd Proof -This stores the argument values -*/ -type InnerProdArg struct { - L []ECPoint - R []ECPoint - A *big.Int - B *big.Int - - Challenges []*big.Int -} - -func GenerateNewParams(G, H []ECPoint, x *big.Int, L, R, P ECPoint) ([]ECPoint, []ECPoint, ECPoint) { - nprime := len(G) / 2 - - Gprime := make([]ECPoint, nprime) - Hprime := make([]ECPoint, nprime) - - xinv := new(big.Int).ModInverse(x, EC.N) - - // Gprime = xinv * G[:nprime] + x*G[nprime:] - // Hprime = x * H[:nprime] + xinv*H[nprime:] - - for i := range Gprime { - //fmt.Printf("i: %d && i+nprime: %d\n", i, i+nprime) - Gprime[i] = G[i].Mult(xinv).Add(G[i+nprime].Mult(x)) - Hprime[i] = H[i].Mult(x).Add(H[i+nprime].Mult(xinv)) - } - - x2 := new(big.Int).Mod(new(big.Int).Mul(x, x), EC.N) - xinv2 := new(big.Int).ModInverse(x2, EC.N) - - Pprime := L.Mult(x2).Add(P).Add(R.Mult(xinv2)) // x^2 * L + P + xinv^2 * R - - return Gprime, Hprime, Pprime -} - -/* - Inner Product Argument - -Proves that =c -This is a building block for BulletProofs -*/ -func InnerProductProveSub(proof InnerProdArg, G, H []ECPoint, a []*big.Int, b []*big.Int, u ECPoint, P ECPoint) InnerProdArg { - if len(a) == 1 { - // Prover sends a & b - proof.A = a[0] - proof.B = b[0] - return proof - } - - curIt := int(math.Log2(float64(len(a)))) - 1 - - nprime := len(a) / 2 - cl := InnerProduct(a[:nprime], b[nprime:]) // either this line - cr := InnerProduct(a[nprime:], b[:nprime]) // or this line - L := TwoVectorPCommitWithGens(G[nprime:], H[:nprime], a[:nprime], b[nprime:]).Add(u.Mult(cl)) - R := TwoVectorPCommitWithGens(G[:nprime], H[nprime:], a[nprime:], b[:nprime]).Add(u.Mult(cr)) - - proof.L[curIt] = L - proof.R[curIt] = R - - // prover sends L & R and gets a challenge - // LvalInBytes := append(PadTo32Bytes(L.X.Bytes()), PadTo32Bytes(L.Y.Bytes())...) - // RvalInBytes := append(PadTo32Bytes(R.X.Bytes()), PadTo32Bytes(R.Y.Bytes())...) - // input := append(LvalInBytes, RvalInBytes...) - // s256 := crypto.Keccak256(input) - s256 := HashPointsToBytes([]ECPoint{L, R}) - - x := new(big.Int).SetBytes(s256[:]) - - proof.Challenges[curIt] = x - - Gprime, Hprime, Pprime := GenerateNewParams(G, H, x, L, R, P) - - xinv := new(big.Int).ModInverse(x, EC.N) - - // or these two lines - aprime := VectorAdd( - ScalarVectorMul(a[:nprime], x), - ScalarVectorMul(a[nprime:], xinv)) - bprime := VectorAdd( - ScalarVectorMul(b[:nprime], xinv), - ScalarVectorMul(b[nprime:], x)) - - return InnerProductProveSub(proof, Gprime, Hprime, aprime, bprime, u, Pprime) -} - -// rpresult.IPP = InnerProductProve(left, right, that, P, EC.U, EC.BPG, HPrime) -func InnerProductProve(a []*big.Int, b []*big.Int, c *big.Int, P, U ECPoint, G, H []ECPoint) InnerProdArg { - loglen := int(math.Log2(float64(len(a)))) - - challenges := make([]*big.Int, loglen+1) - Lvals := make([]ECPoint, loglen) - Rvals := make([]ECPoint, loglen) - - runningProof := InnerProdArg{ - Lvals, - Rvals, - big.NewInt(0), - big.NewInt(0), - challenges} - - // randomly generate an x value from public data - // input := append(PadTo32Bytes(P.X.Bytes()), PadTo32Bytes(P.Y.Bytes())...) - // x := crypto.Keccak256(input) - x := HashPointsToBytes([]ECPoint{P}) - - runningProof.Challenges[loglen] = new(big.Int).SetBytes(x[:]) - - Pprime := P.Add(U.Mult(new(big.Int).Mul(new(big.Int).SetBytes(x[:]), c))) - - ux := U.Mult(new(big.Int).SetBytes(x[:])) - //fmt.Printf("Prover Pprime value to run sub off of: %s\n", Pprime) - - return InnerProductProveSub(runningProof, G, H, a, b, ux, Pprime) -} - -/* - Inner Product Verify - -Given a inner product proof, verifies the correctness of the proof -Since we're using the Fiat-Shamir transform, we need to verify all x hash computations, -all g' and h' computations -P : the Pedersen commitment we are verifying is a commitment to the innner product -ipp : the proof -*/ -func InnerProductVerify(c *big.Int, P, U ECPoint, G, H []ECPoint, ipp InnerProdArg) bool { - //fmt.Println("Verifying Inner Product Argument") - //fmt.Printf("Commitment Value: %s \n", P) - // s1 := sha256.Sum256([]byte(P.X.String() + P.Y.String())) - - // input := append(PadTo32Bytes(P.X.Bytes()), PadTo32Bytes(P.Y.Bytes())...) - // s1 := crypto.Keccak256(input) - s1 := HashPointsToBytes([]ECPoint{P}) - - chal1 := new(big.Int).SetBytes(s1[:]) - ux := U.Mult(chal1) - curIt := len(ipp.Challenges) - 1 - - if ipp.Challenges[curIt].Cmp(chal1) != 0 { - log.Info("Initial Challenge Failed") - return false - } - - curIt -= 1 - - Gprime := G - Hprime := H - Pprime := P.Add(ux.Mult(c)) // line 6 from protocol 1 - //fmt.Printf("New Commitment value with u^cx: %s \n", Pprime) - - for curIt >= 0 { - Lval := ipp.L[curIt] - Rval := ipp.R[curIt] - - // prover sends L & R and gets a challenge - // s256 := sha256.Sum256([]byte( - // Lval.X.String() + Lval.Y.String() + - // Rval.X.String() + Rval.Y.String())) - // LvalInBytes := append(PadTo32Bytes(Lval.X.Bytes()), PadTo32Bytes(Lval.Y.Bytes())...) - // RvalInBytes := append(PadTo32Bytes(Rval.X.Bytes()), PadTo32Bytes(Rval.Y.Bytes())...) - // input := append(LvalInBytes, RvalInBytes...) - // s256 := crypto.Keccak256(input) - s256 := HashPointsToBytes([]ECPoint{Lval, Rval}) - - chal2 := new(big.Int).SetBytes(s256[:]) - - if ipp.Challenges[curIt].Cmp(chal2) != 0 { - log.Info("Challenge verification failed", "index", strconv.Itoa(curIt)) - return false - } - - Gprime, Hprime, Pprime = GenerateNewParams(Gprime, Hprime, chal2, Lval, Rval, Pprime) - curIt -= 1 - } - ccalc := new(big.Int).Mod(new(big.Int).Mul(ipp.A, ipp.B), EC.N) - - Pcalc1 := Gprime[0].Mult(ipp.A) - Pcalc2 := Hprime[0].Mult(ipp.B) - Pcalc3 := ux.Mult(ccalc) - Pcalc := Pcalc1.Add(Pcalc2).Add(Pcalc3) - - return Pprime.Equal(Pcalc) -} - -/* Inner Product Verify Fast -Given a inner product proof, verifies the correctness of the proof. Does the same as above except -we replace n separate exponentiations with a single multi-exponentiation. -*/ - -func InnerProductVerifyFast(c *big.Int, P, U ECPoint, G, H []ECPoint, ipp InnerProdArg) bool { - // input := append(PadTo32Bytes(P.X.Bytes()), PadTo32Bytes(P.Y.Bytes())...) - // s1 := crypto.Keccak256(input) - s1 := HashPointsToBytes([]ECPoint{P}) - - chal1 := new(big.Int).SetBytes(s1[:]) - ux := U.Mult(chal1) - curIt := len(ipp.Challenges) - 1 - - // check all challenges - if ipp.Challenges[curIt].Cmp(chal1) != 0 { - log.Debug("Initial Challenge Failed") - return false - } - - for j := curIt - 1; j >= 0; j-- { - Lval := ipp.L[j] - Rval := ipp.R[j] - - // prover sends L & R and gets a challenge - // LvalInBytes := append(PadTo32Bytes(Lval.X.Bytes()), PadTo32Bytes(Lval.Y.Bytes())...) - // RvalInBytes := append(PadTo32Bytes(Rval.X.Bytes()), PadTo32Bytes(Rval.Y.Bytes())...) - // input := append(LvalInBytes, RvalInBytes...) - // s256 := crypto.Keccak256(input) - s256 := HashPointsToBytes([]ECPoint{Lval, Rval}) - - chal2 := new(big.Int).SetBytes(s256[:]) - - if ipp.Challenges[j].Cmp(chal2) != 0 { - log.Debug("Challenge verification failed", "index", strconv.Itoa(j)) - return false - } - } - // begin computing - - curIt -= 1 - Pprime := P.Add(ux.Mult(c)) // line 6 from protocol 1 - - tmp1 := EC.Zero() - for j := curIt; j >= 0; j-- { - x2 := new(big.Int).Exp(ipp.Challenges[j], big.NewInt(2), EC.N) - x2i := new(big.Int).ModInverse(x2, EC.N) - //fmt.Println(tmp1) - tmp1 = ipp.L[j].Mult(x2).Add(ipp.R[j].Mult(x2i)).Add(tmp1) - //fmt.Println(tmp1) - } - rhs := Pprime.Add(tmp1) - //rhs=P+c*ux + L*xw+R*x2i 公式29 - - sScalars := make([]*big.Int, EC.V) - invsScalars := make([]*big.Int, EC.V) - - for i := 0; i < EC.V; i++ { - si := big.NewInt(1) - for j := curIt; j >= 0; j-- { - // original challenge if the jth bit of i is 1, inverse challenge otherwise - chal := ipp.Challenges[j] - if big.NewInt(int64(i)).Bit(j) == 0 { - chal = new(big.Int).ModInverse(chal, EC.N) - } - // fmt.Printf("Challenge raised to value: %d\n", chal) - si = new(big.Int).Mod(new(big.Int).Mul(si, chal), EC.N) - } - //fmt.Printf("Si value: %d\n", si) - sScalars[i] = si - invsScalars[i] = new(big.Int).ModInverse(si, EC.N) - } - - ccalc := new(big.Int).Mod(new(big.Int).Mul(ipp.A, ipp.B), EC.N) - lhs := TwoVectorPCommitWithGens(G, H, ScalarVectorMul(sScalars, ipp.A), ScalarVectorMul(invsScalars, ipp.B)).Add(ux.Mult(ccalc)) - - if !rhs.Equal(lhs) { - log.Info("IPVerify - Final Commitment checking failed") - return false - } - - return true -} - -// from here: https://play.golang.org/p/zciRZvD0Gr with a fix -func PadLeft(str, pad string, l int) string { - strCopy := str - for len(strCopy) < l { - strCopy = pad + strCopy - } - - return strCopy -} - -func STRNot(str string) string { - result := "" - - for _, i := range str { - if i == '0' { - result += "1" - } else { - result += "0" - } - } - return result -} - -func StrToBigIntArray(str string) []*big.Int { - result := make([]*big.Int, len(str)) - - for i := range str { - t, success := new(big.Int).SetString(string(str[i]), 10) - if success { - result[i] = t - } - } - - return result -} - -func reverse(l []*big.Int) []*big.Int { - result := make([]*big.Int, len(l)) - - for i := range l { - result[i] = l[len(l)-i-1] - } - - return result -} - -func PowerVector(l int, base *big.Int) []*big.Int { - result := make([]*big.Int, l) - - for i := 0; i < l; i++ { - result[i] = new(big.Int).Exp(base, big.NewInt(int64(i)), EC.N) - } - - return result -} - -func RandVector(l int) []*big.Int { - result := make([]*big.Int, l) - - for i := 0; i < l; i++ { - x, err := rand.Int(rand.Reader, EC.N) - check(err) - result[i] = x - } - - return result -} - -func VectorSum(y []*big.Int) *big.Int { - result := big.NewInt(0) - - for _, j := range y { - result = new(big.Int).Mod(new(big.Int).Add(result, j), EC.N) - } - - return result -} - -type RangeProof struct { - Comm ECPoint - A ECPoint - S ECPoint - T1 ECPoint - T2 ECPoint - Tau *big.Int - Th *big.Int - Mu *big.Int - IPP InnerProdArg - - // challenges - Cy *big.Int - Cz *big.Int - Cx *big.Int -} - -/* -Delta is a helper function that is used in the range proof -\delta(y, z) = (z-z^2)<1^n, y^n> - z^3<1^n, 2^n> -*/ - -func Delta(y []*big.Int, z *big.Int) *big.Int { - result := big.NewInt(0) - - // (z-z^2)<1^n, y^n> - z2 := new(big.Int).Mod(new(big.Int).Mul(z, z), EC.N) - t1 := new(big.Int).Mod(new(big.Int).Sub(z, z2), EC.N) - t2 := new(big.Int).Mod(new(big.Int).Mul(t1, VectorSum(y)), EC.N) - - // z^3<1^n, 2^n> - z3 := new(big.Int).Mod(new(big.Int).Mul(z2, z), EC.N) - po2sum := new(big.Int).Sub(new(big.Int).Exp(big.NewInt(2), big.NewInt(int64(EC.V)), EC.N), big.NewInt(1)) - t3 := new(big.Int).Mod(new(big.Int).Mul(z3, po2sum), EC.N) - - result = new(big.Int).Mod(new(big.Int).Sub(t2, t3), EC.N) - - return result -} - -// Calculates (aL - z*1^n) + sL*x -func CalculateL(aL, sL []*big.Int, z, x *big.Int) []*big.Int { - result := make([]*big.Int, len(aL)) - - tmp1 := VectorAddScalar(aL, new(big.Int).Neg(z)) - tmp2 := ScalarVectorMul(sL, x) - - result = VectorAdd(tmp1, tmp2) - - return result -} - -func CalculateR(aR, sR, y, po2 []*big.Int, z, x *big.Int) []*big.Int { - if len(aR) != len(sR) || len(aR) != len(y) || len(y) != len(po2) { - log.Info("CalculateR: Arrays not of the same length") - } - - result := make([]*big.Int, len(aR)) - - z2 := new(big.Int).Exp(z, big.NewInt(2), EC.N) - tmp11 := VectorAddScalar(aR, z) - tmp12 := ScalarVectorMul(sR, x) - tmp1 := VectorHadamard(y, VectorAdd(tmp11, tmp12)) - tmp2 := ScalarVectorMul(po2, z2) - - result = VectorAdd(tmp1, tmp2) - - return result -} - -// Calculates (aL - z*1^n) + sL*x -func CalculateLMRP(aL, sL []*big.Int, z, x *big.Int) []*big.Int { - result := make([]*big.Int, len(aL)) - - tmp1 := VectorAddScalar(aL, new(big.Int).Neg(z)) - tmp2 := ScalarVectorMul(sL, x) - - result = VectorAdd(tmp1, tmp2) - - return result -} - -func CalculateRMRP(aR, sR, y, zTimesTwo []*big.Int, z, x *big.Int) []*big.Int { - if len(aR) != len(sR) || len(aR) != len(y) || len(y) != len(zTimesTwo) { - log.Info("CalculateRMRP: Arrays not of the same length") - } - - result := make([]*big.Int, len(aR)) - - tmp11 := VectorAddScalar(aR, z) - tmp12 := ScalarVectorMul(sR, x) - tmp1 := VectorHadamard(y, VectorAdd(tmp11, tmp12)) - - result = VectorAdd(tmp1, zTimesTwo) - - return result -} - -/* -DeltaMRP is a helper function that is used in the multi range proof -\delta(y, z) = (z-z^2)<1^n, y^n> - \sum_j z^3+j<1^n, 2^n> -*/ - -func DeltaMRP(y []*big.Int, z *big.Int, m int) *big.Int { - result := big.NewInt(0) - - // (z-z^2)<1^n, y^n> - z2 := new(big.Int).Mod(new(big.Int).Mul(z, z), EC.N) - t1 := new(big.Int).Mod(new(big.Int).Sub(z, z2), EC.N) - t2 := new(big.Int).Mod(new(big.Int).Mul(t1, VectorSum(y)), EC.N) - - // \sum_j z^3+j<1^n, 2^n> - // <1^n, 2^n> = 2^n - 1 - po2sum := new(big.Int).Sub( - new(big.Int).Exp( - big.NewInt(2), big.NewInt(int64(EC.V/m)), EC.N), big.NewInt(1)) - t3 := big.NewInt(0) - - for j := 0; j < m; j++ { - zp := new(big.Int).Exp(z, big.NewInt(3+int64(j)), EC.N) - tmp1 := new(big.Int).Mod(new(big.Int).Mul(zp, po2sum), EC.N) - t3 = new(big.Int).Mod(new(big.Int).Add(t3, tmp1), EC.N) - } - - result = new(big.Int).Mod(new(big.Int).Sub(t2, t3), EC.N) - - return result -} - -type MultiRangeProof struct { - Comms []ECPoint - A ECPoint - S ECPoint - T1 ECPoint - T2 ECPoint - Tau *big.Int - Th *big.Int - Mu *big.Int - IPP InnerProdArg - - // challenges - Cy *big.Int - Cz *big.Int - Cx *big.Int -} - -func serializePointArray(pa []ECPoint, serializeSize bool) []byte { - ret := []byte{} - - if serializeSize { - size := make([]byte, 4) - binary.BigEndian.PutUint32(size, uint32(len(pa))) - ret = append(ret, size[:]...) - } - - for i := 0; i < len(pa); i++ { - sp := SerializeCompressed(pa[i].toECPubKey()) - ret = append(ret, sp[:]...) - } - return ret -} - -func deserializePointArray(input []byte, numPoint uint32) ([]ECPoint, error) { - if len(input) <= 4 { - return []ECPoint{}, errors.New("input data invalid") - } - numPointSize := uint32(0) - if numPoint == 0 { - numPointSize = 4 - numPoint = binary.BigEndian.Uint32(input[0:4]) - } - if uint32(len(input)) < (numPointSize + 33*numPoint) { - return []ECPoint{}, errors.New("input data too short") - } - ret := make([]ECPoint, numPoint) - offset := numPointSize - for i := 0; i < int(numPoint); i++ { - compressed := DeserializeCompressed(curve, input[offset:offset+33]) - if compressed == nil { - return ret, errors.New("invalid input data") - } - ret[i] = *toECPoint(compressed) - offset += 33 - } - return ret, nil -} - -func (ipp *InnerProdArg) Serialize() []byte { - proof := []byte{} - - spa := serializePointArray(ipp.L, false) - proof = append(proof, spa[:]...) - - spa = serializePointArray(ipp.R, false) - proof = append(proof, spa[:]...) - - if ipp.A.Cmp(big.NewInt(0)) < 0 { - ipp.A.Mod(ipp.A, EC.N) - } - sp := PadTo32Bytes(ipp.A.Bytes()) - proof = append(proof, sp[:]...) - - sp = PadTo32Bytes(ipp.B.Bytes()) - proof = append(proof, sp[:]...) - - for i := 0; i < len(ipp.Challenges); i++ { - sp = PadTo32Bytes(ipp.Challenges[i].Bytes()) - proof = append(proof, sp[:]...) - } - - return proof -} - -func (ipp *InnerProdArg) Deserialize(proof []byte, numChallenges int) error { - if len(proof) <= 12 { - return errors.New("proof data too short") - } - offset := 0 - L, err := deserializePointArray(proof[:], uint32(numChallenges)-1) - if err != nil { - return err - } - ipp.L = append(ipp.L, L[:]...) - offset += len(L) * 33 - - R, err := deserializePointArray(proof[offset:], uint32(numChallenges)-1) - if err != nil { - return err - } - - ipp.R = append(ipp.R, R[:]...) - offset += len(R) * 33 - - if len(proof) <= offset+64+4 { - return errors.New("proof data too short") - } - - ipp.A = new(big.Int).SetBytes(proof[offset : offset+32]) - offset += 32 - ipp.B = new(big.Int).SetBytes(proof[offset : offset+32]) - offset += 32 - - if len(proof) <= (offset + 32*numChallenges) { - return errors.New("input data too short") - } - for i := 0; i < numChallenges; i++ { - ipp.Challenges = append(ipp.Challenges, new(big.Int).SetBytes(proof[offset:offset+32])) - offset += 32 - } - return nil -} - -func (mrp *MultiRangeProof) Serialize() []byte { - proof := []byte{} - - serializedPA := serializePointArray(mrp.Comms, true) - proof = append(proof, serializedPA[:]...) - - sp := SerializeCompressed(mrp.A.toECPubKey()) - proof = append(proof, sp[:]...) - - sp = SerializeCompressed(mrp.S.toECPubKey()) - proof = append(proof, sp[:]...) - - sp = SerializeCompressed(mrp.T1.toECPubKey()) - proof = append(proof, sp[:]...) - - sp = SerializeCompressed(mrp.T2.toECPubKey()) - proof = append(proof, sp[:]...) - - //Tau, Th, Mu - sp = PadTo32Bytes(mrp.Tau.Bytes()) - proof = append(proof, sp[:]...) - - if mrp.Th.Cmp(big.NewInt(0)) < 0 { - mrp.Th.Mod(mrp.Th, EC.N) - } - sp = PadTo32Bytes(mrp.Th.Bytes()) - proof = append(proof, sp[:]...) - - sp = PadTo32Bytes(mrp.Mu.Bytes()) - proof = append(proof, sp[:]...) - - //challenges - sp = mrp.IPP.Serialize() - proof = append(proof, sp[:]...) - - //challenges - sp = PadTo32Bytes(mrp.Cy.Bytes()) - proof = append(proof, sp[:]...) - - sp = PadTo32Bytes(mrp.Cz.Bytes()) - proof = append(proof, sp[:]...) - - sp = PadTo32Bytes(mrp.Cx.Bytes()) - proof = append(proof, sp[:]...) - - return proof -} - -func (mrp *MultiRangeProof) Deserialize(proof []byte) error { - Cs, err := deserializePointArray(proof[:], 0) - if err != nil { - return err - } - mrp.Comms = append(mrp.Comms, Cs[:]...) - - offset := 4 + len(Cs)*33 - - if len(proof) <= offset+4+4*33+6*32 { - return errors.New("invalid input data") - } - compressed := DeserializeCompressed(curve, proof[offset:offset+33]) - if compressed == nil { - return errors.New("failed to decode A") - } - offset += 33 - mrp.A = *toECPoint(compressed) - - compressed = DeserializeCompressed(curve, proof[offset:offset+33]) - if compressed == nil { - return errors.New("failed to decode S") - } - offset += 33 - mrp.S = *toECPoint(compressed) - - compressed = DeserializeCompressed(curve, proof[offset:offset+33]) - if compressed == nil { - return errors.New("failed to decode T2") - } - offset += 33 - mrp.T1 = *toECPoint(compressed) - - compressed = DeserializeCompressed(curve, proof[offset:offset+33]) - if compressed == nil { - return errors.New("failed to decode T2") - } - offset += 33 - mrp.T2 = *toECPoint(compressed) - - mrp.Tau = new(big.Int).SetBytes(proof[offset : offset+32]) - offset += 32 - - mrp.Th = new(big.Int).SetBytes(proof[offset : offset+32]) - offset += 32 - - mrp.Mu = new(big.Int).SetBytes(proof[offset : offset+32]) - offset += 32 - - numChallenges := int(math.Log2(float64(len(mrp.Comms)*bitsPerValue))) + 1 - mrp.IPP.Deserialize(proof[offset:], numChallenges) - offset += len(mrp.IPP.L)*33 + len(mrp.IPP.R)*33 + len(mrp.IPP.Challenges)*32 + 2*32 - - mrp.Cy = new(big.Int).SetBytes(proof[offset : offset+32]) - offset += 32 - - mrp.Cz = new(big.Int).SetBytes(proof[offset : offset+32]) - offset += 32 - - mrp.Cx = new(big.Int).SetBytes(proof[offset : offset+32]) - offset += 32 - - return nil -} - -func pedersenCommitment(gamma *big.Int, value *big.Int) ECPoint { - return EC.G.Mult(value).Add(EC.H.Mult(gamma)) -} - -var MAX_64_BITS = new(big.Int).SetUint64(0xFFFFFFFFFFFFFFFF) - -/* -MultiRangeProof Prove -Takes in a list of values and provides an aggregate -range proof for all the values. -changes: - - all values are concatenated - r(x) is computed differently - tau_x calculation is different - delta calculation is different - -{(g, h \in G, \textbf{V} \in G^m ; \textbf{v, \gamma} \in Z_p^m) : - - V_j = h^{\gamma_j}g^{v_j} \wedge v_j \in [0, 2^n - 1] \forall j \in [1, m]} -*/ -var bitsPerValue = 64 - -func MRPProve(values []*big.Int) (MultiRangeProof, error) { - var acceptedInputNumber bool - - MRPResult := MultiRangeProof{} - - m := len(values) - - if m == 1 || m == 2 || m == 4 || m == 8 { - acceptedInputNumber = true - } - - if !acceptedInputNumber { - return MultiRangeProof{}, errors.New("Value number is not supported - just 1, 2, 4, 8") - } - - EC = genECPrimeGroupKey(m * bitsPerValue) - - // we concatenate the binary representation of the values - - PowerOfTwos := PowerVector(bitsPerValue, big.NewInt(2)) - - Comms := make([]ECPoint, m) - gammas := make([]*big.Int, m) - aLConcat := make([]*big.Int, EC.V) - aRConcat := make([]*big.Int, EC.V) - - for j := range values { - v := values[j] - if v.Cmp(big.NewInt(0)) == -1 { - return MultiRangeProof{}, errors.New("Value is below range! Not proving") - } - - if v.Cmp(MAX_64_BITS) == 1 { - return MultiRangeProof{}, errors.New("Value is above range! Not proving") - } - - if v.Cmp(new(big.Int).Exp(big.NewInt(2), big.NewInt(int64(bitsPerValue)), EC.N)) == 1 { - return MultiRangeProof{}, errors.New("Value is above range! Not proving") - } - - gamma, err := rand.Int(rand.Reader, EC.N) - - check(err) - Comms[j] = pedersenCommitment(gamma, v) - gammas[j] = gamma - - // break up v into its bitwise representation - aL := reverse(StrToBigIntArray(PadLeft(fmt.Sprintf("%b", v), "0", bitsPerValue))) - aR := VectorAddScalar(aL, big.NewInt(-1)) - - for i := range aR { - aLConcat[bitsPerValue*j+i] = aL[i] - aRConcat[bitsPerValue*j+i] = aR[i] - } - } - - //compare aL, aR - MRPResult.Comms = Comms - - alpha, err := rand.Int(rand.Reader, EC.N) - check(err) - - A := TwoVectorPCommitWithGens(EC.BPG, EC.BPH, aLConcat, aRConcat).Add(EC.H.Mult(alpha)) - MRPResult.A = A - - // fmt.Println("Ec.V %+v", EC.V) - sL := RandVector(EC.V) - sR := RandVector(EC.V) - - rho, err := rand.Int(rand.Reader, EC.N) - check(err) - - S := TwoVectorPCommitWithGens(EC.BPG, EC.BPH, sL, sR).Add(EC.H.Mult(rho)) - MRPResult.S = S - - // input := append(PadTo32Bytes(A.X.Bytes()), PadTo32Bytes(A.Y.Bytes())...) - // chal1s256 := crypto.Keccak256(input) - chal1s256 := HashPointsToBytes(append(Comms, A)) - - // chal1s256 := sha256.Sum256([]byte(A.X.String() + A.Y.String())) - cy := new(big.Int).SetBytes(chal1s256[:]) - MRPResult.Cy = cy - - // input = append(PadTo32Bytes(S.X.Bytes()), PadTo32Bytes(S.Y.Bytes())...) - // chal2s256 := crypto.Keccak256(input) - chal2s256 := HashPointsToBytes(append(Comms, A, S)) - - // chal2s256 := sha256.Sum256([]byte(S.X.String() + S.Y.String())) - cz := new(big.Int).SetBytes(chal2s256[:]) - MRPResult.Cz = cz - - zPowersTimesTwoVec := make([]*big.Int, EC.V) - for j := 0; j < m; j++ { - zp := new(big.Int).Exp(cz, big.NewInt(2+int64(j)), EC.N) - for i := 0; i < bitsPerValue; i++ { - zPowersTimesTwoVec[j*bitsPerValue+i] = new(big.Int).Mod(new(big.Int).Mul(PowerOfTwos[i], zp), EC.N) - } - } - - PowerOfCY := PowerVector(EC.V, cy) - // fmt.Println(PowerOfCY) - l0 := VectorAddScalar(aLConcat, new(big.Int).Neg(cz)) - l1 := sL - r0 := VectorAdd( - VectorHadamard( - PowerOfCY, - VectorAddScalar(aRConcat, cz)), - zPowersTimesTwoVec) - r1 := VectorHadamard(sR, PowerOfCY) - - //calculate t0 - vz2 := big.NewInt(0) - z2 := new(big.Int).Mod(new(big.Int).Mul(cz, cz), EC.N) - PowerOfCZ := PowerVector(m, cz) - for j := 0; j < m; j++ { - vz2 = new(big.Int).Add(vz2, - new(big.Int).Mul( - PowerOfCZ[j], - new(big.Int).Mul(values[j], z2))) - vz2 = new(big.Int).Mod(vz2, EC.N) - } - - t0 := new(big.Int).Mod(new(big.Int).Add(vz2, DeltaMRP(PowerOfCY, cz, m)), EC.N) - - t1 := new(big.Int).Mod(new(big.Int).Add(InnerProduct(l1, r0), InnerProduct(l0, r1)), EC.N) - t2 := InnerProduct(l1, r1) - - // given the t_i values, we can generate commitments to them - tau1, err := rand.Int(rand.Reader, EC.N) - check(err) - tau2, err := rand.Int(rand.Reader, EC.N) - check(err) - - T1 := pedersenCommitment(tau1, t1) // EC.G.Mult(t1).Add(EC.H.Mult(tau1)) //commitment to t1 - T2 := pedersenCommitment(tau2, t2) //EC.G.Mult(t2).Add(EC.H.Mult(tau2)) //commitment to t2 - - MRPResult.T1 = T1 - MRPResult.T2 = T2 - - // t1Byte := append(PadTo32Bytes(T1.X.Bytes()), PadTo32Bytes(T1.Y.Bytes())...) - // t2Byte := append(PadTo32Bytes(T2.X.Bytes()), PadTo32Bytes(T2.Y.Bytes())...) - // input = append(t1Byte, t2Byte...) - // chal3s256 := crypto.Keccak256(input) - chal3s256 := HashPointsToBytes(append(Comms, A, S, T1, T2)) - - // chal3s256 := sha256.Sum256([]byte(T1.X.String() + T1.Y.String() + T2.X.String() + T2.Y.String())) - cx := new(big.Int).SetBytes(chal3s256[:]) - - MRPResult.Cx = cx - - left := CalculateLMRP(aLConcat, sL, cz, cx) - right := CalculateRMRP(aRConcat, sR, PowerOfCY, zPowersTimesTwoVec, cz, cx) - - thatPrime := new(big.Int).Mod( // t0 + t1*x + t2*x^2 - new(big.Int).Add(t0, new(big.Int).Add(new(big.Int).Mul(t1, cx), new(big.Int).Mul(new(big.Int).Mul(cx, cx), t2))), EC.N) - - that := InnerProduct(left, right) // NOTE: BP Java implementation calculates this from the t_i - - // thatPrime and that should be equal - if thatPrime.Cmp(that) != 0 { - fmt.Println("Proving -- Uh oh! Two diff ways to compute same value not working") - fmt.Printf("\tthatPrime = %s\n", thatPrime.String()) - fmt.Printf("\tthat = %s \n", that.String()) - } - - MRPResult.Th = that - - vecRandomnessTotal := big.NewInt(0) - for j := 0; j < m; j++ { - zp := new(big.Int).Exp(cz, big.NewInt(2+int64(j)), EC.N) - tmp1 := new(big.Int).Mul(gammas[j], zp) - vecRandomnessTotal = new(big.Int).Mod(new(big.Int).Add(vecRandomnessTotal, tmp1), EC.N) - } - //fmt.Println(vecRandomnessTotal) - taux1 := new(big.Int).Mod(new(big.Int).Mul(tau2, new(big.Int).Mul(cx, cx)), EC.N) - taux2 := new(big.Int).Mod(new(big.Int).Mul(tau1, cx), EC.N) - taux := new(big.Int).Mod(new(big.Int).Add(taux1, new(big.Int).Add(taux2, vecRandomnessTotal)), EC.N) - - MRPResult.Tau = taux - - mu := new(big.Int).Mod(new(big.Int).Add(alpha, new(big.Int).Mul(rho, cx)), EC.N) - MRPResult.Mu = mu - - HPrime := make([]ECPoint, len(EC.BPH)) - - for i := range HPrime { - HPrime[i] = EC.BPH[i].Mult(new(big.Int).ModInverse(PowerOfCY[i], EC.N)) - } - - P := TwoVectorPCommitWithGens(EC.BPG, HPrime, left, right) - //fmt.Println(P) - - MRPResult.IPP = InnerProductProve(left, right, that, P, EC.U, EC.BPG, HPrime) - - return MRPResult, nil -} - -/* -MultiRangeProof Verify -Takes in a MultiRangeProof and verifies its correctness -*/ -func MRPVerify(mrp *MultiRangeProof) bool { - m := len(mrp.Comms) - EC = genECPrimeGroupKey(m * bitsPerValue) - - //changes: - // check 1 changes since it includes all commitments - // check 2 commitment generation is also different - - // verify the challenges - // input := append(PadTo32Bytes(mrp.A.X.Bytes()), PadTo32Bytes(mrp.A.Y.Bytes())...) - // chal1s256 := crypto.Keccak256(input) - chal1s256 := HashPointsToBytes(append(mrp.Comms, mrp.A)) - - cy := new(big.Int).SetBytes(chal1s256[:]) - - if cy.Cmp(mrp.Cy) != 0 { - log.Debug("MRPVerify challenge failed!", "Cy", common.Bytes2Hex(mrp.Cy.Bytes())) - return false - } - - // input = append(PadTo32Bytes(mrp.S.X.Bytes()), PadTo32Bytes(mrp.S.Y.Bytes())...) - // chal2s256 := crypto.Keccak256(input) - chal2s256 := HashPointsToBytes(append(mrp.Comms, mrp.A, mrp.S)) - - // chal2s256 := sha256.Sum256([]byte(mrp.S.X.String() + mrp.S.Y.String())) - cz := new(big.Int).SetBytes(chal2s256[:]) - if cz.Cmp(mrp.Cz) != 0 { - log.Debug("MRPVerify challenge failed!", "Cz", common.Bytes2Hex(mrp.Cz.Bytes())) - return false - } - - // t1Byte := append(PadTo32Bytes(mrp.T1.X.Bytes()), PadTo32Bytes(mrp.T1.Y.Bytes())...) - // t2Byte := append(PadTo32Bytes(mrp.T2.X.Bytes()), PadTo32Bytes(mrp.T2.Y.Bytes())...) - // input = append(t1Byte, t2Byte...) - // chal3s256 := crypto.Keccak256(input) - chal3s256 := HashPointsToBytes(append(mrp.Comms, mrp.A, mrp.S, mrp.T1, mrp.T2)) - - // chal3s256 := sha256.Sum256([]byte(T1.X.String() + T1.Y.String() + T2.X.String() + T2.Y.String())) - // cx := new(big.Int).SetBytes(chal3s256[:]) - //chal3s256 := sha256.Sum256([]byte(mrp.T1.X.String() + mrp.T1.Y.String() + mrp.T2.X.String() + mrp.T2.Y.String())) - - cx := new(big.Int).SetBytes(chal3s256[:]) - - if cx.Cmp(mrp.Cx) != 0 { - log.Debug("MRPVerify challenge failed!", "Cx", common.Bytes2Hex(mrp.Cx.Bytes())) - return false - } - - // given challenges are correct, very range proof - PowersOfY := PowerVector(EC.V, cy) - - // t_hat * G + tau * H - lhs := pedersenCommitment(mrp.Tau, mrp.Th) //EC.G.Mult(mrp.Th).Add(EC.H.Mult(mrp.Tau)) - - // z^2 * \bold{z}^m \bold{V} + delta(y,z) * G + x * T1 + x^2 * T2 - CommPowers := EC.Zero() - PowersOfZ := PowerVector(m, cz) - z2 := new(big.Int).Mod(new(big.Int).Mul(cz, cz), EC.N) - - for j := 0; j < m; j++ { - CommPowers = CommPowers.Add(mrp.Comms[j].Mult(new(big.Int).Mul(z2, PowersOfZ[j]))) - } - - // TODO i need to change how to calculate the commitment here also ? - // need to compare and double check with privacy-client lib - rhs := EC.G.Mult(DeltaMRP(PowersOfY, cz, m)).Add( - mrp.T1.Mult(cx)).Add( - mrp.T2.Mult(new(big.Int).Mul(cx, cx))).Add(CommPowers) - - if !lhs.Equal(rhs) { - log.Debug("Rangeproof failed") - return false - } - - tmp1 := EC.Zero() - zneg := new(big.Int).Mod(new(big.Int).Neg(cz), EC.N) - for i := range EC.BPG { - tmp1 = tmp1.Add(EC.BPG[i].Mult(zneg)) - } - - PowerOfTwos := PowerVector(bitsPerValue, big.NewInt(2)) - tmp2 := EC.Zero() - // generate h' - HPrime := make([]ECPoint, len(EC.BPH)) - - for i := range HPrime { - mi := new(big.Int).ModInverse(PowersOfY[i], EC.N) - HPrime[i] = EC.BPH[i].Mult(mi) - } - - for j := 0; j < m; j++ { - for i := 0; i < bitsPerValue; i++ { - val1 := new(big.Int).Mul(cz, PowersOfY[j*bitsPerValue+i]) - zp := new(big.Int).Exp(cz, big.NewInt(2+int64(j)), EC.N) - val2 := new(big.Int).Mod(new(big.Int).Mul(zp, PowerOfTwos[i]), EC.N) - tmp2 = tmp2.Add(HPrime[j*bitsPerValue+i].Mult(new(big.Int).Add(val1, val2))) - } - } - - // without subtracting this value should equal muCH + l[i]G[i] + r[i]H'[i] - // we want to make sure that the innerproduct checks out, so we subtract it - P := mrp.A.Add(mrp.S.Mult(cx)).Add(tmp1).Add(tmp2).Add(EC.H.Mult(mrp.Mu).Neg()) - //fmt.Println(P) - - if !InnerProductVerifyFast(mrp.Th, P, EC.U, EC.BPG, HPrime, mrp.IPP) { - log.Debug("Range proof failed!") - return false - } - - return true -} - -// NewECPrimeGroupKey returns the curve (field), -// Generator 1 x&y, Generator 2 x&y, order of the generators -func NewECPrimeGroupKey(n int) CryptoParams { - curValue := btcec.S256().Gx - s256 := sha256.New() - gen1Vals := make([]ECPoint, n) - gen2Vals := make([]ECPoint, n) - u := ECPoint{big.NewInt(0), big.NewInt(0)} - cg := ECPoint{} - ch := ECPoint{} - - j := 0 - confirmed := 0 - for confirmed < (2*n + 3) { - s256.Write(new(big.Int).Add(curValue, big.NewInt(int64(j))).Bytes()) - - potentialXValue := make([]byte, 33) - binary.LittleEndian.PutUint32(potentialXValue, 2) - for i, elem := range s256.Sum(nil) { - potentialXValue[i+1] = elem - } - - gen2, err := btcec.ParsePubKey(potentialXValue, btcec.S256()) - if err == nil { - if confirmed == 2*n { // once we've generated all g and h values then assign this to u - u = ECPoint{gen2.X, gen2.Y} - //fmt.Println("Got that U value") - } else if confirmed == 2*n+1 { - cg = ECPoint{gen2.X, gen2.Y} - - } else if confirmed == 2*n+2 { - ch = ECPoint{gen2.X, gen2.Y} - } else { - if confirmed%2 == 0 { - gen1Vals[confirmed/2] = ECPoint{gen2.X, gen2.Y} - //fmt.Println("new G Value") - } else { - gen2Vals[confirmed/2] = ECPoint{gen2.X, gen2.Y} - //fmt.Println("new H value") - } - } - confirmed += 1 - } - j += 1 - } - - return CryptoParams{ - btcec.S256(), - btcec.S256(), - gen1Vals, - gen2Vals, - btcec.S256().N, - u, - n, - cg, - ch} -} - -func genECPrimeGroupKey(n int) CryptoParams { - // curValue := btcec.S256().Gx - // s256 := sha256.New() - gen1Vals := make([]ECPoint, n) - gen2Vals := make([]ECPoint, n) - // u := ECPoint{big.NewInt(0), big.NewInt(0)} - hx, _ := new(big.Int).SetString("50929b74c1a04954b78b4b6035e97a5e078a5a0f28ec96d547bfee9ace803ac0", 16) - hy, _ := new(big.Int).SetString("31d3c6863973926e049e637cb1b5f40a36dac28af1766968c30c2313f3a38904", 16) - ch := ECPoint{hx, hy} - - gx, _ := new(big.Int).SetString("79be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798", 16) - gy, _ := new(big.Int).SetString("483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8", 16) - cg := ECPoint{gx, gy} - - i := 0 - for i < n { - gen2Vals[i] = ch.Mult( - big.NewInt(int64(i*2 + 1)), - ) - gen1Vals[i] = cg.Mult( - big.NewInt(int64(i*2 + 2)), - ) - i++ - } - - u := cg.Mult( - big.NewInt(int64(n + 3)), - ) - - return CryptoParams{ - btcec.S256(), - btcec.S256(), - gen1Vals, - gen2Vals, - btcec.S256().N, - u, - n, - ch, - cg} -} - -func init() { - // just need the base parameter N, P, G, H for this init, ignore everything else - EC = CryptoParams{ - btcec.S256(), - btcec.S256(), - make([]ECPoint, VecLength), - make([]ECPoint, VecLength), - btcec.S256().N, - ECPoint{big.NewInt(0), big.NewInt(0)}, - VecLength, - ECPoint{big.NewInt(0), big.NewInt(0)}, - ECPoint{big.NewInt(0), big.NewInt(0)}} -} diff --git a/core/vm/privacy/bulletproof.json b/core/vm/privacy/bulletproof.json deleted file mode 100644 index 263dd7927099..000000000000 --- a/core/vm/privacy/bulletproof.json +++ /dev/null @@ -1 +0,0 @@ -{"Ipp":{"L":[{"x":"7be22788517d8c7e149727c5397cf7b2d6713546dee4f974f3239a1f53e64f44","y":"b18c08695e40b801ace64f00bf7010245dcf972cad7ce1e97e441fa68575bb72"},{"x":"29956e85820c1ede4f6ec987b3c20cbf7c0fc0aa6a8cd823e73105fc681c1880","y":"228e434578a40d247a2b5f1c2a7a5154716fb06e98d8087b3dce9cc85429b72c"},{"x":"b39703b5680857d7629a39374451baae59459418c23f44f522838efd952e69db","y":"60033aa9807a0c081c530c30292eca71f61e17433513ead9caadce7997d97981"},{"x":"074cd428559b2bf9c0a6d54479254bdeedc26e655b7f0d822aec9a6d1f1068b3","y":"915958a8e24fefe8ec5e6338661567c8e6178d03ac35422284701bf2ab37d592"},{"x":"80d27e070c49f6d41d49254295a9e70ebaf82d8780c93f1c48f018609e3822dd","y":"5c5e365b72835ff1e24ff3a130e1cc332e36d891ba383752e469a667ecf5db01"},{"x":"6e9c63c3188c29d593417b5cb96ab0f149d905a194ace7a3e523d15f8f8922cd","y":"a91566f2cae911542a0658f63451b4a87cea5c668ab4220c974a640442021da6"}],"R":[{"x":"34f512b1fe0989ce77f8cb5b3a95dd31b55c38d4b6278e4923d6cf224d59c421","y":"8757d403eb39a181418db28f742f0ff3f59991929800c424ebce792f27353335"},{"x":"900bc03a4e26a61bb11de434ee150970a22dce77320b26fea1b172dbdfef5b10","y":"de9d1b833decc36f84ae4ce1be87414674ebef7b58009563f35a722347eb76d7"},{"x":"0ca13ff9d0a929b417a165ceb42c532dd54c34e8f1e9083208630dadafdb5ee4","y":"0bba4e3ac3b20cde8074d4683742f924bdb070a590c1d9d7c8f239748359015c"},{"x":"c29728cbb8393b65f8f224e587eccee9d332d2936b36bb460a9f9df720ef5add","y":"88295fbbe05f25534a43ac528a890b9a26ab3bf95a63e4803168d56b430190ce"},{"x":"4cd804793a0169e0bfe1206907cec530a733efb7cca86f08bff8d04bfb82394b","y":"453594ec2090934e75348db0db070c79b6302cf289d1907adbc198493fee417e"},{"x":"9d9a42ba4b30cc68841ce6528f0d4ffa7990b35fc533f7cb0e4bf0d26cc9c6b6","y":"d6dbdb179262c2bc1fc734d4e20a2c54c5e0b8b8d0c48ee630e146f4cef1f486"}],"A":"-2d23144bda297742e1eafb40911ccdbf2f5e950e8b73b4eaf8f78b857d5c7a93","B":"162325c6d1160e0c033135e32b57351c17ef79755cf4f19c6d6c0ba8117e8d09","Challenges":["139fb4a37d387933e43987862d67297c65af5302c6995bfe7181646dcfc169f1","d43aa9b8fdd97b12e3c4bfabf4c36c59dabb08ace9d5da221f676cc7244000e0","3013fdc8605a4dd479898c2b9abbab45ed9b9676267d8c86a0b7b737448c3d8e","b7a16a537783cd7a9e5bddad4536754a6b16a152fedd2df46a36f76a51cd66d9","5408a38e71aa569b6ddc2ccc84a3b2fa29253905072bf8ed5035406cda89e6fa","1ab61f234a5982567e51af82efd118ebcb44befabfaa5f07183471508e3f4208","3e666d903ccd1312a9a83506b298dfac2c2f11f796087d91104487a577802faa"]},"Comms":["71a29edddcf580c0ab4c992f34df4bcd7f23079bf29c07267e354c0e1b0c7b7d0d7d7f55259df2570dc37a2b6719eb58b2195f06163d29b7aca710cbf9b66560"],"A":"e7d28764b37d275ee1b0cc589ab2aa46cc60a406d6cb0def47dcb5fc49b3279dc65b2eb160328db9dc5953a263a5eba0855b51c66a5e23ac0a3b997d060643ed","S":"78aa79b16298d8c7cc587c8fe521d13b9c768256a8842e74e82970507efea3b9735e4324787071ded1e049c888aee40fe85cff0fff4ffdc4d2d3dc2a17ac306a","cy":"3e38e29bf805dc855b687f969a1a854a0c23fddb8ff1f480079929518e8df1f6","cz":"d794749e1c1442762943a40422a6f9bd284f938fce652c382fea05a0e33ca68f","T1":"45e56a5bc134b7b19d53670d57b45874a01442b58a853dd0960f4a7ec1a093f59be5d93e35a55f2006f03cf9c31801942d9a8739a9408c67d93c4dff6c9f7346","T2":"ad380e6564ae44cd6f91656e66c031cfe21aa47cc511ae51e4a2a8604bd181cd181be8eb1b8e0de71458eed4ce538667a392cc0e7c4e85ab7f4cff54161c8087","cx":"75327f647ab5124eefa92e51f769cdb64a24fe5f88a059b002f2d590c9236894","Th":"-ee380a27a0b95643f9a3a5a975c9b35638ba2a7105a36c7ffd90acdd16029323","Tau":"38059dcf3dfc1da9646f3dc66c8b1487c3375577e751e8341b2addd45ef06306","Mu":"e648b63a1857d1e9723b01ac3151c29fd723845f8aa2a7d6ae867feba8db53e5"} \ No newline at end of file diff --git a/core/vm/privacy/bulletproof_test.go b/core/vm/privacy/bulletproof_test.go deleted file mode 100644 index 8088ac98e9d3..000000000000 --- a/core/vm/privacy/bulletproof_test.go +++ /dev/null @@ -1,527 +0,0 @@ -package privacy - -import ( - "crypto/rand" - "encoding/json" - "fmt" - "io" - "math/big" - "os" - "testing" - - "github.com/stretchr/testify/assert" -) - -func TestInnerProductProveLen1(t *testing.T) { - fmt.Println("TestInnerProductProve1") - EC = genECPrimeGroupKey(1) - a := make([]*big.Int, 1) - b := make([]*big.Int, 1) - - a[0] = big.NewInt(1) - - b[0] = big.NewInt(1) - - c := InnerProduct(a, b) - - P := TwoVectorPCommitWithGens(EC.BPG, EC.BPH, a, b) - - ipp := InnerProductProve(a, b, c, P, EC.U, EC.BPG, EC.BPH) - - if InnerProductVerify(c, P, EC.U, EC.BPG, EC.BPH, ipp) { - fmt.Println("Inner Product Proof correct") - } else { - t.Error("Inner Product Proof incorrect") - } -} - -func TestInnerProductProveLen2(t *testing.T) { - fmt.Println("TestInnerProductProve2") - EC = genECPrimeGroupKey(2) - a := make([]*big.Int, 2) - b := make([]*big.Int, 2) - - a[0] = big.NewInt(1) - a[1] = big.NewInt(1) - - b[0] = big.NewInt(1) - b[1] = big.NewInt(1) - - c := InnerProduct(a, b) - - P := TwoVectorPCommitWithGens(EC.BPG, EC.BPH, a, b) - - fmt.Println("P after two vector commitment with gen ", P) - - ipp := InnerProductProve(a, b, c, P, EC.U, EC.BPG, EC.BPH) - - if InnerProductVerify(c, P, EC.U, EC.BPG, EC.BPH, ipp) { - fmt.Println("Inner Product Proof correct") - } else { - t.Error("Inner Product Proof incorrect") - } -} - -func TestInnerProductProveLen4(t *testing.T) { - fmt.Println("TestInnerProductProve4") - EC = genECPrimeGroupKey(4) - a := make([]*big.Int, 4) - b := make([]*big.Int, 4) - - a[0] = big.NewInt(1) - a[1] = big.NewInt(1) - a[2] = big.NewInt(1) - a[3] = big.NewInt(1) - - b[0] = big.NewInt(1) - b[1] = big.NewInt(1) - b[2] = big.NewInt(1) - b[3] = big.NewInt(1) - - c := InnerProduct(a, b) - - P := TwoVectorPCommitWithGens(EC.BPG, EC.BPH, a, b) - - ipp := InnerProductProve(a, b, c, P, EC.U, EC.BPG, EC.BPH) - - if InnerProductVerify(c, P, EC.U, EC.BPG, EC.BPH, ipp) { - fmt.Println("Inner Product Proof correct") - } else { - t.Error("Inner Product Proof incorrect") - } -} - -func TestInnerProductProveLen8(t *testing.T) { - fmt.Println("TestInnerProductProve8") - EC = genECPrimeGroupKey(8) - a := make([]*big.Int, 8) - b := make([]*big.Int, 8) - - a[0] = big.NewInt(1) - a[1] = big.NewInt(1) - a[2] = big.NewInt(1) - a[3] = big.NewInt(1) - a[4] = big.NewInt(1) - a[5] = big.NewInt(1) - a[6] = big.NewInt(1) - a[7] = big.NewInt(1) - - b[0] = big.NewInt(2) - b[1] = big.NewInt(2) - b[2] = big.NewInt(2) - b[3] = big.NewInt(2) - b[4] = big.NewInt(2) - b[5] = big.NewInt(2) - b[6] = big.NewInt(2) - b[7] = big.NewInt(2) - - c := InnerProduct(a, b) - - P := TwoVectorPCommitWithGens(EC.BPG, EC.BPH, a, b) - - ipp := InnerProductProve(a, b, c, P, EC.U, EC.BPG, EC.BPH) - - if InnerProductVerify(c, P, EC.U, EC.BPG, EC.BPH, ipp) { - fmt.Println("Inner Product Proof correct") - } else { - t.Error("Inner Product Proof incorrect") - } -} - -func TestInnerProductProveLen64Rand(t *testing.T) { - fmt.Println("TestInnerProductProveLen64Rand") - EC = genECPrimeGroupKey(64) - a := RandVector(64) - b := RandVector(64) - - c := InnerProduct(a, b) - - P := TwoVectorPCommitWithGens(EC.BPG, EC.BPH, a, b) - - ipp := InnerProductProve(a, b, c, P, EC.U, EC.BPG, EC.BPH) - - if InnerProductVerify(c, P, EC.U, EC.BPG, EC.BPH, ipp) { - fmt.Println("Inner Product Proof correct") - } else { - t.Error("Inner Product Proof incorrect") - fmt.Printf("Values Used: \n\ta = %s\n\tb = %s\n", a, b) - } - -} - -func TestInnerProductVerifyFastLen1(t *testing.T) { - fmt.Println("TestInnerProductProve1") - EC = genECPrimeGroupKey(1) - a := make([]*big.Int, 1) - b := make([]*big.Int, 1) - - a[0] = big.NewInt(2) - - b[0] = big.NewInt(2) - - c := InnerProduct(a, b) - - P := TwoVectorPCommitWithGens(EC.BPG, EC.BPH, a, b) - - ipp := InnerProductProve(a, b, c, P, EC.U, EC.BPG, EC.BPH) - - if InnerProductVerifyFast(c, P, EC.U, EC.BPG, EC.BPH, ipp) { - fmt.Println("Inner Product Proof correct") - } else { - t.Error("Inner Product Proof incorrect") - } -} - -func TestInnerProductVerifyFastLen2(t *testing.T) { - fmt.Println("TestInnerProductProve2") - EC = genECPrimeGroupKey(2) - a := make([]*big.Int, 2) - b := make([]*big.Int, 2) - - a[0] = big.NewInt(2) - a[1] = big.NewInt(3) - - b[0] = big.NewInt(2) - b[1] = big.NewInt(3) - - c := InnerProduct(a, b) - - P := TwoVectorPCommitWithGens(EC.BPG, EC.BPH, a, b) - - ipp := InnerProductProve(a, b, c, P, EC.U, EC.BPG, EC.BPH) - - if InnerProductVerifyFast(c, P, EC.U, EC.BPG, EC.BPH, ipp) { - fmt.Println("Inner Product Proof correct") - } else { - t.Error("Inner Product Proof incorrect") - } -} - -func TestInnerProductVerifyFastLen4(t *testing.T) { - fmt.Println("TestInnerProductProve4") - EC = genECPrimeGroupKey(4) - a := make([]*big.Int, 4) - b := make([]*big.Int, 4) - - a[0] = big.NewInt(1) - a[1] = big.NewInt(1) - a[2] = big.NewInt(1) - a[3] = big.NewInt(1) - - b[0] = big.NewInt(1) - b[1] = big.NewInt(1) - b[2] = big.NewInt(1) - b[3] = big.NewInt(1) - - c := InnerProduct(a, b) - - P := TwoVectorPCommitWithGens(EC.BPG, EC.BPH, a, b) - - ipp := InnerProductProve(a, b, c, P, EC.U, EC.BPG, EC.BPH) - - if InnerProductVerifyFast(c, P, EC.U, EC.BPG, EC.BPH, ipp) { - fmt.Println("Inner Product Proof correct") - } else { - t.Error("Inner Product Proof incorrect") - } -} - -func TestInnerProductVerifyFastLen8(t *testing.T) { - fmt.Println("TestInnerProductProve8") - EC = genECPrimeGroupKey(8) - a := make([]*big.Int, 8) - b := make([]*big.Int, 8) - - a[0] = big.NewInt(1) - a[1] = big.NewInt(1) - a[2] = big.NewInt(1) - a[3] = big.NewInt(1) - a[4] = big.NewInt(1) - a[5] = big.NewInt(1) - a[6] = big.NewInt(1) - a[7] = big.NewInt(1) - - b[0] = big.NewInt(2) - b[1] = big.NewInt(2) - b[2] = big.NewInt(2) - b[3] = big.NewInt(2) - b[4] = big.NewInt(2) - b[5] = big.NewInt(2) - b[6] = big.NewInt(2) - b[7] = big.NewInt(2) - - c := InnerProduct(a, b) - - P := TwoVectorPCommitWithGens(EC.BPG, EC.BPH, a, b) - - ipp := InnerProductProve(a, b, c, P, EC.U, EC.BPG, EC.BPH) - - if InnerProductVerifyFast(c, P, EC.U, EC.BPG, EC.BPH, ipp) { - fmt.Println("Inner Product Proof correct") - } else { - t.Error("Inner Product Proof incorrect") - } -} - -func TestInnerProductVerifyFastLen64Rand(t *testing.T) { - fmt.Println("TestInnerProductProveLen64Rand") - EC = genECPrimeGroupKey(64) - a := RandVector(64) - b := RandVector(64) - - c := InnerProduct(a, b) - - P := TwoVectorPCommitWithGens(EC.BPG, EC.BPH, a, b) - - ipp := InnerProductProve(a, b, c, P, EC.U, EC.BPG, EC.BPH) - - if InnerProductVerifyFast(c, P, EC.U, EC.BPG, EC.BPH, ipp) { - fmt.Println("Inner Product Proof correct") - } else { - t.Error("Inner Product Proof incorrect") - fmt.Printf("Values Used: \n\ta = %s\n\tb = %s\n", a, b) - } - -} - -func TestMRPProveZERO(t *testing.T) { - - mRangeProof, _ := MRPProve([]*big.Int{ - new(big.Int).SetInt64(0), - }) - mv := MRPVerify(&mRangeProof) - assert.Equal(t, mv, true, " MRProof incorrect") -} - -func TestMRPProve_MAX_2_POW_64(t *testing.T) { - - mRangeProof, _ := MRPProve([]*big.Int{ - new(big.Int).SetUint64(0xFFFFFFFFFFFFFFFF), - }) - mv := MRPVerify(&mRangeProof) - assert.Equal(t, mv, true, " MRProof incorrect") -} - -func TestMRPProveOutOfSupportedRange(t *testing.T) { - - value, _ := new(big.Int).SetString("FFFFFFFFFFFFFFFFFFFF", 16) - _, err := MRPProve([]*big.Int{ - value, - }) - assert.NotNil(t, err, " MRProof incorrect") -} - -func TestMRPProve_RANDOM(t *testing.T) { - - mRangeProof, _ := MRPProve(Rand64Vector(1)) - mv := MRPVerify(&mRangeProof) - assert.Equal(t, mv, true, " MRProof incorrect") - - mRangeProof, _ = MRPProve(Rand64Vector(2)) - mv = MRPVerify(&mRangeProof) - assert.Equal(t, mv, true, " MRProof incorrect") - - mRangeProof, _ = MRPProve(Rand64Vector(4)) - mv = MRPVerify(&mRangeProof) - assert.Equal(t, mv, true, " MRProof incorrect") - - mRangeProof, _ = MRPProve(Rand64Vector(8)) - mv = MRPVerify(&mRangeProof) - assert.Equal(t, mv, true, " MRProof incorrect") -} - -func Rand64Vector(l int) []*big.Int { - result := make([]*big.Int, l) - - for i := 0; i < l; i++ { - x, err := rand.Int(rand.Reader, big.NewInt(0xFFFFFFFFFFFFFFF)) - check(err) - result[i] = x - } - - return result -} - -func TestMRPProveValueNumberNotSupported(t *testing.T) { - - _, err := MRPProve(Rand64Vector(3)) - assert.NotNil(t, err, "MRProof incorrect - accepted 3 inputs") - - _, err = MRPProve(Rand64Vector(5)) - assert.NotNil(t, err, "MRProof incorrect - accepted 5 inputs") - - _, err = MRPProve(Rand64Vector(6)) - assert.NotNil(t, err, "MRProof incorrect - accepted 6 inputs") - - _, err = MRPProve(Rand64Vector(7)) - assert.NotNil(t, err, "MRProof incorrect - accepted 7 inputs") - - _, err = MRPProve(Rand64Vector(10)) - assert.NotNil(t, err, "MRProof incorrect - accepted 10 inputs") - - _, err = MRPProve(Rand64Vector(1)) - assert.Nil(t, err, "MRProof incorrect - not accepted 1 inputs") - - _, err = MRPProve(Rand64Vector(2)) - assert.Nil(t, err, "MRProof incorrect - not accepted 2 inputs") - - _, err = MRPProve(Rand64Vector(4)) - fmt.Println(err) - assert.Nil(t, err, "MRProof incorrect - not accepted 4 inputs") - - _, err = MRPProve(Rand64Vector(8)) - assert.Nil(t, err, "MRProof incorrect - not accepted 8 inputs") -} - -type Point struct { - x string - y string -} - -type IPP struct { - L []map[string]string `json:"L"` - R []map[string]string `json:"R"` - A string `json:"A"` - B string `json:"B"` - Challenges []string `json:"Challenges"` -} - -type BulletProof struct { - Comms []string `json:"Comms"` - A string `json:"A"` - S string `json:"S"` - Cx string `json:"Cx"` - Cy string `json:"Cy"` - Cz string `json:"Cz"` - T1 string `json:"T1"` - T2 string `json:"T2"` - Th string `json:"Th"` - Tau string `json:"Tau"` - Mu string `json:"Mu"` - Ipp IPP `json:"Ipp"` -} - -func parseTestData(filePath string) MultiRangeProof { - jsonFile, err := os.Open(filePath) - - if err != nil { - fmt.Println(err) - } - - defer jsonFile.Close() - - byteValue, _ := io.ReadAll(jsonFile) - - // we initialize our Users array - // var result map[string]interface{} - result := BulletProof{} - - json.Unmarshal([]byte(byteValue), &result) - - fmt.Println("result ", result.Tau) - fmt.Println("result ", result.Th) - fmt.Println("result.Ipp ", result.Ipp) - - ipp := result.Ipp - - proof := MultiRangeProof{ - Comms: MapECPointFromHex(result.Comms, ECPointFromHex), - A: ECPointFromHex(result.A), - S: ECPointFromHex(result.S), - T1: ECPointFromHex(result.T1), - T2: ECPointFromHex(result.T2), - Th: bigIFromHex(result.Th), - Tau: bigIFromHex(result.Tau), - Mu: bigIFromHex(result.Mu), - Cx: bigIFromHex(result.Cx), - Cy: bigIFromHex(result.Cy), - Cz: bigIFromHex(result.Cz), - IPP: InnerProdArg{ - L: MapECPoint(ipp.L, ECPointFromPoint), - R: MapECPoint(ipp.R, ECPointFromPoint), - A: bigIFromHex(ipp.A), - B: bigIFromHex(ipp.B), - Challenges: MapBigI(ipp.Challenges, bigIFromHex), - }, - } - - fmt.Println(proof) - return proof -} - -/* -* -Utils for parsing data from json -*/ -func MapBigI(list []string, f func(string) *big.Int) []*big.Int { - result := make([]*big.Int, len(list)) - - for i, item := range list { - result[i] = f(item) - } - return result -} - -func MapECPointFromHex(list []string, f func(string) ECPoint) []ECPoint { - result := make([]ECPoint, len(list)) - - for i, item := range list { - result[i] = f(item) - } - return result -} - -func MapECPoint(list []map[string]string, f func(Point) ECPoint) []ECPoint { - result := make([]ECPoint, len(list)) - - for i, item := range list { - result[i] = f(Point{ - x: item["x"], - y: item["y"], - }) - } - return result -} - -func bigIFromHex(hex string) *big.Int { - tmp, _ := new(big.Int).SetString(hex, 16) - return tmp -} - -func ECPointFromHex(hex string) ECPoint { - Px, _ := new(big.Int).SetString(hex[:64], 16) - Py, _ := new(big.Int).SetString(hex[64:], 16) - P := ECPoint{Px, Py} - return P -} - -func ECPointFromPoint(ecpoint Point) ECPoint { - Px, _ := new(big.Int).SetString(ecpoint.x, 16) - Py, _ := new(big.Int).SetString(ecpoint.y, 16) - P := ECPoint{Px, Py} - return P -} - -func TestMRPGeneration(t *testing.T) { - values := make([]*big.Int, 2) - values[0] = big.NewInt(1000) - values[1] = big.NewInt(100000) - mrp, err := MRPProve(values) - if err != nil { - t.Error("failed to generate bulletproof") - } - - v := MRPVerify(&mrp) - serilizedBp := mrp.Serialize() - - newMRP := new(MultiRangeProof) - if newMRP.Deserialize(serilizedBp) != nil { - t.Error("failed to deserialized bulletproof") - } - - v = v && MRPVerify(newMRP) - - if !v { - t.Error("failed to verify bulletproof") - } -} diff --git a/core/vm/privacy/ringct.go b/core/vm/privacy/ringct.go deleted file mode 100644 index 93c97c56cee1..000000000000 --- a/core/vm/privacy/ringct.go +++ /dev/null @@ -1,632 +0,0 @@ -package privacy - -import ( - "bytes" - "crypto/ecdsa" - "crypto/elliptic" - "crypto/rand" - "encoding/binary" - "errors" - "fmt" - "math/big" - - "github.com/XinFinOrg/XDPoSChain/common" - - "github.com/XinFinOrg/XDPoSChain/crypto" - "github.com/XinFinOrg/XDPoSChain/crypto/secp256k1" - - "github.com/XinFinOrg/XDPoSChain/log" -) - -// These constants define the lengths of serialized public keys. -const ( - PubKeyBytesLenCompressed = 33 - PubKeyBytesLenUncompressed = 65 - PubKeyBytesLenHybrid = 65 -) - -const ( - pubkeyCompressed byte = 0x2 // y_bit + x coord - pubkeyUncompressed byte = 0x4 // x coord + y coord - pubkeyHybrid byte = 0x6 // y_bit + x coord + y coord -) - -// The proof contains pretty much stuffs -// The proof contains pretty much stuffs -// Ring size rs: 1 byte => proof[0] -// num input: number of real inputs: 1 byte => proof[1] -// List of inputs/UTXO index typed uint64 => total size = rs * numInput * 8 = proof[0]*proof[1]*8 -// List of key images: total size = numInput * 33 = proof[1] * 33 -// number of output n: 1 byte -// List of output => n * 130 bytes -// transaction fee: uint256 => 32 byte -// ringCT proof size ctSize: uint16 => 2 byte -// ringCT proof: ctSize bytes -// bulletproofs: bp -type PrivateSendVerifier struct { - proof []byte - //ringCT RingCT -} - -type Ring []*ecdsa.PublicKey - -type RingSignature struct { - NumRing int - Size int // size of ring - M [32]byte // message - C *big.Int // ring signature value, 1 element - S [][]*big.Int // ring signature values: [NumRing][Size] - Ring []Ring // array of rings of pubkeys: [NumRing] - I []*ecdsa.PublicKey // key images, size = the number of rings [NumRing] - Curve elliptic.Curve - SerializedRing []byte //temporary memory stored the raw ring ct used in case of verifying ringCT with message verification -} - -func (p *PrivateSendVerifier) verify() bool { - return false -} - -func (p *PrivateSendVerifier) deserialize() { - -} - -// helper function, returns type of v -func typeof(v interface{}) string { - return fmt.Sprintf("%T", v) -} - -func isOdd(a *big.Int) bool { - return a.Bit(0) == 1 -} - -// SerializeCompressed serializes a public key in a 33-byte compressed format. -func SerializeCompressed(p *ecdsa.PublicKey) []byte { - b := make([]byte, 0, PubKeyBytesLenCompressed) - format := pubkeyCompressed - if isOdd(p.Y) { - format |= 0x1 - } - b = append(b, format) - return append(b, PadTo32Bytes(p.X.Bytes())...) -} - -func DeserializeCompressed(curve elliptic.Curve, b []byte) *ecdsa.PublicKey { - x := new(big.Int).SetBytes(b[1:33]) - // Y = +-sqrt(x^3 + B) - x3 := new(big.Int).Mul(x, x) - x3.Mul(x3, x) - x3.Add(x3, curve.Params().B) - - // now calculate sqrt mod p of x2 + B - // This code used to do a full sqrt based on tonelli/shanks, - // but this was replaced by the algorithms referenced in - // https://bitcointalk.org/index.php?topic=162805.msg1712294#msg1712294 - PPlus1Div4 := new(big.Int).Add(curve.Params().P, big.NewInt(1)) - PPlus1Div4 = PPlus1Div4.Div(PPlus1Div4, big.NewInt(4)) - y := new(big.Int).Exp(x3, PPlus1Div4, curve.Params().P) - ybit := b[0]%2 == 1 - if ybit != isOdd(y) { - y.Sub(curve.Params().P, y) - } - if ybit != isOdd(y) { - return nil - } - return &ecdsa.PublicKey{curve, x, y} -} - -// bytes returns the public key ring as a byte slice. -func (r Ring) Bytes() (b []byte) { - for _, pub := range r { - b = append(b, PadTo32Bytes(pub.X.Bytes())...) - b = append(b, PadTo32Bytes(pub.Y.Bytes())...) - } - return -} - -func PadTo32Bytes(in []byte) []byte { - padded := make([]byte, 32) - if len(in) >= 32 { - copy(padded, in) - } else { - copy(padded[32-len(in):], in) - } - - return padded -} - -// converts the signature to a byte array -// this is the format that will be used when passing EVM bytecode -func (r *RingSignature) Serialize() ([]byte, error) { - sig := []byte{} - // add size and message - b := make([]byte, 8) - binary.BigEndian.PutUint64(b, uint64(r.NumRing)) - sig = append(sig, b[:]...) // 8 bytes - - b = make([]byte, 8) - binary.BigEndian.PutUint64(b, uint64(r.Size)) - sig = append(sig, b[:]...) // 8 bytes - - sig = append(sig, PadTo32Bytes(r.M[:])...) // 32 bytes - sig = append(sig, PadTo32Bytes(r.C.Bytes())...) // 32 bytes - - for k := 0; k < r.NumRing; k++ { - // 96 bytes each iteration - for i := 0; i < r.Size; i++ { - sig = append(sig, PadTo32Bytes(r.S[k][i].Bytes())...) - } - } - for k := 0; k < r.NumRing; k++ { - // 96 bytes each iteration - for i := 0; i < r.Size; i++ { - rb := SerializeCompressed(r.Ring[k][i]) - sig = append(sig, rb...) - } - } - - for k := 0; k < r.NumRing; k++ { - // 64 bytes - rb := SerializeCompressed(r.I[k]) - sig = append(sig, rb...) - } - - if len(sig) != 8+8+32+32+(32+33)*r.NumRing*r.Size+33*r.NumRing { - return []byte{}, errors.New("Could not serialize ring signature") - } - - return sig, nil -} - -func computeSignatureSize(numRing int, ringSize int) int { - const MaxInt = int(^uint(0) >> 1) - - if numRing < 0 || ringSize < 0 { - return -1 - } - - // Calculate term and check for overflow - - term := numRing * ringSize * 65 - - if term < 0 || term < numRing || term < ringSize { - return -1 - } - - return 8 + 8 + 32 + 32 + numRing*ringSize*32 + numRing*ringSize*33 + numRing*33 -} - -// deserializes the byteified signature into a RingSignature struct -func Deserialize(r []byte) (*RingSignature, error) { - if len(r) < 16 { - return nil, errors.New("Failed to deserialize ring signature") - } - offset := 0 - sig := new(RingSignature) - numRing := r[offset : offset+8] - offset += 8 - size := r[offset : offset+8] - offset += 8 - - size_uint := binary.BigEndian.Uint64(size) - size_int := int(size_uint) - sig.Size = size_int - - size_uint = binary.BigEndian.Uint64(numRing) - size_int = int(size_uint) - sig.NumRing = size_int - - if len(r) != computeSignatureSize(sig.NumRing, sig.Size) { - return nil, fmt.Errorf("incorrect ring size, len r: %d, sig.NumRing: %d sig.Size: %d", len(r), sig.NumRing, sig.Size) - } - - m := r[offset : offset+32] - offset += 32 - - var m_byte [32]byte - copy(m_byte[:], m) - - sig.M = m_byte - sig.C = new(big.Int).SetBytes(r[offset : offset+32]) - offset += 32 - - sig.S = make([][]*big.Int, sig.NumRing) - for i := 0; i < sig.NumRing; i++ { - sig.S[i] = make([]*big.Int, sig.Size) - for j := 0; j < sig.Size; j++ { - sig.S[i][j] = new(big.Int).SetBytes(r[offset : offset+32]) - offset += 32 - } - } - - sig.Curve = crypto.S256() - - sig.Ring = make([]Ring, sig.NumRing) - for i := 0; i < sig.NumRing; i++ { - sig.Ring[i] = make([]*ecdsa.PublicKey, sig.Size) - for j := 0; j < sig.Size; j++ { - compressedKey := r[offset : offset+33] - offset += 33 - compressedPubKey := DeserializeCompressed(sig.Curve, compressedKey) - sig.Ring[i][j] = compressedPubKey - } - } - - sig.I = make([]*ecdsa.PublicKey, sig.NumRing) - for i := 0; i < sig.NumRing; i++ { - compressedKey := r[offset : offset+33] - offset += 33 - compressedPubKey := DeserializeCompressed(sig.Curve, compressedKey) - sig.I[i] = compressedPubKey - } - - sig.SerializedRing = r - - if !Verify(sig, false) { - return nil, errors.New("failed to deserialize, invalid ring signature") - } - - return sig, nil -} - -// takes public key ring and places the public key corresponding to `privkey` in index s of the ring -// returns a key ring of type []*ecdsa.PublicKey -func GenKeyRing(ring []*ecdsa.PublicKey, privkey *ecdsa.PrivateKey, s int) ([]*ecdsa.PublicKey, error) { - size := len(ring) + 1 - new_ring := make([]*ecdsa.PublicKey, size) - pubkey := privkey.Public().(*ecdsa.PublicKey) - - if s > len(ring) { - return nil, errors.New("index s out of bounds") - } - - new_ring[s] = pubkey - for i := 1; i < size; i++ { - idx := (i + s) % size - new_ring[idx] = ring[i-1] - } - - return new_ring, nil -} - -// creates a ring with size specified by `size` and places the public key corresponding to `privkey` in index s of the ring -// returns a new key ring of type []*ecdsa.PublicKey -func GenNewKeyRing(size int, privkey *ecdsa.PrivateKey, s int) ([]*ecdsa.PublicKey, error) { - ring := make([]*ecdsa.PublicKey, size) - pubkey := privkey.Public().(*ecdsa.PublicKey) - - if s >= len(ring) { - return nil, errors.New("index s out of bounds") - } - - ring[s] = pubkey - - for i := 1; i < size; i++ { - idx := (i + s) % size - priv, err := crypto.GenerateKey() - if err != nil { - return nil, err - } - - pub := priv.Public() - ring[idx] = pub.(*ecdsa.PublicKey) - } - - return ring, nil -} - -// calculate key image I = x * H_p(P) where H_p is a hash function that returns a point -// H_p(P) = sha3(P) * G -func GenKeyImage(privkey *ecdsa.PrivateKey) *ecdsa.PublicKey { - pubkey := privkey.Public().(*ecdsa.PublicKey) - image := new(ecdsa.PublicKey) - - // calculate sha3(P) - h_x, h_y := HashPoint(pubkey) - - // calculate H_p(P) = x * sha3(P) * G - i_x, i_y := privkey.Curve.ScalarMult(h_x, h_y, privkey.D.Bytes()) - - image.X = i_x - image.Y = i_y - return image -} - -func HashPoint(p *ecdsa.PublicKey) (*big.Int, *big.Int) { - input := append(PadTo32Bytes(p.X.Bytes()), PadTo32Bytes(p.Y.Bytes())...) - log.Info("HashPoint", "input ", common.Bytes2Hex(input)) - hash := crypto.Keccak256(input) - log.Info("HashPoint", "hash ", common.Bytes2Hex(hash)) - return p.Curve.ScalarBaseMult(hash[:]) -} - -// create ring signature from list of public keys given inputs: -// msg: byte array, message to be signed -// ring: array of *ecdsa.PublicKeys to be included in the ring -// privkey: *ecdsa.PrivateKey of signer -// s: index of signer in ring -func Sign(m [32]byte, rings []Ring, privkeys []*ecdsa.PrivateKey, s int) (*RingSignature, error) { - numRing := len(rings) - if numRing < 1 { - return nil, errors.New("there is no ring to make signature") - } - // check ringsize > 1 - ringsize := len(rings[0]) - if ringsize < 2 { - return nil, errors.New("size of ring less than two") - } else if s >= ringsize || s < 0 { - return nil, errors.New("secret index out of range of ring size") - } - - // setup - //pubkey := privkey.Public().(*ecdsa.PublicKey) - pubkeys := make([]*ecdsa.PublicKey, numRing) - for i := 0; i < numRing; i++ { - pubkeys[i] = &privkeys[i].PublicKey - } - //cast to BitCurve used in go-eth since elliptic.Curve.Add() and elliptic.Curve.ScalarMult() is deprecated - curve := pubkeys[0].Curve.(*secp256k1.BitCurve) - sig := new(RingSignature) - sig.Size = ringsize - sig.NumRing = numRing - sig.M = m - sig.Ring = rings - sig.Curve = curve - - // check that key at index s is indeed the signer - for i := 0; i < numRing; i++ { - if rings[i][s] != pubkeys[i] { - return nil, errors.New("secret index in ring is not signer") - } - } - - // generate key image - images := make([]*ecdsa.PublicKey, numRing) - for i := 0; i < numRing; i++ { - images[i] = GenKeyImage(privkeys[i]) - } - sig.I = images - - // start at c[1] - // pick random scalar u (glue value), calculate c[1] = H(m, u*G) where H is a hash function and G is the base point of the curve - C := make([]*big.Int, ringsize) - S := make([][]*big.Int, numRing) - for i := 0; i < numRing; i++ { - S[i] = make([]*big.Int, ringsize) - } - - //Initialize S except S[..][s] - for i := 0; i < numRing; i++ { - for j := 0; j < ringsize; j++ { - if j != s { - randomGenerated, err := rand.Int(rand.Reader, curve.Params().P) - if err != nil { - return nil, err - } - S[i][j] = randomGenerated - } - } - } - - L := make([][]*ecdsa.PublicKey, numRing) - R := make([][]*ecdsa.PublicKey, numRing) - for i := 0; i < numRing; i++ { - L[i] = make([]*ecdsa.PublicKey, ringsize) - R[i] = make([]*ecdsa.PublicKey, ringsize) - } - alpha := make([]*big.Int, numRing) - - var l []byte - //compute L[i][s], R[i][s], i = 0..numRing - for i := 0; i < numRing; i++ { - randomGenerated, err := rand.Int(rand.Reader, curve.Params().P) - if err != nil { - return nil, err - } - alpha[i] = randomGenerated - // start at secret index s/PI - // compute L_s = u*G - l_x, l_y := curve.ScalarBaseMult(PadTo32Bytes(alpha[i].Bytes())) - L[i][s] = &ecdsa.PublicKey{curve, l_x, l_y} - lT := append(PadTo32Bytes(l_x.Bytes()), PadTo32Bytes(l_y.Bytes())...) - l = append(l, lT...) - // compute R_s = u*H_p(P[s]) - h_x, h_y := HashPoint(pubkeys[i]) - r_x, r_y := curve.ScalarMult(h_x, h_y, PadTo32Bytes(alpha[i].Bytes())) - R[i][s] = &ecdsa.PublicKey{curve, r_x, r_y} - rT := append(PadTo32Bytes(r_x.Bytes()), PadTo32Bytes(r_y.Bytes())...) - l = append(l, rT...) - } - - // concatenate m and u*G and calculate c[s+1] = H(m, L_s, R_s) - C_j := crypto.Keccak256(append(m[:], l...)) - idx := s + 1 - if idx == ringsize { - idx = 0 - } - if idx == 0 { - C[0] = new(big.Int).SetBytes(C_j[:]) - } else { - C[idx] = new(big.Int).SetBytes(C_j[:]) - } - for idx != s { - var l []byte - for j := 0; j < numRing; j++ { - // calculate L[j][idx] = s[j][idx]*G + c[idx]*Ring[j][idx] - px, py := curve.ScalarMult(rings[j][idx].X, rings[j][idx].Y, PadTo32Bytes(C[idx].Bytes())) // px, py = c_i*P_i - sx, sy := curve.ScalarBaseMult(PadTo32Bytes(S[j][idx].Bytes())) // sx, sy = s[n-1]*G - if px == nil || py == nil || sx == nil || sy == nil { - return nil, errors.New("Could not create ring signature") - } - l_x, l_y := curve.Add(sx, sy, px, py) - L[j][idx] = &ecdsa.PublicKey{curve, l_x, l_y} - lT := append(PadTo32Bytes(l_x.Bytes()), PadTo32Bytes(l_y.Bytes())...) - l = append(l, lT...) - - // calculate R[j][idx] = s[j][idx]*H_p(Ring[j][idx]) + c[idx]*I[j] - px, py = curve.ScalarMult(images[j].X, images[j].Y, C[idx].Bytes()) // px, py = c_i*I - hx, hy := HashPoint(rings[j][idx]) - sx, sy = curve.ScalarMult(hx, hy, S[j][idx].Bytes()) // sx, sy = s[n-1]*H_p(P_i) - if px == nil || py == nil || sx == nil || sy == nil { - return nil, errors.New("Could not create ring signature") - } - r_x, r_y := curve.Add(sx, sy, px, py) - R[j][idx] = &ecdsa.PublicKey{curve, r_x, r_y} - rT := append(PadTo32Bytes(r_x.Bytes()), PadTo32Bytes(r_y.Bytes())...) - l = append(l, rT...) - } - - idx++ - if idx == ringsize { - idx = 0 - } - - var ciIdx int - if idx == 0 { - ciIdx = 0 - } else { - ciIdx = idx - } - cSha := crypto.Keccak256(append(PadTo32Bytes(m[:]), l...)) - C[ciIdx] = new(big.Int).SetBytes(cSha[:]) - } - - //compute S[j][s] = alpha[j] - c[s] * privkeys[j], privkeys[j] = private key corresponding to key image I[j] - for j := 0; j < numRing; j++ { - cx := C[s] - // close ring by finding S[j][s] = (alpha[j] - c[s]*privkeys[s] ) mod P where k[s] is the private key and P is the order of the curve - S[j][s] = new(big.Int).Mod(new(big.Int).Sub(alpha[j], new(big.Int).Mul(cx, privkeys[j].D)), curve.Params().N) - } - - // everything ok, add values to signature - sig.S = S - sig.C = C[0] - sig.NumRing = numRing - sig.Size = ringsize - sig.C = C[0] - - return sig, nil -} - -// verify ring signature contained in RingSignature struct -// returns true if a valid signature, false otherwise -func Verify(sig *RingSignature, verifyMes bool) bool { - // setup - rings := sig.Ring - ringsize := sig.Size - numRing := sig.NumRing - S := sig.S - C := make([]*big.Int, ringsize+1) - C[0] = sig.C - //cast to BitCurve used in go-eth since elliptic.Curve.Add() and elliptic.Curve.ScalarMult() is deprecated - curve := sig.Curve.(*secp256k1.BitCurve) - image := sig.I - - //check on curve - for i := 0; i < numRing; i++ { - onCurve := curve.IsOnCurve(image[i].X, image[i].Y) - if !onCurve { - return false - } - for j := 0; j < ringsize; j++ { - onCurve := curve.IsOnCurve(rings[i][j].X, rings[i][j].Y) - if !onCurve { - return false - } - } - } - - // calculate c[i+1] = H(m, s[i]*G + c[i]*P[i]) - // and c[0] = H)(m, s[n-1]*G + c[n-1]*P[n-1]) where n is the ring size - //log.Info("C", "0", common.Bytes2Hex(C[0].Bytes())) - for j := 0; j < ringsize; j++ { - var l []byte - for i := 0; i < numRing; i++ { - // Validate S[i][j] and C[j] - if !isValidScalar(S[i][j], curve) || !isValidScalar(C[j], curve) { - return false // Or handle the error as required - } - - // calculate L[i][j] = s[i][j]*G + c[j]*Ring[i][j] - px, py := curve.ScalarMult(rings[i][j].X, rings[i][j].Y, C[j].Bytes()) // px, py = c_i*P_i - sx, sy := curve.ScalarBaseMult(S[i][j].Bytes()) // sx, sy = s[i]*G - if px == nil || py == nil || sx == nil || sy == nil { - return false - } - l_x, l_y := curve.Add(sx, sy, px, py) - lT := append(PadTo32Bytes(l_x.Bytes()), PadTo32Bytes(l_y.Bytes())...) - //log.Info("L[i][j]", "i", i, "j", j, "L", common.Bytes2Hex(lT)) - l = append(l, lT...) - - // calculate R_i = s[i][j]*H_p(Ring[i][j]) + c[j]*I[j] - px, py = curve.ScalarMult(image[i].X, image[i].Y, C[j].Bytes()) // px, py = c[i]*I - hx, hy := HashPoint(rings[i][j]) - - // Validate S[i][j], hx, and hy - if !isValidScalar(S[i][j], curve) || !isValidScalar(hx, curve) || !isValidScalar(hy, curve) { - return false // Or handle the error as required - } - //log.Info("H[i][j]", "i", i, "j", j, "x.input", common.Bytes2Hex(rings[i][j].X.Bytes()), "y.input", common.Bytes2Hex(rings[i][j].Y.Bytes())) - //log.Info("H[i][j]", "i", i, "j", j, "x", common.Bytes2Hex(hx.Bytes()), "y", common.Bytes2Hex(hy.Bytes())) - sx, sy = curve.ScalarMult(hx, hy, S[i][j].Bytes()) // sx, sy = s[i]*H_p(P[i]) - if px == nil || py == nil || sx == nil || sy == nil { - return false - } - r_x, r_y := curve.Add(sx, sy, px, py) - rT := append(PadTo32Bytes(r_x.Bytes()), PadTo32Bytes(r_y.Bytes())...) - //log.Info("R[i][j]", "i", i, "j", j, "L", common.Bytes2Hex(rT)) - l = append(l, rT...) - } - - // calculate c[i+1] = H(m, L_i, R_i) - //cj_mes := append(PadTo32Bytes(sig.M[:]), l...) - C_j := crypto.Keccak256(append(PadTo32Bytes(sig.M[:]), l...)) - //log.Info("C hash input", "j", j + 1, "C_input", common.Bytes2Hex(cj_mes)) - - /*if j == ringsize-1 { - C[0] = new(big.Int).SetBytes(C_j[:]) - } else {*/ - C[j+1] = new(big.Int).SetBytes(C_j[:]) - //log.Info("C", "j", j + 1, "C", common.Bytes2Hex(C[j + 1].Bytes())) - //} - } - - return bytes.Equal(sig.C.Bytes(), C[ringsize].Bytes()) -} - -func isValidScalar(scalar *big.Int, curve elliptic.Curve) bool { - return scalar.Sign() >= 0 && scalar.Cmp(curve.Params().N) < 0 -} - -func Link(sig_a *RingSignature, sig_b *RingSignature) bool { - for i := 0; i < len(sig_a.I); i++ { - for j := 0; j < len(sig_b.I); j++ { - if sig_a.I[i].X == sig_b.I[j].X && sig_a.I[i].Y == sig_b.I[j].Y { - return true - } - } - } - return false -} - -// function returns(mutiple rings, private keys, message, error) -func GenerateMultiRingParams(numRing int, ringSize int, s int) (rings []Ring, privkeys []*ecdsa.PrivateKey, m [32]byte, err error) { - for i := 0; i < numRing; i++ { - privkey, err := crypto.GenerateKey() - if err != nil { - return nil, nil, [32]byte{}, err - } - privkeys = append(privkeys, privkey) - - ring, err := GenNewKeyRing(ringSize, privkey, s) - if err != nil { - return nil, nil, [32]byte{}, err - } - rings = append(rings, ring) - } - - _, err = rand.Read(m[:]) - if err != nil { - return nil, nil, [32]byte{}, err - } - return rings, privkeys, m, nil -} diff --git a/core/vm/privacy/ringct_test.go b/core/vm/privacy/ringct_test.go deleted file mode 100644 index 3e5b771c0bce..000000000000 --- a/core/vm/privacy/ringct_test.go +++ /dev/null @@ -1,324 +0,0 @@ -package privacy - -import ( - "bytes" - "encoding/binary" - "fmt" - "math/big" - "testing" - - "github.com/XinFinOrg/XDPoSChain/crypto" - "github.com/stretchr/testify/assert" - - "github.com/XinFinOrg/XDPoSChain/crypto/secp256k1" -) - -func TestSign(t *testing.T) { - /*for i := 14; i < 15; i++ { - for j := 14; j < 15; j++ { - for k := 0; k <= j; k++ {*/ - numRing := 5 - ringSize := 10 - s := 9 - fmt.Println("Generate random ring parameter ") - rings, privkeys, m, err := GenerateMultiRingParams(numRing, ringSize, s) - - fmt.Println("numRing ", numRing) - fmt.Println("ringSize ", ringSize) - fmt.Println("index of real one ", s) - - fmt.Println("Ring ", rings) - fmt.Println("privkeys ", privkeys) - fmt.Println("m ", m) - - ringSignature, err := Sign(m, rings, privkeys, s) - if err != nil { - t.Error("Failed to create Ring signature") - } - - sig, err := ringSignature.Serialize() - if err != nil { - t.Error("Failed to Serialize input Ring signature") - } - - deserializedSig, err := Deserialize(sig) - if err != nil { - t.Error("Failed to Deserialize Ring signature") - } - verified := Verify(deserializedSig, false) - - if !verified { - t.Error("Failed to verify Ring signature") - } - -} - -func TestDeserialize(t *testing.T) { - numRing := 5 - ringSize := 10 - s := 5 - rings, privkeys, m, err := GenerateMultiRingParams(numRing, ringSize, s) - - ringSignature, err := Sign(m, rings, privkeys, s) - if err != nil { - t.Error("Failed to create Ring signature") - } - - // A normal signature. - sig, err := ringSignature.Serialize() - if err != nil { - t.Error("Failed to Serialize input Ring signature") - } - - // Modify the serialized signature s.t. - // the new signature passes the length check - // but triggers buffer overflow in Deserialize(). - // ringSize: 10 -> 56759212534490939 - // len(sig): 3495 -> 3804 - // 80 + 5 * (56759212534490939*65 + 33) = 18446744073709551616 + 3804 - bs := make([]byte, 8) - binary.BigEndian.PutUint64(bs, 56759212534490939) - for i := 0; i < 8; i++ { - sig[i+8] = bs[i] - } - tail := make([]byte, 3804-len(sig)) - sig = append(sig, tail...) - - _, err = Deserialize(sig) - assert.EqualError(t, err, "incorrect ring size, len r: 3804, sig.NumRing: 5 sig.Size: 56759212534490939") -} - -func TestVerify1(t *testing.T) { - numRing := 5 - ringSize := 10 - s := 7 - - rings, privkeys, m, err := GenerateMultiRingParams(numRing, ringSize, s) - if err != nil { - t.Error("fail to generate rings") - } - - ringSignature, err := Sign(m, rings, privkeys, s) - if err != nil { - t.Error("fail to create ring signature") - } - - sig, err := ringSignature.Serialize() - if err != nil { - t.Error("fail to serialize input ring signature") - } - - deserializedSig, err := Deserialize(sig) - if err != nil { - t.Error("fail to deserialize ring signature") - } - - assert.True(t, Verify(deserializedSig, false), "Verify should return true") -} - -func TestDeserialize2(t *testing.T) { - numRing := 5 - ringSize := 10 - s := 7 - - rings, privkeys, m, err := GenerateMultiRingParams(numRing, ringSize, s) - if err != nil { - t.Error("fail to generate rings") - } - - ringSignature, err := Sign(m, rings, privkeys, s) - if err != nil { - t.Error("fail to create ring signature") - } - - // change one sig to the scalar field - ringSignature.S[0][0] = curve.Params().N - - sig, err := ringSignature.Serialize() - if err != nil { - t.Error("fail to serialize input ring signature") - } - - _, err = Deserialize(sig) - assert.EqualError(t, err, "failed to deserialize, invalid ring signature") -} - -func TestPadTo32Bytes(t *testing.T) { - arr := [44]byte{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34} - - // test input slice is longer than 32 bytes - assert.True(t, bytes.Equal(PadTo32Bytes(arr[0:]), arr[0:32]), "Test PadTo32Bytes longer than 32 bytes #1") - assert.True(t, bytes.Equal(PadTo32Bytes(arr[1:]), arr[1:33]), "Test PadTo32Bytes longer than 32 bytes #2") - assert.True(t, bytes.Equal(PadTo32Bytes(arr[2:]), arr[2:34]), "Test PadTo32Bytes longer than 32 bytes #3") - assert.True(t, bytes.Equal(PadTo32Bytes(arr[3:]), arr[3:35]), "Test PadTo32Bytes longer than 32 bytes #4") - assert.True(t, bytes.Equal(PadTo32Bytes(arr[4:]), arr[4:36]), "Test PadTo32Bytes longer than 32 bytes #5") - assert.True(t, bytes.Equal(PadTo32Bytes(arr[5:]), arr[5:37]), "Test PadTo32Bytes longer than 32 bytes #6") - assert.True(t, bytes.Equal(PadTo32Bytes(arr[6:]), arr[6:38]), "Test PadTo32Bytes longer than 32 bytes #7") - assert.True(t, bytes.Equal(PadTo32Bytes(arr[7:]), arr[7:39]), "Test PadTo32Bytes longer than 32 bytes #8") - assert.True(t, bytes.Equal(PadTo32Bytes(arr[8:]), arr[8:40]), "Test PadTo32Bytes longer than 32 bytes #9") - assert.True(t, bytes.Equal(PadTo32Bytes(arr[9:]), arr[9:41]), "Test PadTo32Bytes longer than 32 bytes #10") - assert.True(t, bytes.Equal(PadTo32Bytes(arr[10:]), arr[10:42]), "Test PadTo32Bytes longer than 32 bytes #11") - assert.True(t, bytes.Equal(PadTo32Bytes(arr[11:]), arr[11:43]), "Test PadTo32Bytes longer than 32 bytes #12") - - // test input slice is equal 32 bytes - assert.True(t, bytes.Equal(PadTo32Bytes(arr[0:32]), arr[0:32]), "Test PadTo32Bytes equal 32 bytes #1") - assert.True(t, bytes.Equal(PadTo32Bytes(arr[1:33]), arr[1:33]), "Test PadTo32Bytes equal 32 bytes #2") - assert.True(t, bytes.Equal(PadTo32Bytes(arr[2:34]), arr[2:34]), "Test PadTo32Bytes equal 32 bytes #3") - assert.True(t, bytes.Equal(PadTo32Bytes(arr[3:35]), arr[3:35]), "Test PadTo32Bytes equal 32 bytes #4") - assert.True(t, bytes.Equal(PadTo32Bytes(arr[4:36]), arr[4:36]), "Test PadTo32Bytes equal 32 bytes #5") - assert.True(t, bytes.Equal(PadTo32Bytes(arr[5:37]), arr[5:37]), "Test PadTo32Bytes equal 32 bytes #6") - assert.True(t, bytes.Equal(PadTo32Bytes(arr[6:38]), arr[6:38]), "Test PadTo32Bytes equal 32 bytes #7") - assert.True(t, bytes.Equal(PadTo32Bytes(arr[7:39]), arr[7:39]), "Test PadTo32Bytes equal 32 bytes #8") - assert.True(t, bytes.Equal(PadTo32Bytes(arr[8:40]), arr[8:40]), "Test PadTo32Bytes equal 32 bytes #9") - assert.True(t, bytes.Equal(PadTo32Bytes(arr[9:41]), arr[9:41]), "Test PadTo32Bytes equal 32 bytes #10") - assert.True(t, bytes.Equal(PadTo32Bytes(arr[10:42]), arr[10:42]), "Test PadTo32Bytes equal 32 bytes #11") - assert.True(t, bytes.Equal(PadTo32Bytes(arr[11:43]), arr[11:43]), "Test PadTo32Bytes equal 32 bytes #12") - assert.True(t, bytes.Equal(PadTo32Bytes(arr[12:44]), arr[12:44]), "Test PadTo32Bytes equal 32 bytes #13") - - // test input slice is shorter than 32 bytes - assert.True(t, bytes.Equal(PadTo32Bytes(arr[10:32]), arr[0:32]), "Test PadTo32Bytes shorter than 32 bytes #1") - assert.True(t, bytes.Equal(PadTo32Bytes(arr[10:33]), arr[1:33]), "Test PadTo32Bytes shorter than 32 bytes #2") - assert.True(t, bytes.Equal(PadTo32Bytes(arr[10:34]), arr[2:34]), "Test PadTo32Bytes shorter than 32 bytes #3") - assert.True(t, bytes.Equal(PadTo32Bytes(arr[10:35]), arr[3:35]), "Test PadTo32Bytes shorter than 32 bytes #4") - assert.True(t, bytes.Equal(PadTo32Bytes(arr[10:36]), arr[4:36]), "Test PadTo32Bytes shorter than 32 bytes #5") - assert.True(t, bytes.Equal(PadTo32Bytes(arr[10:37]), arr[5:37]), "Test PadTo32Bytes shorter than 32 bytes #6") - assert.True(t, bytes.Equal(PadTo32Bytes(arr[10:38]), arr[6:38]), "Test PadTo32Bytes shorter than 32 bytes #7") - assert.True(t, bytes.Equal(PadTo32Bytes(arr[10:39]), arr[7:39]), "Test PadTo32Bytes shorter than 32 bytes #8") - assert.True(t, bytes.Equal(PadTo32Bytes(arr[10:40]), arr[8:40]), "Test PadTo32Bytes shorter than 32 bytes #9") - assert.True(t, bytes.Equal(PadTo32Bytes(arr[10:41]), arr[9:41]), "Test PadTo32Bytes shorter than 32 bytes #10") -} - -func TestCurveAddNegative(t *testing.T) { - curve := crypto.S256().(*secp256k1.BitCurve) - - x1, y1 := curve.ScalarBaseMult(new(big.Int).SetUint64(uint64(2)).Bytes()) - fmt.Printf("Point(%x, %x)\n", x1, y1) - - x2 := x1 - y2 := new(big.Int).Neg(y1) // negative of point (x1,y1) - - x3, y3 := curve.Add(x1, y1, x2, y2) - fmt.Printf("Output is Point(%x, %x)\n", x3, y3) - - x0 := new(big.Int).SetUint64(uint64(0)) - y0 := new(big.Int).SetUint64(uint64(0)) // infinity - - if (x3.Cmp(x0) == 0) && (y3.Cmp(y0) == 0) { - // fmt.Printf("Correct, add negative of self should yield (0,0)") - } else { - t.Error("Incorrect, add negative of self did not yield (0,0)") - } -} - -func TestCurveAddZero(t *testing.T) { - // curve := crypto.S256() - curve := crypto.S256().(*secp256k1.BitCurve) - - x1, y1 := curve.ScalarBaseMult(new(big.Int).SetUint64(uint64(1)).Bytes()) - fmt.Printf("Point(%x, %x)\n", x1, y1) - - x0 := new(big.Int).SetUint64(uint64(0)) - y0 := new(big.Int).SetUint64(uint64(0)) // infinity - fmt.Printf("Is point (%d,%d) on the curve: %t \n", x0, y0, curve.IsOnCurve(x0, y0)) - - x2, y2 := curve.Add(x1, y1, x0, y0) - fmt.Printf("Output is Point(%x, %x)\n", x2, y2) - - if (x1.Cmp(x2) == 0) && (y1.Cmp(y2) == 0) { - // fmt.Printf("Correct, Point on curve is the same after Zero addition\n") - } else { - t.Error("Incorrect, Point on curve changed after Zero addition\n") - } -} - -func TestOnCurveVerify(t *testing.T) { - numRing := 5 - ringSize := 10 - s := 5 - rings, privkeys, m, err := GenerateMultiRingParams(numRing, ringSize, s) - ringSignature, err := Sign(m, rings, privkeys, s) - if err != nil { - t.Error("Failed to create Ring signature") - } - - valid := Verify(ringSignature, false) - if !valid { - t.Error("Incorrect, unmodified ringSignature should be valid") - } - - ringsModified := ringSignature.Ring - ringsModified[0][0].X = big.NewInt(1) - ringsModified[0][0].Y = big.NewInt(1) - valid = Verify(ringSignature, false) - if valid { - t.Error("Incorrect, modified ringSignature should be invalid") - } -} - -func TestOnCurveDeserialize(t *testing.T) { - numRing := 5 - ringSize := 10 - s := 5 - rings, privkeys, m, err := GenerateMultiRingParams(numRing, ringSize, s) - ringSignature, err := Sign(m, rings, privkeys, s) - if err != nil { - t.Error("Failed to create Ring signature") - } - - sig, err := ringSignature.Serialize() - if err != nil { - t.Error("Failed to Serialize input Ring signature") - } - _, err = Deserialize(sig) - if err != nil { - t.Error("Failed to Deserialize") - } - - ringsModified := ringSignature.Ring - ringsModified[0][0].X = big.NewInt(1) - ringsModified[0][0].Y = big.NewInt(1) - - sig, err = ringSignature.Serialize() - if err != nil { - t.Error("Failed to Serialize input Ring signature") - } - _, err = Deserialize(sig) - assert.EqualError(t, err, "failed to deserialize, invalid ring signature") -} - -func TestCurveScalarMult(t *testing.T) { - curve := crypto.S256().(*secp256k1.BitCurve) - - x, y := curve.ScalarBaseMult(curve.Params().N.Bytes()) - if x == nil && y == nil { - fmt.Println("Scalar multiplication with base point returns nil when scalar is the scalar field") - } - - x2, y2 := curve.ScalarMult(new(big.Int).SetUint64(uint64(100)), new(big.Int).SetUint64(uint64(2)), curve.Params().N.Bytes()) - if x2 == nil && y2 == nil { - fmt.Println("Scalar multiplication with a point (not necessarily on curve) returns nil when scalar is the scalar field") - } -} - -func TestNilPointerDereferencePanic(t *testing.T) { - numRing := 5 - ringSize := 10 - s := 7 - rings, privkeys, m, err := GenerateMultiRingParams(numRing, ringSize, s) - - ringSig, err := Sign(m, rings, privkeys, s) - if err != nil { - fmt.Println("Failed to set up") - } - - ringSig.S[0][0] = curve.Params().N // change one sig to the scalar field - - sig, err := ringSig.Serialize() - if err != nil { - t.Error("Failed to Serialize input Ring signature") - } - - _ , err = Deserialize(sig) - // Should failed to verify Ring signature as the signature is invalid - assert.EqualError(t, err, "failed to deserialize, invalid ring signature") -}