Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implement MPC for secure Plonk setup #16

Open
wants to merge 34 commits into
base: dev
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
34 commits
Select commit Hold shift + click to select a range
72a0459
[CI] Fix ECS deployment
blam23 Aug 20, 2021
b83a9cc
Streamline SRS creation logic
myrade Aug 23, 2021
406ae66
Implement circuit library map and AddCircuit test
myrade Aug 13, 2021
c16db39
Store and query circuit identifiers in lower case
myrade Aug 17, 2021
516d87f
Update gnark
myrade Aug 23, 2021
b2f4855
Wip MPC
myrade Aug 23, 2021
f02cea6
Update gnark for groth16 performance
myrade Aug 27, 2021
f045285
Incremental ceremony update per feedback
myrade Aug 27, 2021
1dc0bbf
Ceremony WIP
myrade Aug 27, 2021
e0976a2
Make ceremony content agnostic
myrade Aug 30, 2021
78bbb1d
Remove unused e2e_test helper
myrade Aug 30, 2021
69a8677
Add docs link to readme
kthomas Aug 31, 2021
e96261f
Update readme
kthomas Aug 31, 2021
d3821af
Add go report card to readme
kthomas Sep 2, 2021
f64ff1d
Wip ceremony-circuit integration
myrade Sep 2, 2021
5368721
Upgrade to jetstream
kthomas Sep 3, 2021
a6ecc93
Merge branch 'dev'
kthomas Sep 3, 2021
daa3d50
Fix hostname collision in docker-compose
kthomas Sep 3, 2021
a8c9f47
Fix jetstream subscription syntax
kthomas Sep 3, 2021
608befe
Fix privacy nats container names in debug docker-compose
kthomas Sep 3, 2021
d5d83be
Streamline SRS creation logic
myrade Aug 23, 2021
927c4d7
Implement circuit library map and AddCircuit test
myrade Aug 13, 2021
0cc3402
Store and query circuit identifiers in lower case
myrade Aug 17, 2021
8d39451
Update gnark
myrade Aug 23, 2021
c020fb7
Wip MPC
myrade Aug 23, 2021
4f5bedb
Update gnark for groth16 performance
myrade Aug 27, 2021
2ad1b51
Incremental ceremony update per feedback
myrade Aug 27, 2021
e22bd7d
Ceremony WIP
myrade Aug 27, 2021
6ece611
Make ceremony content agnostic
myrade Aug 30, 2021
a5960e3
Remove unused e2e_test helper
myrade Aug 30, 2021
d351df0
Wip ceremony-circuit integration
myrade Sep 2, 2021
7e662c5
Merge branch 'plonk-mpc' of https://github.com/provideplatform/privac…
myrade Sep 7, 2021
d2d8d73
Update gnark
myrade Sep 7, 2021
e1ce018
Upgrade ceremony consumer to jetstream
myrade Sep 8, 2021
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 6 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1,10 +1,15 @@
# privacy

