@@ -180,7 +180,7 @@ type Clique struct {
180
180
181
181
signer common.Address // Ethereum address of the signing key
182
182
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
184
184
185
185
// The fields below are for testing only
186
186
fakeDiff bool // Skip difficulty verifications
@@ -507,9 +507,8 @@ func (c *Clique) Prepare(chain consensus.ChainHeaderReader, header *types.Header
507
507
if err != nil {
508
508
return err
509
509
}
510
+ c .lock .RLock ()
510
511
if number % c .config .Epoch != 0 {
511
- c .lock .RLock ()
512
-
513
512
// Gather all the proposals that make sense voting on
514
513
addresses := make ([]common.Address , 0 , len (c .proposals ))
515
514
for address , authorize := range c .proposals {
@@ -526,10 +525,14 @@ func (c *Clique) Prepare(chain consensus.ChainHeaderReader, header *types.Header
526
525
copy (header .Nonce [:], nonceDropVote )
527
526
}
528
527
}
529
- c .lock .RUnlock ()
530
528
}
529
+
530
+ // Copy signer protected by mutex to avoid race condition
531
+ signer := c .signer
532
+ c .lock .RUnlock ()
533
+
531
534
// Set the correct difficulty
532
- header .Difficulty = calcDifficulty (snap , c . signer )
535
+ header .Difficulty = calcDifficulty (snap , signer )
533
536
534
537
// Ensure the extra data has all its components
535
538
if len (header .Extra ) < extraVanity {
@@ -666,7 +669,10 @@ func (c *Clique) CalcDifficulty(chain consensus.ChainHeaderReader, time uint64,
666
669
if err != nil {
667
670
return nil
668
671
}
669
- return calcDifficulty (snap , c .signer )
672
+ c .lock .RLock ()
673
+ signer := c .signer
674
+ c .lock .RUnlock ()
675
+ return calcDifficulty (snap , signer )
670
676
}
671
677
672
678
func calcDifficulty (snap * Snapshot , signer common.Address ) * big.Int {
0 commit comments