@@ -180,7 +180,7 @@ type Clique struct {
180180
181181 signer common.Address // Ethereum address of the signing key
182182 signFn SignerFn // Signer function to authorize hashes with
183- lock sync.RWMutex // Protects the signer fields
183+ lock sync.RWMutex // Protects the signer and proposals fields
184184
185185 // The fields below are for testing only
186186 fakeDiff bool // Skip difficulty verifications
@@ -507,9 +507,8 @@ func (c *Clique) Prepare(chain consensus.ChainHeaderReader, header *types.Header
507507 if err != nil {
508508 return err
509509 }
510+ c .lock .RLock ()
510511 if number % c .config .Epoch != 0 {
511- c .lock .RLock ()
512-
513512 // Gather all the proposals that make sense voting on
514513 addresses := make ([]common.Address , 0 , len (c .proposals ))
515514 for address , authorize := range c .proposals {
@@ -526,10 +525,14 @@ func (c *Clique) Prepare(chain consensus.ChainHeaderReader, header *types.Header
526525 copy (header .Nonce [:], nonceDropVote )
527526 }
528527 }
529- c .lock .RUnlock ()
530528 }
529+
530+ // Copy signer protected by mutex to avoid race condition
531+ signer := c .signer
532+ c .lock .RUnlock ()
533+
531534 // Set the correct difficulty
532- header .Difficulty = calcDifficulty (snap , c . signer )
535+ header .Difficulty = calcDifficulty (snap , signer )
533536
534537 // Ensure the extra data has all its components
535538 if len (header .Extra ) < extraVanity {
@@ -666,7 +669,10 @@ func (c *Clique) CalcDifficulty(chain consensus.ChainHeaderReader, time uint64,
666669 if err != nil {
667670 return nil
668671 }
669- return calcDifficulty (snap , c .signer )
672+ c .lock .RLock ()
673+ signer := c .signer
674+ c .lock .RUnlock ()
675+ return calcDifficulty (snap , signer )
670676}
671677
672678func calcDifficulty (snap * Snapshot , signer common.Address ) * big.Int {
0 commit comments