[![Go Report Card](https://goreportcard.com/badge/github.com/provideplatform/privacy)](https://goreportcard.com/report/github.com/provideplatform/privacy)

Microservice providing a circuit registry and compilation, trusted setup, verification and proving capabilities for zero-knowledge circuits.

## Supported Circuit Providers

The following zkSNARK toolboxes are supported:

- Gnark
- ZoKrates

## Documentation

See the privacy documentation [here](https://docs.provide.services/privacy).
199 changes: 199 additions & 0 deletions ceremony/ceremony.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,199 @@
package ceremony

import (
"bytes"
"encoding/hex"
"encoding/json"
"fmt"
"sort"

"github.com/jinzhu/gorm"
provide "github.com/provideplatform/provide-go/api"
"github.com/provideplatform/provide-go/api/vault"

dbconf "github.com/kthomas/go-db-config"
natsutil "github.com/kthomas/go-natsutil"
uuid "github.com/kthomas/go.uuid"
"github.com/provideplatform/privacy/common"
)

const defaultWordSize = 32

// const ceremonyStatusComplete = "complete"
// const ceremonyStatusCreated = "created"
// const ceremonyStatusFailed = "failed"
// const ceremonyStatusInit = "init"
const ceremonyStatusPending = "pending"

// CeremonyConfig
type CeremonyConfig struct {
Block *uint64 `json:"block"` // number of block being used for entropy
ExpectedEntropy int `json:"expected_entropy"` // expected number of bytes of entropy from all parties and any random beacon as required
WordSize int `json:"word_size"`
}

// Ceremony model
type Ceremony struct {
provide.Model

Config CeremonyConfig `json:"config"`
Parties []string `json:"parties"`
Status *string `json:"status"`
entropy []byte `json:"-"`
ownEntropy []byte `json:"-"`
}

// AddParty creates a ceremony
func (c *Ceremony) AddParty(index int, other *Ceremony) error {
// TODO: receive entropy from other parties
if c.Config.WordSize != other.Config.WordSize {
return fmt.Errorf("other word size %d does not match expected word size %d", other.Config.WordSize, c.Config.WordSize)
}

if len(other.ownEntropy) == 0 || bytes.Equal(other.ownEntropy, make([]byte, other.Config.WordSize)) {
return fmt.Errorf("other party ceremony has uninitialized entropy value")
}

copy(c.entropy[index*c.Config.WordSize:], other.ownEntropy)
return nil
}

// CeremonyFactory creates a new Ceremony object
func CeremonyFactory(parties []string, config *CeremonyConfig) *Ceremony {
ceremony := &Ceremony{
Parties: parties,
Config: *config,
}

sort.Strings(ceremony.Parties)

if ceremony.Config.WordSize <= 0 {
ceremony.Config.WordSize = defaultWordSize
}

if ceremony.Config.ExpectedEntropy <= 0 {
ceremony.Config.ExpectedEntropy = ceremony.Config.WordSize * (len(parties) + 1)
}

ceremony.entropy = make([]byte, ceremony.Config.ExpectedEntropy)

return ceremony
}

// CompareEntropy compares entropy value to that of other Ceremony
func (c *Ceremony) CompareEntropy(other *Ceremony) bool {
return bytes.Equal(c.entropy, other.entropy)
}

func (c *Ceremony) Create(variables interface{}) bool {
if !c.validate() {
return false
}

db := dbconf.DatabaseConnection()

if db.NewRecord(c) {
result := db.Create(&c)
rowsAffected := result.RowsAffected
errors := result.GetErrors()
if len(errors) > 0 {
for _, err := range errors {
c.Errors = append(c.Errors, &provide.Error{
Message: common.StringOrNil(err.Error()),
})
}
}
if !db.NewRecord(c) {
success := rowsAffected > 0
if success {
payload, _ := json.Marshal(map[string]interface{}{
"ceremony_id": c.ID.String(),
})
natsutil.NatsStreamingPublish(natsCeremonyPendingSubject, payload)
c.updateStatus(db, ceremonyStatusPending, nil)
}

return success
}
}

return false
}

// enrich the ceremony
func (c *Ceremony) enrich() error {
return nil
}

// GenerateEntropy generates entropy at party index
func (c *Ceremony) GenerateEntropy() error {
entropy, err := common.RandomBytes(c.Config.WordSize)
if err != nil {
return fmt.Errorf("unable to generate entropy for mpc ceremony; %s", err.Error())
}

c.ownEntropy = entropy

return nil
}

// GetEntropyFromBeacon gets the requested entropy by block number
func (c *Ceremony) GetEntropyFromBeacon(block uint64) error {

// TODO: get beacon entropy by block number, this will be same for all parties
entropy := []byte("test block entropy blahblahblah.")

// insert block entropy at end
copy(c.entropy[len(c.entropy)-c.Config.WordSize:], entropy)
return nil
}

// StoreEntropy stores entropy in vault
func (c *Ceremony) StoreEntropy(token, vaultID, name, description, secretType *string) (*uuid.UUID, error) {
// TODO: make sure entropy value has no uninitialized/all-zero words

secret, err := vault.CreateSecret(
*token,
*vaultID,
hex.EncodeToString(c.entropy),
*name,
*description,
*secretType,
)
if err != nil {
return nil, fmt.Errorf("failed to store entropy for ceremony %s in vault %s; %s", c.ID.String(), *vaultID, err.Error())
}
return &secret.ID, nil
}

// SubmitEntropy broadcasts entropy to other parties
func (c *Ceremony) SubmitEntropy() error {
// TODO: broadcast entropy to other parties
return nil
}

// updateStatus updates the circuit status and optional description
func (c *Ceremony) updateStatus(db *gorm.DB, status string, description *string) error {
// FIXME-- use distributed lock here
c.Status = common.StringOrNil(status)
// c.Description = description
if !db.NewRecord(&c) {
result := db.Save(&c)
errors := result.GetErrors()
if len(errors) > 0 {
for _, err := range errors {
c.Errors = append(c.Errors, &provide.Error{
Message: common.StringOrNil(err.Error()),
})
}
return errors[0]
}
}
return nil
}

func (c *Ceremony) validate() bool {
c.Errors = make([]*provide.Error, 0)

return len(c.Errors) == 0
}
Loading