- Introduced `ibc_example.rs` demonstrating Inter-Blockchain Communication operations including cross-chain transfers, channel management, packet handling, and relayer operations. - Introduced `zk_example.rs` showcasing Zero-Knowledge proof operations such as circuit compilation, proof generation and verification, and on-chain verification with multiple proving systems.
662 lines
19 KiB
Go
662 lines
19 KiB
Go
// Package main demonstrates the Synor ZK SDK for Go
|
|
//
|
|
// This example covers Zero-Knowledge proof operations:
|
|
// - Circuit compilation
|
|
// - Proof generation and verification
|
|
// - Groth16, PLONK, and STARK proving systems
|
|
// - Recursive proofs
|
|
// - On-chain verification
|
|
package main
|
|
|
|
import (
|
|
"context"
|
|
"fmt"
|
|
"log"
|
|
"os"
|
|
"time"
|
|
|
|
"github.com/synor/sdk-go/zk"
|
|
)
|
|
|
|
func main() {
|
|
// Initialize client
|
|
config := zk.Config{
|
|
APIKey: getEnv("SYNOR_API_KEY", "your-api-key"),
|
|
Endpoint: "https://zk.synor.io/v1",
|
|
Timeout: 120 * time.Second, // ZK ops can be slow
|
|
Retries: 3,
|
|
Debug: false,
|
|
DefaultProvingSystem: zk.ProvingSystemGroth16,
|
|
}
|
|
|
|
client, err := zk.NewClient(config)
|
|
if err != nil {
|
|
log.Fatalf("Failed to create client: %v", err)
|
|
}
|
|
defer client.Close()
|
|
|
|
ctx := context.Background()
|
|
|
|
// Check service health
|
|
healthy, err := client.HealthCheck(ctx)
|
|
if err != nil {
|
|
log.Printf("Health check failed: %v", err)
|
|
} else {
|
|
fmt.Printf("Service healthy: %v\n\n", healthy)
|
|
}
|
|
|
|
// Run examples
|
|
circuitExample(ctx, client)
|
|
proofExample(ctx, client)
|
|
provingSystemsExample(ctx, client)
|
|
recursiveProofExample(ctx, client)
|
|
onChainVerificationExample(ctx, client)
|
|
setupExample(ctx, client)
|
|
}
|
|
|
|
func circuitExample(ctx context.Context, client *zk.Client) {
|
|
fmt.Println("=== Circuit Compilation ===")
|
|
|
|
// Circom circuit example: prove knowledge of preimage
|
|
circomCircuit := `
|
|
pragma circom 2.1.0;
|
|
|
|
template HashPreimage() {
|
|
signal input preimage;
|
|
signal input hash;
|
|
|
|
// Simplified hash computation (in reality, use proper hash)
|
|
signal preimageSquared;
|
|
preimageSquared <== preimage * preimage;
|
|
|
|
// Constrain that hash matches
|
|
hash === preimageSquared;
|
|
}
|
|
|
|
component main {public [hash]} = HashPreimage();
|
|
`
|
|
|
|
// Compile circuit
|
|
fmt.Println("Compiling Circom circuit...")
|
|
compiled, err := client.Circuits.Compile(ctx, &zk.CompileRequest{
|
|
Code: circomCircuit,
|
|
Format: zk.CircuitFormatCircom,
|
|
Name: "hash_preimage",
|
|
ProvingSystem: zk.ProvingSystemGroth16,
|
|
})
|
|
if err != nil {
|
|
log.Printf("Failed to compile circuit: %v", err)
|
|
return
|
|
}
|
|
|
|
fmt.Println("Circuit compiled:")
|
|
fmt.Printf(" Circuit ID: %s\n", compiled.CircuitID)
|
|
fmt.Printf(" Constraints: %d\n", compiled.ConstraintCount)
|
|
fmt.Printf(" Public inputs: %d\n", compiled.PublicInputCount)
|
|
fmt.Printf(" Private inputs: %d\n", compiled.PrivateInputCount)
|
|
fmt.Printf(" Proving key size: %d bytes\n", compiled.ProvingKeySize)
|
|
fmt.Printf(" Verification key size: %d bytes\n", compiled.VerificationKeySize)
|
|
|
|
// List circuits
|
|
circuits, err := client.Circuits.List(ctx)
|
|
if err != nil {
|
|
log.Printf("Failed to list circuits: %v", err)
|
|
return
|
|
}
|
|
fmt.Printf("\nYour circuits: %d\n", len(circuits))
|
|
for _, circuit := range circuits {
|
|
fmt.Printf(" %s (%s)\n", circuit.Name, circuit.CircuitID)
|
|
}
|
|
|
|
// Get circuit details
|
|
details, err := client.Circuits.Get(ctx, compiled.CircuitID)
|
|
if err != nil {
|
|
log.Printf("Failed to get circuit details: %v", err)
|
|
return
|
|
}
|
|
fmt.Println("\nCircuit details:")
|
|
fmt.Printf(" Format: %s\n", details.Format)
|
|
fmt.Printf(" Proving system: %s\n", details.ProvingSystem)
|
|
fmt.Printf(" Created: %s\n", details.CreatedAt)
|
|
|
|
// Download proving key
|
|
provingKey, err := client.Circuits.GetProvingKey(ctx, compiled.CircuitID)
|
|
if err != nil {
|
|
log.Printf("Failed to get proving key: %v", err)
|
|
return
|
|
}
|
|
fmt.Printf("\nProving key downloaded: %d bytes\n", len(provingKey))
|
|
|
|
// Download verification key
|
|
verificationKey, err := client.Circuits.GetVerificationKey(ctx, compiled.CircuitID)
|
|
if err != nil {
|
|
log.Printf("Failed to get verification key: %v", err)
|
|
return
|
|
}
|
|
fmt.Printf("Verification key downloaded: %d bytes\n", len(verificationKey))
|
|
|
|
fmt.Println()
|
|
}
|
|
|
|
func proofExample(ctx context.Context, client *zk.Client) {
|
|
fmt.Println("=== Proof Generation ===")
|
|
|
|
// First, compile a simple circuit
|
|
circuit := `
|
|
pragma circom 2.1.0;
|
|
|
|
template Multiplier() {
|
|
signal input a;
|
|
signal input b;
|
|
signal output c;
|
|
|
|
c <== a * b;
|
|
}
|
|
|
|
component main {public [c]} = Multiplier();
|
|
`
|
|
|
|
compiled, err := client.Circuits.Compile(ctx, &zk.CompileRequest{
|
|
Code: circuit,
|
|
Format: zk.CircuitFormatCircom,
|
|
Name: "multiplier",
|
|
ProvingSystem: zk.ProvingSystemGroth16,
|
|
})
|
|
if err != nil {
|
|
log.Printf("Failed to compile circuit: %v", err)
|
|
return
|
|
}
|
|
|
|
// Generate proof
|
|
fmt.Println("Generating proof...")
|
|
startTime := time.Now()
|
|
|
|
proof, err := client.Proofs.Generate(ctx, &zk.GenerateProofRequest{
|
|
CircuitID: compiled.CircuitID,
|
|
Inputs: map[string]string{"a": "3", "b": "7"},
|
|
})
|
|
if err != nil {
|
|
log.Printf("Failed to generate proof: %v", err)
|
|
return
|
|
}
|
|
|
|
proofTime := time.Since(startTime)
|
|
fmt.Printf("Proof generated in %v\n", proofTime)
|
|
fmt.Printf(" Proof ID: %s\n", proof.ProofID)
|
|
fmt.Printf(" Proof size: %d bytes\n", len(proof.Proof))
|
|
fmt.Printf(" Public signals: %v\n", proof.PublicSignals)
|
|
|
|
// Verify proof
|
|
fmt.Println("\nVerifying proof...")
|
|
verifyStart := time.Now()
|
|
|
|
isValid, err := client.Proofs.Verify(ctx, &zk.VerifyRequest{
|
|
CircuitID: compiled.CircuitID,
|
|
Proof: proof.Proof,
|
|
PublicSignals: proof.PublicSignals,
|
|
})
|
|
if err != nil {
|
|
log.Printf("Failed to verify proof: %v", err)
|
|
return
|
|
}
|
|
|
|
verifyTime := time.Since(verifyStart)
|
|
fmt.Printf("Verification completed in %v\n", verifyTime)
|
|
fmt.Printf(" Valid: %v\n", isValid)
|
|
|
|
// Verify with wrong public signals (should fail)
|
|
fmt.Println("\nVerifying with wrong signals...")
|
|
invalidResult, err := client.Proofs.Verify(ctx, &zk.VerifyRequest{
|
|
CircuitID: compiled.CircuitID,
|
|
Proof: proof.Proof,
|
|
PublicSignals: []string{"42"}, // Wrong answer
|
|
})
|
|
if err != nil {
|
|
log.Printf("Failed to verify with wrong signals: %v", err)
|
|
return
|
|
}
|
|
fmt.Printf(" Valid: %v (expected false)\n", invalidResult)
|
|
|
|
// Get proof status
|
|
status, err := client.Proofs.GetStatus(ctx, proof.ProofID)
|
|
if err != nil {
|
|
log.Printf("Failed to get proof status: %v", err)
|
|
return
|
|
}
|
|
fmt.Println("\nProof status:")
|
|
fmt.Printf(" State: %s\n", status.State)
|
|
fmt.Printf(" Verified: %v\n", status.Verified)
|
|
fmt.Printf(" Created: %s\n", status.CreatedAt)
|
|
|
|
// List proofs
|
|
proofs, err := client.Proofs.List(ctx, compiled.CircuitID)
|
|
if err != nil {
|
|
log.Printf("Failed to list proofs: %v", err)
|
|
return
|
|
}
|
|
fmt.Printf("\nProofs for circuit: %d\n", len(proofs))
|
|
|
|
fmt.Println()
|
|
}
|
|
|
|
func provingSystemsExample(ctx context.Context, client *zk.Client) {
|
|
fmt.Println("=== Proving Systems Comparison ===")
|
|
|
|
// Simple circuit for comparison
|
|
circuit := `
|
|
pragma circom 2.1.0;
|
|
|
|
template Comparison() {
|
|
signal input x;
|
|
signal input y;
|
|
signal output sum;
|
|
|
|
sum <== x + y;
|
|
}
|
|
|
|
component main {public [sum]} = Comparison();
|
|
`
|
|
|
|
systems := []struct {
|
|
system zk.ProvingSystem
|
|
name string
|
|
}{
|
|
{zk.ProvingSystemGroth16, "GROTH16"},
|
|
{zk.ProvingSystemPLONK, "PLONK"},
|
|
{zk.ProvingSystemSTARK, "STARK"},
|
|
}
|
|
|
|
fmt.Println("Comparing proving systems:\n")
|
|
|
|
for _, s := range systems {
|
|
fmt.Printf("%s:\n", s.name)
|
|
|
|
// Compile for this system
|
|
compiled, err := client.Circuits.Compile(ctx, &zk.CompileRequest{
|
|
Code: circuit,
|
|
Format: zk.CircuitFormatCircom,
|
|
Name: fmt.Sprintf("comparison_%s", s.name),
|
|
ProvingSystem: s.system,
|
|
})
|
|
if err != nil {
|
|
log.Printf("Failed to compile for %s: %v", s.name, err)
|
|
continue
|
|
}
|
|
|
|
// Generate proof
|
|
proofStart := time.Now()
|
|
proof, err := client.Proofs.Generate(ctx, &zk.GenerateProofRequest{
|
|
CircuitID: compiled.CircuitID,
|
|
Inputs: map[string]string{"x": "10", "y": "20"},
|
|
})
|
|
if err != nil {
|
|
log.Printf("Failed to generate proof for %s: %v", s.name, err)
|
|
continue
|
|
}
|
|
proofTime := time.Since(proofStart)
|
|
|
|
// Verify proof
|
|
verifyStart := time.Now()
|
|
_, err = client.Proofs.Verify(ctx, &zk.VerifyRequest{
|
|
CircuitID: compiled.CircuitID,
|
|
Proof: proof.Proof,
|
|
PublicSignals: proof.PublicSignals,
|
|
})
|
|
if err != nil {
|
|
log.Printf("Failed to verify proof for %s: %v", s.name, err)
|
|
continue
|
|
}
|
|
verifyTime := time.Since(verifyStart)
|
|
|
|
fmt.Printf(" Setup: %dms\n", compiled.SetupTime)
|
|
fmt.Printf(" Proof time: %v\n", proofTime)
|
|
fmt.Printf(" Verify time: %v\n", verifyTime)
|
|
fmt.Printf(" Proof size: %d bytes\n", len(proof.Proof))
|
|
fmt.Printf(" Verification key: %d bytes\n", compiled.VerificationKeySize)
|
|
fmt.Println()
|
|
}
|
|
|
|
fmt.Println("Summary:")
|
|
fmt.Println(" Groth16: Smallest proofs, fast verification, trusted setup required")
|
|
fmt.Println(" PLONK: Universal setup, flexible, moderate proof size")
|
|
fmt.Println(" STARK: No trusted setup, largest proofs, quantum resistant")
|
|
|
|
fmt.Println()
|
|
}
|
|
|
|
func recursiveProofExample(ctx context.Context, client *zk.Client) {
|
|
fmt.Println("=== Recursive Proofs ===")
|
|
|
|
// Inner circuit
|
|
innerCircuit := `
|
|
pragma circom 2.1.0;
|
|
|
|
template Inner() {
|
|
signal input x;
|
|
signal output y;
|
|
y <== x * x;
|
|
}
|
|
|
|
component main {public [y]} = Inner();
|
|
`
|
|
|
|
// Compile inner circuit
|
|
inner, err := client.Circuits.Compile(ctx, &zk.CompileRequest{
|
|
Code: innerCircuit,
|
|
Format: zk.CircuitFormatCircom,
|
|
Name: "inner_circuit",
|
|
ProvingSystem: zk.ProvingSystemGroth16,
|
|
})
|
|
if err != nil {
|
|
log.Printf("Failed to compile inner circuit: %v", err)
|
|
return
|
|
}
|
|
|
|
// Generate multiple proofs to aggregate
|
|
fmt.Println("Generating proofs to aggregate...")
|
|
var proofsToAggregate []zk.ProofData
|
|
for i := 1; i <= 4; i++ {
|
|
proof, err := client.Proofs.Generate(ctx, &zk.GenerateProofRequest{
|
|
CircuitID: inner.CircuitID,
|
|
Inputs: map[string]string{"x": fmt.Sprintf("%d", i)},
|
|
})
|
|
if err != nil {
|
|
log.Printf("Failed to generate proof %d: %v", i, err)
|
|
continue
|
|
}
|
|
proofsToAggregate = append(proofsToAggregate, zk.ProofData{
|
|
Proof: proof.Proof,
|
|
PublicSignals: proof.PublicSignals,
|
|
})
|
|
fmt.Printf(" Proof %d: y = %s\n", i, proof.PublicSignals[0])
|
|
}
|
|
|
|
// Aggregate proofs recursively
|
|
fmt.Println("\nAggregating proofs...")
|
|
aggregated, err := client.Proofs.Aggregate(ctx, &zk.AggregateRequest{
|
|
CircuitID: inner.CircuitID,
|
|
Proofs: proofsToAggregate,
|
|
AggregationType: "recursive",
|
|
})
|
|
if err != nil {
|
|
log.Printf("Failed to aggregate proofs: %v", err)
|
|
return
|
|
}
|
|
|
|
originalSize := 0
|
|
for _, p := range proofsToAggregate {
|
|
originalSize += len(p.Proof)
|
|
}
|
|
|
|
fmt.Println("Aggregated proof:")
|
|
fmt.Printf(" Proof ID: %s\n", aggregated.ProofID)
|
|
fmt.Printf(" Aggregated count: %d\n", aggregated.AggregatedCount)
|
|
fmt.Printf(" Proof size: %d bytes\n", len(aggregated.Proof))
|
|
fmt.Printf(" Size reduction: %.1f%%\n", (1-float64(len(aggregated.Proof))/float64(originalSize))*100)
|
|
|
|
// Verify aggregated proof
|
|
publicSignalsList := make([][]string, len(proofsToAggregate))
|
|
for i, p := range proofsToAggregate {
|
|
publicSignalsList[i] = p.PublicSignals
|
|
}
|
|
|
|
isValid, err := client.Proofs.VerifyAggregated(ctx, &zk.VerifyAggregatedRequest{
|
|
CircuitID: inner.CircuitID,
|
|
Proof: aggregated.Proof,
|
|
PublicSignalsList: publicSignalsList,
|
|
})
|
|
if err != nil {
|
|
log.Printf("Failed to verify aggregated proof: %v", err)
|
|
return
|
|
}
|
|
fmt.Printf("\nAggregated proof valid: %v\n", isValid)
|
|
|
|
// Batch verification (verify multiple proofs in one operation)
|
|
fmt.Println("\nBatch verification...")
|
|
batchResult, err := client.Proofs.BatchVerify(ctx, &zk.BatchVerifyRequest{
|
|
CircuitID: inner.CircuitID,
|
|
Proofs: proofsToAggregate,
|
|
})
|
|
if err != nil {
|
|
log.Printf("Failed to batch verify: %v", err)
|
|
return
|
|
}
|
|
fmt.Printf(" All valid: %v\n", batchResult.AllValid)
|
|
fmt.Printf(" Results: %v\n", batchResult.Results)
|
|
|
|
fmt.Println()
|
|
}
|
|
|
|
func onChainVerificationExample(ctx context.Context, client *zk.Client) {
|
|
fmt.Println("=== On-Chain Verification ===")
|
|
|
|
// Compile circuit
|
|
circuit := `
|
|
pragma circom 2.1.0;
|
|
|
|
template VoteCommitment() {
|
|
signal input vote; // Private: actual vote
|
|
signal input nullifier; // Private: unique identifier
|
|
signal input commitment; // Public: commitment to verify
|
|
|
|
// Simplified commitment (in practice, use Poseidon hash)
|
|
signal computed;
|
|
computed <== vote * nullifier;
|
|
commitment === computed;
|
|
}
|
|
|
|
component main {public [commitment]} = VoteCommitment();
|
|
`
|
|
|
|
compiled, err := client.Circuits.Compile(ctx, &zk.CompileRequest{
|
|
Code: circuit,
|
|
Format: zk.CircuitFormatCircom,
|
|
Name: "vote_commitment",
|
|
ProvingSystem: zk.ProvingSystemGroth16,
|
|
})
|
|
if err != nil {
|
|
log.Printf("Failed to compile circuit: %v", err)
|
|
return
|
|
}
|
|
|
|
// Generate Solidity verifier
|
|
fmt.Println("Generating Solidity verifier...")
|
|
solidityVerifier, err := client.Contracts.GenerateVerifier(ctx, &zk.GenerateVerifierRequest{
|
|
CircuitID: compiled.CircuitID,
|
|
Language: "solidity",
|
|
Optimized: true,
|
|
})
|
|
if err != nil {
|
|
log.Printf("Failed to generate verifier: %v", err)
|
|
return
|
|
}
|
|
fmt.Printf("Solidity verifier generated: %d bytes\n", len(solidityVerifier.Code))
|
|
fmt.Printf(" Contract name: %s\n", solidityVerifier.ContractName)
|
|
fmt.Printf(" Gas estimate: %d\n", solidityVerifier.GasEstimate)
|
|
|
|
// Generate proof
|
|
proof, err := client.Proofs.Generate(ctx, &zk.GenerateProofRequest{
|
|
CircuitID: compiled.CircuitID,
|
|
Inputs: map[string]string{
|
|
"vote": "1", // Vote YES (1) or NO (0)
|
|
"nullifier": "12345",
|
|
"commitment": "12345", // 1 * 12345
|
|
},
|
|
})
|
|
if err != nil {
|
|
log.Printf("Failed to generate proof: %v", err)
|
|
return
|
|
}
|
|
|
|
// Format proof for on-chain verification
|
|
fmt.Println("\nFormatting proof for on-chain...")
|
|
onChainProof, err := client.Contracts.FormatProof(ctx, &zk.FormatProofRequest{
|
|
CircuitID: compiled.CircuitID,
|
|
Proof: proof.Proof,
|
|
PublicSignals: proof.PublicSignals,
|
|
Format: "calldata",
|
|
})
|
|
if err != nil {
|
|
log.Printf("Failed to format proof: %v", err)
|
|
return
|
|
}
|
|
calldataPreview := onChainProof.Calldata
|
|
if len(calldataPreview) > 100 {
|
|
calldataPreview = calldataPreview[:100]
|
|
}
|
|
fmt.Printf(" Calldata: %s...\n", calldataPreview)
|
|
fmt.Printf(" Estimated gas: %d\n", onChainProof.GasEstimate)
|
|
|
|
// Deploy verifier contract (simulation)
|
|
fmt.Println("\nDeploying verifier contract...")
|
|
deployment, err := client.Contracts.DeployVerifier(ctx, &zk.DeployRequest{
|
|
CircuitID: compiled.CircuitID,
|
|
Network: "synor-testnet",
|
|
})
|
|
if err != nil {
|
|
log.Printf("Failed to deploy verifier: %v", err)
|
|
return
|
|
}
|
|
fmt.Printf(" Contract address: %s\n", deployment.Address)
|
|
fmt.Printf(" TX hash: %s\n", deployment.TxHash)
|
|
fmt.Printf(" Gas used: %d\n", deployment.GasUsed)
|
|
|
|
// Verify on-chain
|
|
fmt.Println("\nVerifying on-chain...")
|
|
onChainResult, err := client.Contracts.VerifyOnChain(ctx, &zk.OnChainVerifyRequest{
|
|
ContractAddress: deployment.Address,
|
|
Proof: proof.Proof,
|
|
PublicSignals: proof.PublicSignals,
|
|
Network: "synor-testnet",
|
|
})
|
|
if err != nil {
|
|
log.Printf("Failed to verify on-chain: %v", err)
|
|
return
|
|
}
|
|
fmt.Printf(" TX hash: %s\n", onChainResult.TxHash)
|
|
fmt.Printf(" Verified: %v\n", onChainResult.Verified)
|
|
fmt.Printf(" Gas used: %d\n", onChainResult.GasUsed)
|
|
|
|
// Generate verifier for other targets
|
|
fmt.Println("\nGenerating verifiers for other targets:")
|
|
targets := []string{"cairo", "noir", "ink"}
|
|
for _, target := range targets {
|
|
verifier, err := client.Contracts.GenerateVerifier(ctx, &zk.GenerateVerifierRequest{
|
|
CircuitID: compiled.CircuitID,
|
|
Language: target,
|
|
})
|
|
if err != nil {
|
|
log.Printf("Failed to generate %s verifier: %v", target, err)
|
|
continue
|
|
}
|
|
fmt.Printf(" %s: %d bytes\n", target, len(verifier.Code))
|
|
}
|
|
|
|
fmt.Println()
|
|
}
|
|
|
|
func setupExample(ctx context.Context, client *zk.Client) {
|
|
fmt.Println("=== Trusted Setup ===")
|
|
|
|
// Get available ceremonies
|
|
ceremonies, err := client.Setup.ListCeremonies(ctx)
|
|
if err != nil {
|
|
log.Printf("Failed to list ceremonies: %v", err)
|
|
return
|
|
}
|
|
fmt.Printf("Active ceremonies: %d\n", len(ceremonies))
|
|
for _, ceremony := range ceremonies {
|
|
fmt.Printf(" %s:\n", ceremony.Name)
|
|
fmt.Printf(" Status: %s\n", ceremony.Status)
|
|
fmt.Printf(" Participants: %d\n", ceremony.ParticipantCount)
|
|
fmt.Printf(" Current round: %d\n", ceremony.CurrentRound)
|
|
}
|
|
|
|
// Create a new circuit setup
|
|
circuit := `
|
|
pragma circom 2.1.0;
|
|
|
|
template NewCircuit() {
|
|
signal input a;
|
|
signal output b;
|
|
b <== a + 1;
|
|
}
|
|
|
|
component main {public [b]} = NewCircuit();
|
|
`
|
|
|
|
fmt.Println("\nInitializing setup for new circuit...")
|
|
setup, err := client.Setup.Initialize(ctx, &zk.SetupInitRequest{
|
|
Circuit: circuit,
|
|
Format: zk.CircuitFormatCircom,
|
|
Name: "new_circuit_setup",
|
|
ProvingSystem: zk.ProvingSystemGroth16,
|
|
CeremonyType: "powers_of_tau", // or 'phase2'
|
|
})
|
|
if err != nil {
|
|
log.Printf("Failed to initialize setup: %v", err)
|
|
return
|
|
}
|
|
fmt.Println("Setup initialized:")
|
|
fmt.Printf(" Ceremony ID: %s\n", setup.CeremonyID)
|
|
fmt.Printf(" Powers of Tau required: %d\n", setup.PowersRequired)
|
|
fmt.Printf(" Current phase: %s\n", setup.Phase)
|
|
|
|
// Contribute to ceremony (in practice, generates random entropy)
|
|
fmt.Println("\nContributing to ceremony...")
|
|
contribution, err := client.Setup.Contribute(ctx, &zk.ContributeRequest{
|
|
CeremonyID: setup.CeremonyID,
|
|
Entropy: fmt.Sprintf("%x", []byte("random-entropy-from-user")),
|
|
})
|
|
if err != nil {
|
|
log.Printf("Failed to contribute: %v", err)
|
|
return
|
|
}
|
|
fmt.Println("Contribution submitted:")
|
|
fmt.Printf(" Participant: %s\n", contribution.ParticipantID)
|
|
fmt.Printf(" Contribution hash: %s\n", contribution.Hash)
|
|
fmt.Printf(" Verification status: %v\n", contribution.Verified)
|
|
|
|
// Get ceremony status
|
|
status, err := client.Setup.GetStatus(ctx, setup.CeremonyID)
|
|
if err != nil {
|
|
log.Printf("Failed to get ceremony status: %v", err)
|
|
return
|
|
}
|
|
fmt.Println("\nCeremony status:")
|
|
fmt.Printf(" Phase: %s\n", status.Phase)
|
|
fmt.Printf(" Total contributions: %d\n", status.TotalContributions)
|
|
fmt.Printf(" Verified contributions: %d\n", status.VerifiedContributions)
|
|
fmt.Printf(" Ready for finalization: %v\n", status.ReadyForFinalization)
|
|
|
|
// Finalize setup (when enough contributions)
|
|
if status.ReadyForFinalization {
|
|
fmt.Println("\nFinalizing setup...")
|
|
finalized, err := client.Setup.Finalize(ctx, setup.CeremonyID)
|
|
if err != nil {
|
|
log.Printf("Failed to finalize setup: %v", err)
|
|
return
|
|
}
|
|
fmt.Println("Setup finalized:")
|
|
fmt.Printf(" Proving key hash: %s\n", finalized.ProvingKeyHash)
|
|
fmt.Printf(" Verification key hash: %s\n", finalized.VerificationKeyHash)
|
|
fmt.Printf(" Contribution transcript: %s\n", finalized.TranscriptCID)
|
|
}
|
|
|
|
// Download ceremony transcript
|
|
transcript, err := client.Setup.GetTranscript(ctx, setup.CeremonyID)
|
|
if err != nil {
|
|
log.Printf("Failed to get transcript: %v", err)
|
|
return
|
|
}
|
|
fmt.Printf("\nCeremony transcript: %d bytes\n", len(transcript))
|
|
|
|
fmt.Println()
|
|
}
|
|
|
|
func getEnv(key, defaultValue string) string {
|
|
if value := os.Getenv(key); value != "" {
|
|
return value
|
|
}
|
|
return defaultValue
|
|
}
|