github.com/dusk-network/dusk-crypto@v0.1.3/rangeproof/pedersen/pedersen.go (about) 1 package pedersen 2 3 import ( 4 "encoding/binary" 5 "errors" 6 "io" 7 8 ristretto "github.com/bwesterb/go-ristretto" 9 generator "github.com/dusk-network/dusk-crypto/rangeproof/generators" 10 ) 11 12 // Pedersen represents a pedersen struct which holds 13 // the necessary information to commit a vector or a scalar to a point 14 type Pedersen struct { 15 BaseVector *generator.Generator 16 GenData []byte 17 BlindPoint ristretto.Point 18 BasePoint ristretto.Point 19 } 20 21 // New will setup the BaseVector 22 // returning a Pedersen struct 23 // genData is the byte slice, that will be used 24 // to form the unique set of generators 25 func New(genData []byte) *Pedersen { 26 gen := generator.New(genData) 27 28 var blindPoint ristretto.Point 29 var basePoint ristretto.Point 30 31 basePoint.Derive([]byte("blindPoint")) 32 blindPoint.SetBase() 33 34 return &Pedersen{ 35 BaseVector: gen, 36 GenData: genData, 37 BlindPoint: blindPoint, 38 BasePoint: basePoint, 39 } 40 } 41 42 // Commitment represents a Pedersen Commitment 43 // storing the value and the random blinding factor 44 type Commitment struct { 45 // Value is the point which has been commited to 46 Value ristretto.Point 47 // blinding factor is the blinding scalar. 48 // Note that n vectors have 1 blinding factor 49 BlindingFactor ristretto.Scalar 50 } 51 52 func (c *Commitment) Encode(w io.Writer) error { 53 return binary.Write(w, binary.BigEndian, c.Value.Bytes()) 54 } 55 56 func EncodeCommitments(w io.Writer, comms []Commitment) error { 57 lenV := uint32(len(comms)) 58 err := binary.Write(w, binary.BigEndian, lenV) 59 if err != nil { 60 return err 61 } 62 for i := range comms { 63 err := comms[i].Encode(w) 64 if err != nil { 65 return err 66 } 67 } 68 return nil 69 } 70 71 func (c *Commitment) Decode(r io.Reader) error { 72 if c == nil { 73 return errors.New("struct is nil") 74 } 75 76 var cBytes [32]byte 77 err := binary.Read(r, binary.BigEndian, &cBytes) 78 if err != nil { 79 return err 80 } 81 ok := c.Value.SetBytes(&cBytes) 82 if !ok { 83 return errors.New("could not set bytes for commitment, not an encodable point") 84 } 85 return nil 86 } 87 88 func DecodeCommitments(r io.Reader) ([]Commitment, error) { 89 90 var lenV uint32 91 err := binary.Read(r, binary.BigEndian, &lenV) 92 if err != nil { 93 return nil, err 94 } 95 96 comms := make([]Commitment, lenV) 97 98 for i := uint32(0); i < lenV; i++ { 99 err := comms[i].Decode(r) 100 if err != nil { 101 return nil, err 102 } 103 } 104 105 return comms, nil 106 } 107 108 func (c *Commitment) EqualValue(other Commitment) bool { 109 return c.Value.Equals(&other.Value) 110 } 111 112 func (c *Commitment) Equals(other Commitment) bool { 113 return c.EqualValue(other) && c.BlindingFactor.Equals(&other.BlindingFactor) 114 } 115 116 func (p *Pedersen) commitToScalars(blind *ristretto.Scalar, scalars ...ristretto.Scalar) ristretto.Point { 117 118 n := len(scalars) 119 120 var sum ristretto.Point 121 sum.SetZero() 122 123 if blind != nil { 124 125 var blindPoint ristretto.Point 126 blindPoint.ScalarMult(&p.BlindPoint, blind) 127 sum.Add(&sum, &blindPoint) 128 } 129 130 if len(p.BaseVector.Bases) < n { 131 132 diff := n - len(p.BaseVector.Bases) 133 134 p.BaseVector.Compute(uint32(diff)) 135 // num of scalars to commit should be equal or less than the number of precomputed generators 136 } 137 138 for i := 0; i < n; i++ { 139 140 bi := scalars[i] 141 142 Hi := p.BaseVector.Bases[i] 143 144 // H_i * b_i 145 product := ristretto.Point{} 146 product.ScalarMult(&Hi, &bi) 147 148 sum.Add(&sum, &product) 149 } 150 151 return sum 152 } 153 154 // CommitToScalar generates a Commitment to a scalar v, s.t. V = v * Base + blind * BlindingPoint 155 func (p *Pedersen) CommitToScalar(v ristretto.Scalar) Commitment { 156 157 // generate random blinder 158 blind := ristretto.Scalar{} 159 blind.Rand() 160 161 // v * Base 162 var vBase ristretto.Point 163 vBase.ScalarMult(&p.BasePoint, &v) 164 // blind * BlindPoint 165 var blindPoint ristretto.Point 166 blindPoint.ScalarMult(&p.BlindPoint, &blind) 167 168 var sum ristretto.Point 169 sum.SetZero() 170 sum.Add(&vBase, &blindPoint) 171 172 return Commitment{ 173 Value: sum, 174 BlindingFactor: blind, 175 } 176 } 177 178 // CommitToVectors will take n set of vectors and form a commitment to them s.t. 179 // V = aH + <v1, G1> + <v2, G2> + <v3, G3> 180 // where a is a scalar, v1 is a vector of scalars, and G1 is a vector of points 181 func (p *Pedersen) CommitToVectors(vectors ...[]ristretto.Scalar) Commitment { 182 183 // Generate random blinding factor 184 blind := ristretto.Scalar{} 185 blind.Rand() 186 187 // For each vector, we can use the commitToScalars, because a vector is just a slice of scalars 188 189 var sum ristretto.Point 190 sum.SetZero() 191 192 for i, vector := range vectors { 193 if i == 0 { 194 195 // Commit to vector + blinding factor 196 commit := p.commitToScalars(&blind, vector...) 197 sum.Add(&sum, &commit) 198 } else { 199 200 genData := append(p.GenData, uint8(i)) 201 ped2 := New(genData) 202 203 commit := ped2.commitToScalars(nil, vector...) 204 sum.Add(&sum, &commit) 205 } 206 } 207 208 return Commitment{ 209 Value: sum, 210 BlindingFactor: blind, 211 } 212 }