mirror of
https://github.com/scroll-tech/scroll.git
synced 2026-01-13 16:08:04 -05:00
221 lines
5.8 KiB
Go
221 lines
5.8 KiB
Go
//go:build !mock_verifier
|
|
|
|
package verifier
|
|
|
|
import (
|
|
"encoding/base64"
|
|
"encoding/hex"
|
|
"encoding/json"
|
|
"fmt"
|
|
"io"
|
|
"os"
|
|
"path"
|
|
"path/filepath"
|
|
"strings"
|
|
|
|
"github.com/scroll-tech/go-ethereum/log"
|
|
|
|
"scroll-tech/common/types/message"
|
|
|
|
"scroll-tech/coordinator/internal/config"
|
|
"scroll-tech/coordinator/internal/logic/libzkp"
|
|
"scroll-tech/coordinator/internal/utils"
|
|
)
|
|
|
|
// This struct maps to `CircuitConfig` in libzkp/src/verifier.rs
|
|
// Define a brand new struct here is to eliminate side effects in case fields
|
|
// in `*config.CircuitConfig` being changed
|
|
type rustCircuitConfig struct {
|
|
Version uint `json:"version"`
|
|
ForkName string `json:"fork_name"`
|
|
AssetsPath string `json:"assets_path"`
|
|
Features string `json:"features,omitempty"`
|
|
}
|
|
|
|
var validiumMode bool
|
|
|
|
func newRustCircuitConfig(cfg config.AssetConfig) *rustCircuitConfig {
|
|
ver := cfg.Version
|
|
if ver == 0 {
|
|
var err error
|
|
ver, err = utils.Version(cfg.ForkName, validiumMode)
|
|
if err != nil {
|
|
panic(err)
|
|
}
|
|
}
|
|
|
|
return &rustCircuitConfig{
|
|
Version: uint(ver),
|
|
AssetsPath: cfg.AssetsPath,
|
|
ForkName: cfg.ForkName,
|
|
Features: cfg.Features,
|
|
}
|
|
}
|
|
|
|
// This struct maps to `VerifierConfig` in coordinator/internal/logic/libzkp/src/verifier.rs
|
|
// Define a brand new struct here is to eliminate side effects in case fields
|
|
// in `*config.VerifierConfig` being changed
|
|
type rustVerifierConfig struct {
|
|
Circuits []*rustCircuitConfig `json:"circuits"`
|
|
}
|
|
|
|
func newRustVerifierConfig(cfg *config.VerifierConfig) *rustVerifierConfig {
|
|
|
|
out := &rustVerifierConfig{}
|
|
|
|
for _, cfg := range cfg.Verifiers {
|
|
out.Circuits = append(out.Circuits, newRustCircuitConfig(cfg))
|
|
}
|
|
return out
|
|
}
|
|
|
|
type rustVkDump struct {
|
|
Chunk string `json:"chunk_vk"`
|
|
Batch string `json:"batch_vk"`
|
|
Bundle string `json:"bundle_vk"`
|
|
}
|
|
|
|
// NewVerifier Sets up a rust ffi to call verify.
|
|
func NewVerifier(cfg *config.VerifierConfig, useValidiumMode bool) (*Verifier, error) {
|
|
validiumMode = useValidiumMode
|
|
verifierConfig := newRustVerifierConfig(cfg)
|
|
configBytes, err := json.Marshal(verifierConfig)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
libzkp.InitVerifier(string(configBytes))
|
|
|
|
v := &Verifier{
|
|
cfg: cfg,
|
|
OpenVMVkMap: make(map[string]struct{}),
|
|
ChunkVk: make(map[string][]byte),
|
|
BatchVk: make(map[string][]byte),
|
|
BundleVk: make(map[string][]byte),
|
|
}
|
|
|
|
for _, cfg := range cfg.Verifiers {
|
|
if err := v.loadOpenVMVks(cfg); err != nil {
|
|
return nil, err
|
|
}
|
|
}
|
|
|
|
return v, nil
|
|
}
|
|
|
|
// VerifyBatchProof Verify a ZkProof by marshaling it and sending it to the Verifier.
|
|
func (v *Verifier) VerifyBatchProof(proof *message.OpenVMBatchProof, forkName string) (bool, error) {
|
|
buf, err := json.Marshal(proof)
|
|
if err != nil {
|
|
return false, err
|
|
}
|
|
|
|
log.Info("Start to verify batch proof", "forkName", forkName)
|
|
return libzkp.VerifyBatchProof(string(buf), forkName), nil
|
|
}
|
|
|
|
// VerifyChunkProof Verify a ZkProof by marshaling it and sending it to the Verifier.
|
|
func (v *Verifier) VerifyChunkProof(proof *message.OpenVMChunkProof, forkName string) (bool, error) {
|
|
buf, err := json.Marshal(proof)
|
|
if err != nil {
|
|
return false, err
|
|
}
|
|
|
|
log.Info("Start to verify chunk proof", "forkName", forkName)
|
|
|
|
return libzkp.VerifyChunkProof(string(buf), forkName), nil
|
|
}
|
|
|
|
// VerifyBundleProof Verify a ZkProof for a bundle of batches, by marshaling it and verifying it via the EVM verifier.
|
|
func (v *Verifier) VerifyBundleProof(proof *message.OpenVMBundleProof, forkName string) (bool, error) {
|
|
buf, err := json.Marshal(proof)
|
|
if err != nil {
|
|
return false, err
|
|
}
|
|
|
|
log.Info("Start to verify bundle proof ...")
|
|
return libzkp.VerifyBundleProof(string(buf), forkName), nil
|
|
}
|
|
|
|
/*
|
|
add vk of imcompatilbe circuit app here to avoid we had used them unexpectedly
|
|
25/07/15: 0.5.0rc0 is no longer compatible since a breaking change
|
|
*/
|
|
const blocked_vks = `
|
|
rSJNNBpsxBdKlstbIIU/aYc7bHau98Qb2yjZMc5PmDhmGOolp5kYRbvF/VcWcO5HN5ujGs6S00W8pZcCoNQRLQ==,
|
|
2Lo7Cebm6SFtcsYXipkcMxIBmVY7UpoMXik/Msm7t2nyvi9EaNGsSnDnaCurscYEF+IcdjPUtVtY9EcD7IKwWg==,
|
|
D6YFHwTLZF/U2zpYJPQ3LwJZRm85yA5Vq2iFBqd3Mk4iwOUpS8sbOp3vg2+NDxhhKphgYpuUlykpdsoRhEt+cw==,
|
|
`
|
|
|
|
// tries to decode s as hex, and if that fails, as base64.
|
|
func decodeVkString(s string) ([]byte, error) {
|
|
// Try hex decoding first
|
|
if b, err := hex.DecodeString(s); err == nil {
|
|
return b, nil
|
|
}
|
|
// Fallback to base64 decoding
|
|
b, err := base64.StdEncoding.DecodeString(s)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
if len(b) == 0 {
|
|
return nil, fmt.Errorf("decode vk string %s fail (empty bytes)", s)
|
|
}
|
|
return b, nil
|
|
}
|
|
|
|
func (v *Verifier) loadOpenVMVks(cfg config.AssetConfig) error {
|
|
|
|
vkFileName := cfg.Vkfile
|
|
if vkFileName == "" {
|
|
vkFileName = "openVmVk.json"
|
|
}
|
|
vkFile := path.Join(cfg.AssetsPath, vkFileName)
|
|
|
|
f, err := os.Open(filepath.Clean(vkFile))
|
|
if err != nil {
|
|
return err
|
|
}
|
|
byt, err := io.ReadAll(f)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
var dump rustVkDump
|
|
if err := json.Unmarshal(byt, &dump); err != nil {
|
|
return err
|
|
}
|
|
if strings.Contains(blocked_vks, dump.Chunk) {
|
|
return fmt.Errorf("loaded blocked chunk vk %s", dump.Chunk)
|
|
}
|
|
if strings.Contains(blocked_vks, dump.Batch) {
|
|
return fmt.Errorf("loaded blocked batch vk %s", dump.Batch)
|
|
}
|
|
if strings.Contains(blocked_vks, dump.Bundle) {
|
|
return fmt.Errorf("loaded blocked bundle vk %s", dump.Bundle)
|
|
}
|
|
|
|
v.OpenVMVkMap[dump.Chunk] = struct{}{}
|
|
v.OpenVMVkMap[dump.Batch] = struct{}{}
|
|
v.OpenVMVkMap[dump.Bundle] = struct{}{}
|
|
log.Info("Load vks", "from", cfg.AssetsPath, "chunk", dump.Chunk, "batch", dump.Batch, "bundle", dump.Bundle)
|
|
|
|
decodedBytes, err := decodeVkString(dump.Chunk)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
v.ChunkVk[cfg.ForkName] = decodedBytes
|
|
decodedBytes, err = decodeVkString(dump.Batch)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
v.BatchVk[cfg.ForkName] = decodedBytes
|
|
decodedBytes, err = decodeVkString(dump.Bundle)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
v.BundleVk[cfg.ForkName] = decodedBytes
|
|
|
|
return nil
|
|
}
|