From 4979e14dbf8798274f4bd66457fb233456605b6d Mon Sep 17 00:00:00 2001 From: Daniel Liu <139250065@qq.com> Date: Sat, 15 Nov 2025 19:12:15 +0800 Subject: [PATCH] engines/engine_v2: refactor verifyQC by errgroup, close XFN-09 (#1740) --- commits | 2 +- consensus/XDPoS/engines/engine_v2/engine.go | 50 ++++++++++++--------- 2 files changed, 30 insertions(+), 22 deletions(-) diff --git a/commits b/commits index ed01edb776..d886a75ba1 100644 --- a/commits +++ b/commits @@ -3,7 +3,7 @@ I found 50 commits containing the keyword "XFN" in the last 200 commits. Here th 845137849 - Wanwiset Peerapatanapokin - consensus: change os.Exit to return error (#1653) b49f6cb0f - Wanwiset Peerapatanapokin - consensus: verify header hash is same as input hash in getEpochSwitchInfo (#1627) e0c987f45 - Wanwiset Peerapatanapokin - impose size limit for DecodeBytesExtraFields (#1637) -53f6a8d6d - Wanwiset Peerapatanapokin - consensus: optimize CompareSignersLists +998153ebb - Wanwiset Peerapatanapokin - consensus: optimize CompareSignersLists 6abb4f88d - Wanwiset Peerapatanapokin - consensus: Verify gaslimit bounds when accepting blocks (#1619) c95d25805 - Wanwiset Peerapatanapokin - separate fullVerifies array into v1fullVerifies and v2fullVerifies (#1618) diff --git a/consensus/XDPoS/engines/engine_v2/engine.go b/consensus/XDPoS/engines/engine_v2/engine.go index c9abcc6e91..60f74feecf 100644 --- a/consensus/XDPoS/engines/engine_v2/engine.go +++ b/consensus/XDPoS/engines/engine_v2/engine.go @@ -1,12 +1,14 @@ package engine_v2 import ( + "context" "encoding/json" "errors" "fmt" "math/big" "os" "path/filepath" + "runtime" "sync" "time" @@ -24,6 +26,7 @@ import ( "github.com/XinFinOrg/XDPoSChain/log" "github.com/XinFinOrg/XDPoSChain/params" "github.com/XinFinOrg/XDPoSChain/trie" + "golang.org/x/sync/errgroup" ) type XDPoS_v2 struct { @@ -864,31 +867,36 @@ func (x *XDPoS_v2) verifyQC(blockChainReader consensus.ChainReader, quorumCert * } start := time.Now() - var wg sync.WaitGroup - wg.Add(len(signatures)) - sigErrChan := make(chan error, len(signatures)) - - for _, signature := range signatures { - go func(sig types.Signature) { - defer wg.Done() - verified, _, err := x.verifyMsgSignature(signedVoteObj, sig, epochInfo.Masternodes) - if err != nil { - log.Error("[verifyQC] Error while verfying QC message signatures", "Error", err) - sigErrChan <- errors.New("error while verfying QC message signatures") - return + eg, ctx := errgroup.WithContext(context.Background()) + eg.SetLimit(runtime.NumCPU()) + for _, sig := range signatures { + eg.Go(func() error { + select { + case <-ctx.Done(): + return ctx.Err() + default: + verified, _, err := x.verifyMsgSignature(types.VoteSigHash(&types.VoteForSign{ + ProposedBlockInfo: quorumCert.ProposedBlockInfo, + GapNumber: quorumCert.GapNumber, + }), sig, epochInfo.Masternodes) + if err != nil { + log.Error("[verifyQC] Error while verfying QC message signatures", "Error", err) + return errors.New("error while verfying QC message signatures") + } + if !verified { + log.Warn("[verifyQC] Signature not verified doing QC verification", "QC", quorumCert) + return errors.New("fail to verify QC due to signature mis-match") + } + return nil } - if !verified { - log.Warn("[verifyQC] Signature not verified doing QC verification", "QC", quorumCert) - sigErrChan <- errors.New("fail to verify QC due to signature mis-match") - return - } - }(signature) + }) } - wg.Wait() + err = eg.Wait() + elapsed := time.Since(start) log.Debug("[verifyQC] time verify message signatures of qc", "elapsed", elapsed) - if len(sigErrChan) > 0 { - return <-sigErrChan + if err != nil { + return err } epochSwitchNumber := epochInfo.EpochSwitchBlockInfo.Number.Uint64() gapNumber := epochSwitchNumber - epochSwitchNumber%x.config.Epoch