Skip to content

Commit b297edd

Browse files
authored
[Feat] Prover loading assets (circuits) dynamically (#1717)
1 parent 47c85d4 commit b297edd

File tree

32 files changed

+907
-923
lines changed

32 files changed

+907
-923
lines changed

Cargo.lock

Lines changed: 215 additions & 196 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -17,9 +17,9 @@ repository = "https://github.com/scroll-tech/scroll"
1717
version = "4.5.8"
1818

1919
[workspace.dependencies]
20-
scroll-zkvm-prover-euclid = { git = "https://github.com/scroll-tech/zkvm-prover", branch = "feat/0.5.1", package = "scroll-zkvm-prover" }
21-
scroll-zkvm-verifier-euclid = { git = "https://github.com/scroll-tech/zkvm-prover", branch = "feat/0.5.1", package = "scroll-zkvm-verifier" }
22-
scroll-zkvm-types = { git = "https://github.com/scroll-tech/zkvm-prover", branch = "feat/0.5.1" }
20+
scroll-zkvm-prover = { git = "https://github.com/scroll-tech/zkvm-prover", rev = "89a2dc1" }
21+
scroll-zkvm-verifier = { git = "https://github.com/scroll-tech/zkvm-prover", rev = "89a2dc1" }
22+
scroll-zkvm-types = { git = "https://github.com/scroll-tech/zkvm-prover", rev = "89a2dc1" }
2323

2424
sbv-primitives = { git = "https://github.com/scroll-tech/stateless-block-verifier", branch = "chore/openvm-1.3", features = ["scroll"] }
2525
sbv-utils = { git = "https://github.com/scroll-tech/stateless-block-verifier", branch = "chore/openvm-1.3" }

common/types/message/message.go

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -135,10 +135,18 @@ type BlockContextV2 struct {
135135
NumL1Msgs uint16 `json:"num_l1_msgs"`
136136
}
137137

138+
// Metric data carried with OpenVMProof
139+
type OpenVMProofStat struct {
140+
TotalCycle uint64 `json:"total_cycles"`
141+
ExecutionTimeMills uint64 `json:"execution_time_mills"`
142+
ProvingTimeMills uint64 `json:"proving_time_mills"`
143+
}
144+
138145
// Proof for flatten VM proof
139146
type OpenVMProof struct {
140-
Proof []byte `json:"proofs"`
141-
PublicValues []byte `json:"public_values"`
147+
Proof []byte `json:"proofs"`
148+
PublicValues []byte `json:"public_values"`
149+
Stat *OpenVMProofStat `json:"stat,omitempty"`
142150
}
143151

144152
// Proof for flatten EVM proof
@@ -150,7 +158,8 @@ type OpenVMEvmProof struct {
150158
// OpenVMChunkProof includes the proof info that are required for chunk verification and rollup.
151159
type OpenVMChunkProof struct {
152160
MetaData struct {
153-
ChunkInfo *ChunkInfo `json:"chunk_info"`
161+
ChunkInfo *ChunkInfo `json:"chunk_info"`
162+
TotalGasUsed uint64 `json:"chunk_total_gas"`
154163
} `json:"metadata"`
155164

156165
VmProof *OpenVMProof `json:"proof"`

coordinator/Makefile

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,13 @@ coordinator_cron:
3434
coordinator_tool:
3535
go build -ldflags "-X scroll-tech/common/version.ZkVersion=${ZK_VERSION}" -o $(PWD)/build/bin/coordinator_tool ./cmd/tool
3636

37+
localsetup: coordinator_api ## Local setup: build coordinator_api, copy config, and setup releases
38+
@echo "Copying configuration files..."
39+
cp -r $(PWD)/conf $(PWD)/build/bin/
40+
@echo "Setting up releases..."
41+
cd $(PWD)/build && bash setup_releases.sh
42+
43+
3744
#coordinator_api_skip_libzkp:
3845
# go build -ldflags "-X scroll-tech/common/version.ZkVersion=${ZK_VERSION}" -o $(PWD)/build/bin/coordinator_api ./cmd/api
3946

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
#!/bin/bash
2+
3+
# release version
4+
if [ -z "${SCROLL_ZKVM_VERSION}" ]; then
5+
echo "SCROLL_ZKVM_VERSION not set"
6+
exit 1
7+
fi
8+
9+
# set ASSET_DIR by reading from config.json
10+
CONFIG_FILE="bin/conf/config.json"
11+
if [ ! -f "$CONFIG_FILE" ]; then
12+
echo "Config file $CONFIG_FILE not found"
13+
exit 1
14+
fi
15+
16+
# get the number of verifiers in the array
17+
VERIFIER_COUNT=$(jq -r '.prover_manager.verifier.verifiers | length' "$CONFIG_FILE")
18+
19+
if [ "$VERIFIER_COUNT" = "null" ] || [ "$VERIFIER_COUNT" -eq 0 ]; then
20+
echo "No verifiers found in config file"
21+
exit 1
22+
fi
23+
24+
echo "Found $VERIFIER_COUNT verifier(s) in config"
25+
26+
# iterate through each verifier entry
27+
for ((i=0; i<$VERIFIER_COUNT; i++)); do
28+
# extract assets_path for current verifier
29+
ASSETS_PATH=$(jq -r ".prover_manager.verifier.verifiers[$i].assets_path" "$CONFIG_FILE")
30+
FORK_NAME=$(jq -r ".prover_manager.verifier.verifiers[$i].fork_name" "$CONFIG_FILE")
31+
32+
if [ "$ASSETS_PATH" = "null" ]; then
33+
echo "Warning: Could not find assets_path for verifier $i, skipping..."
34+
continue
35+
fi
36+
37+
echo "Processing verifier $i ($FORK_NAME): assets_path=$ASSETS_PATH"
38+
39+
# check if it's an absolute path (starts with /)
40+
if [[ "$ASSETS_PATH" = /* ]]; then
41+
# absolute path, use as is
42+
ASSET_DIR="$ASSETS_PATH"
43+
else
44+
# relative path, prefix with "bin/"
45+
ASSET_DIR="bin/$ASSETS_PATH"
46+
fi
47+
48+
echo "Using ASSET_DIR: $ASSET_DIR"
49+
50+
# create directory if it doesn't exist
51+
mkdir -p "$ASSET_DIR"
52+
53+
# assets for verifier-only mode
54+
echo "Downloading assets for $FORK_NAME to $ASSET_DIR..."
55+
wget https://circuit-release.s3.us-west-2.amazonaws.com/scroll-zkvm/releases/$SCROLL_ZKVM_VERSION/verifier/verifier.bin -O ${ASSET_DIR}/verifier.bin
56+
wget https://circuit-release.s3.us-west-2.amazonaws.com/scroll-zkvm/releases/$SCROLL_ZKVM_VERSION/verifier/openVmVk.json -O ${ASSET_DIR}/openVmVk.json
57+
58+
echo "Completed downloading assets for $FORK_NAME"
59+
echo "---"
60+
done
61+
62+
echo "All verifier assets downloaded successfully"

coordinator/conf/config.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212
{
1313
"assets_path": "assets",
1414
"fork_name": "euclidV2"
15-
},
15+
},
1616
{
1717
"assets_path": "assets",
1818
"fork_name": "feynman"

coordinator/internal/config/config.go

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -57,9 +57,10 @@ type Config struct {
5757

5858
// AssetConfig contain assets configurated for each fork, the defaul vkfile name is "OpenVmVk.json".
5959
type AssetConfig struct {
60-
AssetsPath string `json:"assets_path"`
61-
ForkName string `json:"fork_name"`
62-
Vkfile string `json:"vk_file,omitempty"`
60+
AssetsPath string `json:"assets_path"`
61+
ForkName string `json:"fork_name"`
62+
Vkfile string `json:"vk_file,omitempty"`
63+
MinProverVersion string `json:"min_prover_version,omitempty"`
6364
}
6465

6566
// VerifierConfig load zk verifier config.

coordinator/internal/logic/auth/login.go

Lines changed: 12 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -24,18 +24,16 @@ type LoginLogic struct {
2424

2525
openVmVks map[string]struct{}
2626

27-
proverVersionHardForkMap map[string][]string
27+
proverVersionHardForkMap map[string]string
2828
}
2929

3030
// NewLoginLogic new a LoginLogic
3131
func NewLoginLogic(db *gorm.DB, cfg *config.Config, vf *verifier.Verifier) *LoginLogic {
32-
proverVersionHardForkMap := make(map[string][]string)
32+
proverVersionHardForkMap := make(map[string]string)
3333

34-
var hardForks []string
3534
for _, cfg := range cfg.ProverManager.Verifier.Verifiers {
36-
hardForks = append(hardForks, cfg.ForkName)
35+
proverVersionHardForkMap[cfg.ForkName] = cfg.MinProverVersion
3736
}
38-
proverVersionHardForkMap[cfg.ProverManager.Verifier.MinProverVersion] = hardForks
3937

4038
return &LoginLogic{
4139
cfg: cfg,
@@ -101,9 +99,15 @@ func (l *LoginLogic) ProverHardForkName(login *types.LoginParameter) (string, er
10199
}
102100

103101
proverVersion := proverVersionSplits[0]
104-
if hardForkNames, ok := l.proverVersionHardForkMap[proverVersion]; ok {
105-
return strings.Join(hardForkNames, ","), nil
102+
var hardForkNames []string
103+
for n, minVersion := range l.proverVersionHardForkMap {
104+
if minVersion == "" || version.CheckScrollRepoVersion(proverVersion, minVersion) {
105+
hardForkNames = append(hardForkNames, n)
106+
}
107+
}
108+
if len(hardForkNames) == 0 {
109+
return "", fmt.Errorf("invalid prover prover_version:%s", login.Message.ProverVersion)
106110
}
107111

108-
return "", fmt.Errorf("invalid prover prover_version:%s", login.Message.ProverVersion)
112+
return strings.Join(hardForkNames, ","), nil
109113
}

coordinator/internal/logic/submitproof/proof_receiver.go

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,9 @@ type ProofReceiverLogic struct {
7171
validateFailureProverTaskStatusNotOk prometheus.Counter
7272
validateFailureProverTaskTimeout prometheus.Counter
7373
validateFailureProverTaskHaveVerifier prometheus.Counter
74+
proverSpeed *prometheus.GaugeVec
75+
provingTime prometheus.Gauge
76+
evmCyclePerGas prometheus.Gauge
7477

7578
ChunkTask provertask.ProverTask
7679
BundleTask provertask.ProverTask
@@ -79,6 +82,7 @@ type ProofReceiverLogic struct {
7982

8083
// NewSubmitProofReceiverLogic create a proof receiver logic
8184
func NewSubmitProofReceiverLogic(cfg *config.ProverManager, chainCfg *params.ChainConfig, db *gorm.DB, vf *verifier.Verifier, reg prometheus.Registerer) *ProofReceiverLogic {
85+
8286
return &ProofReceiverLogic{
8387
chunkOrm: orm.NewChunk(db),
8488
batchOrm: orm.NewBatch(db),
@@ -133,6 +137,18 @@ func NewSubmitProofReceiverLogic(cfg *config.ProverManager, chainCfg *params.Cha
133137
Name: "coordinator_validate_failure_submit_have_been_verifier",
134138
Help: "Total number of submit proof validate failure proof have been verifier.",
135139
}),
140+
evmCyclePerGas: promauto.With(reg).NewGauge(prometheus.GaugeOpts{
141+
Name: "evm_circuit_cycle_per_gas",
142+
Help: "VM cycles cost for a gas unit cost in evm execution",
143+
}),
144+
provingTime: promauto.With(reg).NewGauge(prometheus.GaugeOpts{
145+
Name: "chunk_proving_time",
146+
Help: "Wall clock time for chunk proving in second",
147+
}),
148+
proverSpeed: promauto.With(reg).NewGaugeVec(prometheus.GaugeOpts{
149+
Name: "prover_speed",
150+
Help: "Cycle against running time of prover (in mhz)",
151+
}, []string{"type", "phase"}),
136152
}
137153
}
138154

@@ -204,12 +220,34 @@ func (m *ProofReceiverLogic) HandleZkProof(ctx *gin.Context, proofParameter coor
204220
return unmarshalErr
205221
}
206222
success, verifyErr = m.verifier.VerifyChunkProof(chunkProof, hardForkName)
223+
if stat := chunkProof.VmProof.Stat; stat != nil {
224+
if g, _ := m.proverSpeed.GetMetricWithLabelValues("chunk", "exec"); g != nil && stat.ExecutionTimeMills > 0 {
225+
g.Set(float64(stat.TotalCycle) / float64(stat.ExecutionTimeMills*1000))
226+
}
227+
if g, _ := m.proverSpeed.GetMetricWithLabelValues("chunk", "proving"); g != nil && stat.ProvingTimeMills > 0 {
228+
g.Set(float64(stat.TotalCycle) / float64(stat.ProvingTimeMills*1000))
229+
}
230+
if chunkProof.MetaData.TotalGasUsed > 0 {
231+
cycle_per_gas := float64(stat.TotalCycle) / float64(chunkProof.MetaData.TotalGasUsed)
232+
m.evmCyclePerGas.Set(cycle_per_gas)
233+
}
234+
m.provingTime.Set(float64(stat.ProvingTimeMills) / 1000)
235+
}
236+
207237
case message.ProofTypeBatch:
208238
batchProof := &message.OpenVMBatchProof{}
209239
if unmarshalErr := json.Unmarshal([]byte(proofParameter.Proof), &batchProof); unmarshalErr != nil {
210240
return unmarshalErr
211241
}
212242
success, verifyErr = m.verifier.VerifyBatchProof(batchProof, hardForkName)
243+
if stat := batchProof.VmProof.Stat; stat != nil {
244+
if g, _ := m.proverSpeed.GetMetricWithLabelValues("batch", "exec"); g != nil && stat.ExecutionTimeMills > 0 {
245+
g.Set(float64(stat.TotalCycle) / float64(stat.ExecutionTimeMills*1000))
246+
}
247+
if g, _ := m.proverSpeed.GetMetricWithLabelValues("batch", "proving"); g != nil && stat.ProvingTimeMills > 0 {
248+
g.Set(float64(stat.TotalCycle) / float64(stat.ProvingTimeMills*1000))
249+
}
250+
}
213251
case message.ProofTypeBundle:
214252
bundleProof := &message.OpenVMBundleProof{}
215253
if unmarshalErr := json.Unmarshal([]byte(proofParameter.Proof), &bundleProof); unmarshalErr != nil {

coordinator/internal/logic/verifier/verifier.go

Lines changed: 21 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ package verifier
44

55
import (
66
"encoding/base64"
7+
"encoding/hex"
78
"encoding/json"
89
"fmt"
910
"io"
@@ -129,6 +130,23 @@ const blocked_vks = `
129130
D6YFHwTLZF/U2zpYJPQ3LwJZRm85yA5Vq2iFBqd3Mk4iwOUpS8sbOp3vg2+NDxhhKphgYpuUlykpdsoRhEt+cw==,
130131
`
131132

133+
// tries to decode s as hex, and if that fails, as base64.
134+
func decodeVkString(s string) ([]byte, error) {
135+
// Try hex decoding first
136+
if b, err := hex.DecodeString(s); err == nil {
137+
return b, nil
138+
}
139+
// Fallback to base64 decoding
140+
b, err := base64.StdEncoding.DecodeString(s)
141+
if err != nil {
142+
return nil, err
143+
}
144+
if len(b) == 0 {
145+
return nil, fmt.Errorf("decode vk string %s fail (empty bytes)", s)
146+
}
147+
return b, nil
148+
}
149+
132150
func (v *Verifier) loadOpenVMVks(cfg config.AssetConfig) error {
133151

134152
vkFileName := cfg.Vkfile
@@ -165,17 +183,17 @@ func (v *Verifier) loadOpenVMVks(cfg config.AssetConfig) error {
165183
v.OpenVMVkMap[dump.Bundle] = struct{}{}
166184
log.Info("Load vks", "from", cfg.AssetsPath, "chunk", dump.Chunk, "batch", dump.Batch, "bundle", dump.Bundle)
167185

168-
decodedBytes, err := base64.StdEncoding.DecodeString(dump.Chunk)
186+
decodedBytes, err := decodeVkString(dump.Chunk)
169187
if err != nil {
170188
return err
171189
}
172190
v.ChunkVk[cfg.ForkName] = decodedBytes
173-
decodedBytes, err = base64.StdEncoding.DecodeString(dump.Batch)
191+
decodedBytes, err = decodeVkString(dump.Batch)
174192
if err != nil {
175193
return err
176194
}
177195
v.BatchVk[cfg.ForkName] = decodedBytes
178-
decodedBytes, err = base64.StdEncoding.DecodeString(dump.Bundle)
196+
decodedBytes, err = decodeVkString(dump.Bundle)
179197
if err != nil {
180198
return err
181199
}

0 commit comments

Comments
 (0)