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  }