From 2afa27d424648d2b10082fc7838b3da8146039ab Mon Sep 17 00:00:00 2001 From: Ho Date: Mon, 25 Aug 2025 21:10:31 +0900 Subject: [PATCH 1/2] new metrics for proof stat --- common/types/message/message.go | 15 ++++++++-- .../logic/submitproof/proof_receiver.go | 30 +++++++++++++++++++ coordinator/test/api_test.go | 3 +- crates/libzkp/src/proofs.rs | 2 ++ crates/libzkp/src/tasks.rs | 6 +++- 5 files changed, 51 insertions(+), 5 deletions(-) diff --git a/common/types/message/message.go b/common/types/message/message.go index c7db53704a..acc7e63702 100644 --- a/common/types/message/message.go +++ b/common/types/message/message.go @@ -135,10 +135,18 @@ type BlockContextV2 struct { NumL1Msgs uint16 `json:"num_l1_msgs"` } +// Metric data carried with OpenVMProof +type OpenVMProofStat struct { + TotalCycle uint64 `json:"total_cycles"` + ExecutionTimeMills uint64 `json:"execution_time_mills"` + ProvingTimeMills uint64 `json:"proving_time_mills"` +} + // Proof for flatten VM proof type OpenVMProof struct { - Proof []byte `json:"proofs"` - PublicValues []byte `json:"public_values"` + Proof []byte `json:"proofs"` + PublicValues []byte `json:"public_values"` + Stat *OpenVMProofStat `json:"stat,omitempty"` } // Proof for flatten EVM proof @@ -150,7 +158,8 @@ type OpenVMEvmProof struct { // OpenVMChunkProof includes the proof info that are required for chunk verification and rollup. type OpenVMChunkProof struct { MetaData struct { - ChunkInfo *ChunkInfo `json:"chunk_info"` + ChunkInfo *ChunkInfo `json:"chunk_info"` + TotalGasUsed uint64 `json:"chunk_total_gas"` } `json:"metadata"` VmProof *OpenVMProof `json:"proof"` diff --git a/coordinator/internal/logic/submitproof/proof_receiver.go b/coordinator/internal/logic/submitproof/proof_receiver.go index e35b7aa98a..e138839944 100644 --- a/coordinator/internal/logic/submitproof/proof_receiver.go +++ b/coordinator/internal/logic/submitproof/proof_receiver.go @@ -71,6 +71,8 @@ type ProofReceiverLogic struct { validateFailureProverTaskStatusNotOk prometheus.Counter validateFailureProverTaskTimeout prometheus.Counter validateFailureProverTaskHaveVerifier prometheus.Counter + proofTime *prometheus.GaugeVec + evm_cycle_per_gas prometheus.Gauge ChunkTask provertask.ProverTask BundleTask provertask.ProverTask @@ -79,6 +81,7 @@ type ProofReceiverLogic struct { // NewSubmitProofReceiverLogic create a proof receiver logic func NewSubmitProofReceiverLogic(cfg *config.ProverManager, chainCfg *params.ChainConfig, db *gorm.DB, vf *verifier.Verifier, reg prometheus.Registerer) *ProofReceiverLogic { + return &ProofReceiverLogic{ chunkOrm: orm.NewChunk(db), batchOrm: orm.NewBatch(db), @@ -133,6 +136,14 @@ func NewSubmitProofReceiverLogic(cfg *config.ProverManager, chainCfg *params.Cha Name: "coordinator_validate_failure_submit_have_been_verifier", Help: "Total number of submit proof validate failure proof have been verifier.", }), + evm_cycle_per_gas: promauto.With(reg).NewGauge(prometheus.GaugeOpts{ + Name: "evm_circuit_cycle_per_gas", + Help: "VM cycles cost for a gas unit cost in evm execution", + }), + proofTime: promauto.With(reg).NewGaugeVec(prometheus.GaugeOpts{ + Name: "prover_proving_time", + Help: "Time of prover cost for a proof", + }, []string{"type", "phase"}), } } @@ -204,12 +215,31 @@ func (m *ProofReceiverLogic) HandleZkProof(ctx *gin.Context, proofParameter coor return unmarshalErr } success, verifyErr = m.verifier.VerifyChunkProof(chunkProof, hardForkName) + if stat := chunkProof.VmProof.Stat; stat != nil { + if g, _ := m.proofTime.GetMetricWithLabelValues("chunk", "exec"); g != nil { + g.Set(float64(stat.ExecutionTimeMills) / 1000) + } + if g, _ := m.proofTime.GetMetricWithLabelValues("chunk", "proving"); g != nil { + g.Set(float64(stat.ProvingTimeMills) / 1000) + } + cycle_per_gas := float64(stat.TotalCycle) / float64(chunkProof.MetaData.TotalGasUsed) + m.evm_cycle_per_gas.Set(cycle_per_gas) + } + case message.ProofTypeBatch: batchProof := &message.OpenVMBatchProof{} if unmarshalErr := json.Unmarshal([]byte(proofParameter.Proof), &batchProof); unmarshalErr != nil { return unmarshalErr } success, verifyErr = m.verifier.VerifyBatchProof(batchProof, hardForkName) + if stat := batchProof.VmProof.Stat; stat != nil { + if g, _ := m.proofTime.GetMetricWithLabelValues("batch", "exec"); g != nil { + g.Set(float64(stat.ExecutionTimeMills) / 1000) + } + if g, _ := m.proofTime.GetMetricWithLabelValues("batch", "proving"); g != nil { + g.Set(float64(stat.ProvingTimeMills) / 1000) + } + } case message.ProofTypeBundle: bundleProof := &message.OpenVMBundleProof{} if unmarshalErr := json.Unmarshal([]byte(proofParameter.Proof), &bundleProof); unmarshalErr != nil { diff --git a/coordinator/test/api_test.go b/coordinator/test/api_test.go index 88d5b6081e..053f6b715e 100644 --- a/coordinator/test/api_test.go +++ b/coordinator/test/api_test.go @@ -584,7 +584,8 @@ func testTimeoutProof(t *testing.T) { err = chunkOrm.UpdateBatchHashInRange(context.Background(), 0, 100, batch.Hash) assert.NoError(t, err) encodeData, err := json.Marshal(message.OpenVMChunkProof{VmProof: &message.OpenVMProof{}, MetaData: struct { - ChunkInfo *message.ChunkInfo `json:"chunk_info"` + ChunkInfo *message.ChunkInfo `json:"chunk_info"` + TotalGasUsed uint64 `json:"chunk_total_gas"` }{ChunkInfo: &message.ChunkInfo{}}}) assert.NoError(t, err) assert.NotEmpty(t, encodeData) diff --git a/crates/libzkp/src/proofs.rs b/crates/libzkp/src/proofs.rs index 5311360a38..8f2687d660 100644 --- a/crates/libzkp/src/proofs.rs +++ b/crates/libzkp/src/proofs.rs @@ -122,6 +122,8 @@ pub trait PersistableProof: Sized { pub struct ChunkProofMetadata { /// The chunk information describing the list of blocks contained within the chunk. pub chunk_info: ChunkInfo, + /// Additional data for stat + pub chunk_total_gas: u64, } impl ProofMetadata for ChunkProofMetadata { diff --git a/crates/libzkp/src/tasks.rs b/crates/libzkp/src/tasks.rs index 51bde1f94b..ae937416b2 100644 --- a/crates/libzkp/src/tasks.rs +++ b/crates/libzkp/src/tasks.rs @@ -44,12 +44,16 @@ pub fn gen_universal_chunk_task( if let Some(interpreter) = interpreter { task.prepare_task_via_interpret(interpreter)?; } + let chunk_total_gas = task.stats().total_gas_used; let chunk_info = task.precheck_and_build_metadata()?; let proving_task = task.try_into()?; let expected_pi_hash = chunk_info.pi_hash_by_fork(fork_name); Ok(( expected_pi_hash, - ChunkProofMetadata { chunk_info }, + ChunkProofMetadata { + chunk_info, + chunk_total_gas, + }, proving_task, )) } From 6a9a34bbce921972cbe499f2b5cb141aee3d9157 Mon Sep 17 00:00:00 2001 From: Ho Date: Tue, 26 Aug 2025 11:17:39 +0900 Subject: [PATCH 2/2] update metrics --- .../logic/submitproof/proof_receiver.go | 30 +++++++++++-------- 1 file changed, 18 insertions(+), 12 deletions(-) diff --git a/coordinator/internal/logic/submitproof/proof_receiver.go b/coordinator/internal/logic/submitproof/proof_receiver.go index e138839944..92912e523b 100644 --- a/coordinator/internal/logic/submitproof/proof_receiver.go +++ b/coordinator/internal/logic/submitproof/proof_receiver.go @@ -71,7 +71,8 @@ type ProofReceiverLogic struct { validateFailureProverTaskStatusNotOk prometheus.Counter validateFailureProverTaskTimeout prometheus.Counter validateFailureProverTaskHaveVerifier prometheus.Counter - proofTime *prometheus.GaugeVec + proverSpeed *prometheus.GaugeVec + provingTime prometheus.Gauge evm_cycle_per_gas prometheus.Gauge ChunkTask provertask.ProverTask @@ -140,9 +141,13 @@ func NewSubmitProofReceiverLogic(cfg *config.ProverManager, chainCfg *params.Cha Name: "evm_circuit_cycle_per_gas", Help: "VM cycles cost for a gas unit cost in evm execution", }), - proofTime: promauto.With(reg).NewGaugeVec(prometheus.GaugeOpts{ - Name: "prover_proving_time", - Help: "Time of prover cost for a proof", + provingTime: promauto.With(reg).NewGauge(prometheus.GaugeOpts{ + Name: "chunk_proving_time", + Help: "Wall clock time for chunk proving in second", + }), + proverSpeed: promauto.With(reg).NewGaugeVec(prometheus.GaugeOpts{ + Name: "prover_speed", + Help: "Cycle against running time of prover (in mhz)", }, []string{"type", "phase"}), } } @@ -216,14 +221,15 @@ func (m *ProofReceiverLogic) HandleZkProof(ctx *gin.Context, proofParameter coor } success, verifyErr = m.verifier.VerifyChunkProof(chunkProof, hardForkName) if stat := chunkProof.VmProof.Stat; stat != nil { - if g, _ := m.proofTime.GetMetricWithLabelValues("chunk", "exec"); g != nil { - g.Set(float64(stat.ExecutionTimeMills) / 1000) + if g, _ := m.proverSpeed.GetMetricWithLabelValues("chunk", "exec"); g != nil { + g.Set(float64(stat.TotalCycle) / float64(stat.ExecutionTimeMills*1000)) } - if g, _ := m.proofTime.GetMetricWithLabelValues("chunk", "proving"); g != nil { - g.Set(float64(stat.ProvingTimeMills) / 1000) + if g, _ := m.proverSpeed.GetMetricWithLabelValues("chunk", "proving"); g != nil { + g.Set(float64(stat.TotalCycle) / float64(stat.ProvingTimeMills*1000)) } cycle_per_gas := float64(stat.TotalCycle) / float64(chunkProof.MetaData.TotalGasUsed) m.evm_cycle_per_gas.Set(cycle_per_gas) + m.provingTime.Set(float64(stat.ProvingTimeMills) / 1000) } case message.ProofTypeBatch: @@ -233,11 +239,11 @@ func (m *ProofReceiverLogic) HandleZkProof(ctx *gin.Context, proofParameter coor } success, verifyErr = m.verifier.VerifyBatchProof(batchProof, hardForkName) if stat := batchProof.VmProof.Stat; stat != nil { - if g, _ := m.proofTime.GetMetricWithLabelValues("batch", "exec"); g != nil { - g.Set(float64(stat.ExecutionTimeMills) / 1000) + if g, _ := m.proverSpeed.GetMetricWithLabelValues("batch", "exec"); g != nil { + g.Set(float64(stat.TotalCycle) / float64(stat.ExecutionTimeMills*1000)) } - if g, _ := m.proofTime.GetMetricWithLabelValues("batch", "proving"); g != nil { - g.Set(float64(stat.ProvingTimeMills) / 1000) + if g, _ := m.proverSpeed.GetMetricWithLabelValues("batch", "proving"); g != nil { + g.Set(float64(stat.TotalCycle) / float64(stat.ProvingTimeMills*1000)) } } case message.ProofTypeBundle: