mirror of
https://source.quilibrium.com/quilibrium/ceremonyclient.git
synced 2024-12-30 18:35:18 +00:00
161 lines
5.1 KiB
Go
161 lines
5.1 KiB
Go
//
|
|
// Copyright Coinbase, Inc. All Rights Reserved.
|
|
//
|
|
// SPDX-License-Identifier: Apache-2.0
|
|
//
|
|
|
|
package main
|
|
|
|
import (
|
|
"bufio"
|
|
"encoding/hex"
|
|
"fmt"
|
|
"os"
|
|
|
|
"source.quilibrium.com/quilibrium/monorepo/nekryptology/pkg/accumulator"
|
|
"source.quilibrium.com/quilibrium/monorepo/nekryptology/pkg/core/curves"
|
|
)
|
|
|
|
func main() {
|
|
curve := curves.BLS12381(&curves.PointBls12381G1{})
|
|
sk, _ := new(accumulator.SecretKey).New(curve, []byte("1234567890"))
|
|
pk, _ := sk.GetPublicKey(curve)
|
|
skBytes, _ := sk.MarshalBinary()
|
|
pkBytes, _ := pk.MarshalBinary()
|
|
fmt.Println("Coinbase generates secret key and public key pair...")
|
|
fmt.Printf("Coinbase publishes public key %v\n", hex.EncodeToString(pkBytes))
|
|
fmt.Printf("Coinbase retains secret key %v\n", hex.EncodeToString(skBytes))
|
|
|
|
// Enter initial elements
|
|
fmt.Println("Coinbase starts initiating an accumulator")
|
|
var userInput []string
|
|
scanner := bufio.NewScanner(os.Stdin)
|
|
fmt.Println("Coinbase enters the elements accumulated in the initial accumulator, press enter to start")
|
|
for scanner.Scan() {
|
|
fmt.Println("Enter a string or stop")
|
|
line := scanner.Text()
|
|
if line == "stop" {
|
|
break
|
|
}
|
|
userInput = append(userInput, line+"\n")
|
|
}
|
|
elements := make([]accumulator.Element, len(userInput))
|
|
for i := 0; i < len(elements); i++ {
|
|
elements[i] = curve.Scalar.Hash([]byte(userInput[i]))
|
|
}
|
|
|
|
// Coinbase initiates a new accumulator with elements
|
|
acc, err := new(accumulator.Accumulator).WithElements(curve, sk, elements)
|
|
if err != nil || acc == nil {
|
|
panic(err)
|
|
}
|
|
accBytes, _ := acc.MarshalBinary()
|
|
fmt.Printf("Accumulator Initiated! Value is %v\n", hex.EncodeToString(accBytes))
|
|
|
|
// Initiate a new membership witness
|
|
fmt.Println("Coinbase issues a membership witness to a user")
|
|
fmt.Println("Coinbase enters the element that a membership witness is associated with")
|
|
reader := bufio.NewReader(os.Stdin)
|
|
witnessInput, _ := reader.ReadString('\n')
|
|
witElement := curve.Scalar.Hash([]byte(witnessInput))
|
|
wit, err := new(accumulator.MembershipWitness).New(witElement, acc, sk)
|
|
if err != nil {
|
|
panic(err)
|
|
}
|
|
fmt.Printf("Coinbase issued membership witness associated to element %v\n", witnessInput)
|
|
|
|
// User uses the witness to verify the membership
|
|
fmt.Println("The user can use the witness to verify the associated element is accumulated")
|
|
fmt.Println("verifying...")
|
|
err = wit.Verify(pk, acc)
|
|
if err != nil {
|
|
panic(err)
|
|
}
|
|
fmt.Println("membership verification succeeds!")
|
|
|
|
// Batch Update accumulator and membership witness
|
|
fmt.Println("Coinbase could batch update the accumulator")
|
|
fmt.Println("That is, Coinbase can add/delete multiple elements together")
|
|
var addInput []string
|
|
fmt.Println("Enter elements that you want to batch add, press enter the start")
|
|
for scanner.Scan() {
|
|
fmt.Println("Enter a string or stop")
|
|
line := scanner.Text()
|
|
if line == "stop" {
|
|
break
|
|
}
|
|
addInput = append(addInput, line+"\n")
|
|
}
|
|
additions := make([]accumulator.Element, len(addInput))
|
|
for i := 0; i < len(additions); i++ {
|
|
additions[i] = curve.Scalar.Hash([]byte(addInput[i]))
|
|
}
|
|
|
|
var deleteInput []string
|
|
fmt.Println("Enter elements that you want to batch delete, press enter to start")
|
|
for scanner.Scan() {
|
|
fmt.Println("Enter a string or stop")
|
|
line := scanner.Text()
|
|
if line == "stop" {
|
|
break
|
|
}
|
|
deleteInput = append(deleteInput, line+"\n")
|
|
}
|
|
deletions := make([]accumulator.Element, len(deleteInput))
|
|
for i := 0; i < len(deletions); i++ {
|
|
deletions[i] = curve.Scalar.Hash([]byte(deleteInput[i]))
|
|
}
|
|
|
|
// Batch update accumulator
|
|
_, coefficients, err := acc.Update(sk, additions, deletions)
|
|
if err != nil {
|
|
panic(err)
|
|
}
|
|
accBytes, _ = acc.MarshalBinary()
|
|
fmt.Println("Accumulator batch-update succeeds!")
|
|
fmt.Printf("The new accumulator value is %v\n", hex.EncodeToString(accBytes))
|
|
|
|
// Batch update witness accordingly
|
|
fmt.Println("User should batch-update his/her witness accordingly. This can be done by a trusted third party")
|
|
fmt.Println("so that the witness is still usable to verify the associated element is accumulated")
|
|
_, err = wit.BatchUpdate(additions, deletions, coefficients)
|
|
if err != nil {
|
|
panic(err)
|
|
}
|
|
err = wit.Verify(pk, acc)
|
|
if err != nil {
|
|
panic(err)
|
|
}
|
|
fmt.Println("Verification succeeds after batch-update")
|
|
|
|
// Proof ownership of witness
|
|
fmt.Println("The user can also generate a zero-knowledge proof proving the ownership of witness")
|
|
params, err := new(accumulator.ProofParams).New(curve, pk, []byte("entropy"))
|
|
if err != nil {
|
|
panic(err)
|
|
}
|
|
mpc, err := new(accumulator.MembershipProofCommitting).New(wit, acc, params, pk)
|
|
if err != nil {
|
|
panic(err)
|
|
}
|
|
challenge := curve.Scalar.Hash(mpc.GetChallengeBytes())
|
|
proof := mpc.GenProof(challenge)
|
|
finalProof, err := proof.Finalize(acc, params, pk, challenge)
|
|
if err != nil {
|
|
panic(err)
|
|
}
|
|
proofBytes, err := proof.MarshalBinary()
|
|
if err != nil {
|
|
panic(err)
|
|
}
|
|
fmt.Println("ZK proof successfully generated!")
|
|
fmt.Printf("ZK proof value is %v\n", hex.EncodeToString(proofBytes))
|
|
fmt.Println("Verifying....")
|
|
challenge2 := finalProof.GetChallenge(curve)
|
|
if challenge.Cmp(challenge2) == 0 {
|
|
fmt.Println("proof verification succeeds!")
|
|
} else {
|
|
fmt.Println("proof verification fails!")
|
|
}
|
|
}
|