@@ -181,7 +181,7 @@ type Clique struct {
181181
182182 signer common.Address // Ethereum address of the signing key
183183 signFn SignerFn // Signer function to authorize hashes with
184- lock sync.RWMutex // Protects the signer fields
184+ lock sync.RWMutex // Protects the signer and proposals fields
185185
186186 // The fields below are for testing only
187187 fakeDiff bool // Skip difficulty verifications
@@ -509,9 +509,8 @@ func (c *Clique) Prepare(chain consensus.ChainHeaderReader, header *types.Header
509509 if err != nil {
510510 return err
511511 }
512+ c .lock .RLock ()
512513 if number % c .config .Epoch != 0 {
513- c .lock .RLock ()
514-
515514 // Gather all the proposals that make sense voting on
516515 addresses := make ([]common.Address , 0 , len (c .proposals ))
517516 for address , authorize := range c .proposals {
@@ -528,10 +527,14 @@ func (c *Clique) Prepare(chain consensus.ChainHeaderReader, header *types.Header
528527 copy (header .Nonce [:], nonceDropVote )
529528 }
530529 }
531- c .lock .RUnlock ()
532530 }
531+
532+ // Copy signer protected by mutex to avoid race condition
533+ signer := c .signer
534+ c .lock .RUnlock ()
535+
533536 // Set the correct difficulty
534- header .Difficulty = calcDifficulty (snap , c . signer )
537+ header .Difficulty = calcDifficulty (snap , signer )
535538
536539 // Ensure the extra data has all its components
537540 if len (header .Extra ) < extraVanity {
@@ -670,7 +673,10 @@ func (c *Clique) CalcDifficulty(chain consensus.ChainHeaderReader, time uint64,
670673 if err != nil {
671674 return nil
672675 }
673- return calcDifficulty (snap , c .signer )
676+ c .lock .RLock ()
677+ signer := c .signer
678+ c .lock .RUnlock ()
679+ return calcDifficulty (snap , signer )
674680}
675681
676682func calcDifficulty (snap * Snapshot , signer common.Address ) * big.Int {
0 commit comments