engines/engine_v2: use errgroup to handle goroutine error (#1758)

This commit is contained in:
wit liu 2025-11-14 22:29:43 +08:00 committed by GitHub
parent 5b873ea522
commit c82830d228
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 55 additions and 52 deletions

View file

@ -1,17 +1,19 @@
package engine_v2 package engine_v2
import ( import (
"context"
"errors" "errors"
"fmt" "fmt"
"runtime"
"strconv" "strconv"
"strings" "strings"
"sync"
"github.com/XinFinOrg/XDPoSChain/common" "github.com/XinFinOrg/XDPoSChain/common"
"github.com/XinFinOrg/XDPoSChain/consensus" "github.com/XinFinOrg/XDPoSChain/consensus"
"github.com/XinFinOrg/XDPoSChain/consensus/XDPoS/utils" "github.com/XinFinOrg/XDPoSChain/consensus/XDPoS/utils"
"github.com/XinFinOrg/XDPoSChain/core/types" "github.com/XinFinOrg/XDPoSChain/core/types"
"github.com/XinFinOrg/XDPoSChain/log" "github.com/XinFinOrg/XDPoSChain/log"
"golang.org/x/sync/errgroup"
) )
// Verify syncInfo and trigger process QC or TC if successful // Verify syncInfo and trigger process QC or TC if successful
@ -127,31 +129,30 @@ func (x *XDPoS_v2) processSyncInfoPool(chain consensus.ChainReader) {
} }
func (x *XDPoS_v2) verifySignatures(messageHash common.Hash, signatures []types.Signature, candidates []common.Address) error { func (x *XDPoS_v2) verifySignatures(messageHash common.Hash, signatures []types.Signature, candidates []common.Address) error {
var wg sync.WaitGroup eg, ctx := errgroup.WithContext(context.Background())
wg.Add(len(signatures)) eg.SetLimit(runtime.NumCPU())
var haveError error
for _, signature := range signatures { for _, sig := range signatures {
go func(sig types.Signature) { eg.Go(func() error {
defer wg.Done() select {
verified, _, err := x.verifyMsgSignature(messageHash, sig, candidates) case <-ctx.Done():
if err != nil { return ctx.Err()
log.Error("[verifySignatures] Error while verfying QC message signatures", "error", err) default:
haveError = errors.New("error while verfying QC message signatures") verified, _, err := x.verifyMsgSignature(messageHash, sig, candidates)
return if err != nil {
log.Error("[verifySignatures] Error while verifying message signatures", "error", err)
return errors.New("error while verifying QC message signatures")
}
if !verified {
log.Error("[verifySignatures] Signature not verified during signature verification")
return errors.New("fail to verify QC due to signature mismatch")
}
return nil
} }
if !verified { })
log.Error("[verifySignatures] Signature not verified doing signature verification")
haveError = errors.New("fail to verify QC due to signature mismatch")
return
}
}(signature)
} }
wg.Wait()
if haveError != nil { return eg.Wait()
return haveError
}
return nil
} }
func (x *XDPoS_v2) hygieneSyncInfoPool() { func (x *XDPoS_v2) hygieneSyncInfoPool() {

View file

@ -1,11 +1,12 @@
package engine_v2 package engine_v2
import ( import (
"context"
"errors" "errors"
"fmt" "fmt"
"runtime"
"strconv" "strconv"
"strings" "strings"
"sync"
"time" "time"
"github.com/XinFinOrg/XDPoSChain/common" "github.com/XinFinOrg/XDPoSChain/common"
@ -13,6 +14,7 @@ import (
"github.com/XinFinOrg/XDPoSChain/consensus/XDPoS/utils" "github.com/XinFinOrg/XDPoSChain/consensus/XDPoS/utils"
"github.com/XinFinOrg/XDPoSChain/core/types" "github.com/XinFinOrg/XDPoSChain/core/types"
"github.com/XinFinOrg/XDPoSChain/log" "github.com/XinFinOrg/XDPoSChain/log"
"golang.org/x/sync/errgroup"
) )
func (x *XDPoS_v2) VerifyTimeoutMessage(chain consensus.ChainReader, timeoutMsg *types.Timeout) (bool, error) { func (x *XDPoS_v2) VerifyTimeoutMessage(chain consensus.ChainReader, timeoutMsg *types.Timeout) (bool, error) {
@ -184,42 +186,42 @@ func (x *XDPoS_v2) verifyTC(chain consensus.ChainReader, timeoutCert *types.Time
return utils.ErrInvalidTCSignatures return utils.ErrInvalidTCSignatures
} }
var wg sync.WaitGroup
wg.Add(len(signatures))
var mutex sync.Mutex
var haveError error
signedTimeoutObj := types.TimeoutSigHash(&types.TimeoutForSign{ signedTimeoutObj := types.TimeoutSigHash(&types.TimeoutForSign{
Round: timeoutCert.Round, Round: timeoutCert.Round,
GapNumber: timeoutCert.GapNumber, GapNumber: timeoutCert.GapNumber,
}) })
for _, signature := range signatures { eg, ctx := errgroup.WithContext(context.Background())
go func(sig types.Signature) { eg.SetLimit(runtime.NumCPU())
defer wg.Done()
verified, _, err := x.verifyMsgSignature(signedTimeoutObj, sig, snap.NextEpochCandidates) for _, sig := range signatures {
if err != nil || !verified { eg.Go(func() error {
log.Error("[verifyTC] Error or verification failure", "signature", sig, "error", err) select {
mutex.Lock() // Lock before accessing haveError case <-ctx.Done():
if haveError == nil { return ctx.Err()
if err != nil { default:
log.Error("[verifyTC] Error while verfying TC message signatures", "tcRound", timeoutCert.Round, "tcGapNumber", timeoutCert.GapNumber, "tcSignLen", len(signatures), "error", err) verified, _, err := x.verifyMsgSignature(signedTimeoutObj, sig, snap.NextEpochCandidates)
haveError = fmt.Errorf("error while verifying TC message signatures, %s", err) if err != nil {
} else { log.Error("[verifyTC] Error while verifying TC message signatures",
log.Warn("[verifyTC] Signature not verified doing TC verification", "tcRound", timeoutCert.Round, "tcGapNumber", timeoutCert.GapNumber, "tcSignLen", len(signatures)) "tcRound", timeoutCert.Round,
haveError = errors.New("fail to verify TC due to signature mis-match") "tcGapNumber", timeoutCert.GapNumber,
} "tcSignLen", len(signatures),
"error", err)
return fmt.Errorf("error while verifying TC message signatures: %w", err)
} }
mutex.Unlock() // Unlock after modifying haveError if !verified {
log.Warn("[verifyTC] Signature not verified during TC verification",
"tcRound", timeoutCert.Round,
"tcGapNumber", timeoutCert.GapNumber,
"tcSignLen", len(signatures))
return errors.New("fail to verify TC due to signature mis-match")
}
return nil
} }
}(signature) })
} }
wg.Wait()
if haveError != nil { return eg.Wait()
return haveError
}
return nil
} }
/* /*