ceremonyclient/nekryptology/test/accumulator/ecc/main.go

161 lines
5.1 KiB
Go
Raw Normal View History

2023-07-05 05:32:28 +00:00
//
// 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!")
}
}