Skip to content

Commit

Permalink
Merge pull request #9 from dusk-network/add-mlsag
Browse files Browse the repository at this point in the history
Add mlsag package from dusk-blockchain
  • Loading branch information
jules committed Aug 21, 2019
2 parents 5665f7b + 8271e6d commit 3d78424
Show file tree
Hide file tree
Showing 11 changed files with 1,087 additions and 0 deletions.
63 changes: 63 additions & 0 deletions mlsag/dualkey.go
@@ -0,0 +1,63 @@
package mlsag

import (
"errors"

ristretto "github.com/bwesterb/go-ristretto"
)

// DualKey is a specific instantiation of mlsag where the second key is
// a commitment to zero
type DualKey struct {
Proof
dualkeys []ristretto.Scalar
}

func NewDualKey() *DualKey {
return &DualKey{
Proof: Proof{},
dualkeys: make([]ristretto.Scalar, 2),
}
}

func (d *DualKey) SetPrimaryKey(key ristretto.Scalar) ristretto.Point {
d.dualkeys[0] = key
return privKeyToPubKey(key)
}

func (d *DualKey) SetCommToZero(key ristretto.Scalar) ristretto.Point {
d.dualkeys[1] = key
return privKeyToPubKey(key)
}

func (d *DualKey) SetMsg(msg []byte) {
d.Proof.msg = msg
}

// SubCommToZero subtracts p from every point from the second public key
// in the matrix of decoy pubkeys
func (d *DualKey) SubCommToZero(p ristretto.Point) {
for i := range d.pubKeysMatrix {
commToZero := &d.pubKeysMatrix[i].keys[1]
commToZero.Sub(commToZero, &p)
}
}

func (d *DualKey) Prove() (*Signature, ristretto.Point, error) {

if (d.dualkeys[0].IsNonZeroI() == 0) || (d.dualkeys[1].IsNonZeroI() == 0) {
return nil, ristretto.Point{}, errors.New("primary key or commitment to zero cannot be zero")
}

d.AddSecret(d.dualkeys[0])
d.AddSecret(d.dualkeys[1])

sig, keyimage, err := d.prove(true)
if err != nil {
return nil, ristretto.Point{}, err
}
if len(keyimage) != 1 {
return nil, ristretto.Point{}, errors.New("dual key mlsag must only contain one key image")
}
return sig, keyimage[0], err
}
72 changes: 72 additions & 0 deletions mlsag/dualkey_test.go
@@ -0,0 +1,72 @@
package mlsag

import (
"testing"

ristretto "github.com/bwesterb/go-ristretto"
"github.com/stretchr/testify/assert"
)

func TestDualKey(t *testing.T) {

dk := generateRandDualKeyProof(20)

sig, keyImage, err := dk.Prove()
sig.Verify([]ristretto.Point{keyImage})
assert.Nil(t, err)
}

func TestSubCommToZero(t *testing.T) {
dk := generateRandDualKeyProof(20)

var oldPoints []ristretto.Point

// Save all of the old keys
for i := range dk.pubKeysMatrix {
oldPoint := dk.pubKeysMatrix[i].keys[1]
oldPoints = append(oldPoints, oldPoint)
}

// Generate random point and subtract from commitment to zero column
var x ristretto.Point
x.Rand()
dk.SubCommToZero(x)

for i := range dk.pubKeysMatrix {
var expectedPoint ristretto.Point

// Fetch value of the second key
// before subtracting x
newPoint := dk.pubKeysMatrix[i].keys[1]

// Calculate expected point
expectedPoint.Sub(&oldPoints[i], &x)

assert.True(t, expectedPoint.Equals(&newPoint))
}
}

func generateRandDualKeyProof(numUsers int) *DualKey {
proof := NewDualKey()

numDecoys := numUsers - 1
numKeys := 2

// Generate and add decoys to proof
matrixPubKeys := generateDecoys(numDecoys, numKeys)
for i := 0; i < len(matrixPubKeys); i++ {
pubKeys := matrixPubKeys[i]
proof.AddDecoy(pubKeys)
}

// Generate and add private keys to proof
var primaryKey, commToZero ristretto.Scalar
primaryKey.Rand()
commToZero.Rand()
proof.SetPrimaryKey(primaryKey)
proof.SetCommToZero(commToZero)

proof.msg = []byte("hello world")

return proof
}

0 comments on commit 3d78424

Please sign in to comment.