Skip to content

Commit e6749a0

Browse files
Revert "consensus/clique, miner: remove clique -> accounts dependency (ethereum#30642)"
This reverts commit 31a6418.
1 parent 0ecde76 commit e6749a0

File tree

3 files changed

+76
-4
lines changed

3 files changed

+76
-4
lines changed

consensus/clique/clique.go

Lines changed: 74 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ import (
2727
"sync"
2828
"time"
2929

30+
"github.com/ethereum/go-ethereum/accounts"
3031
"github.com/ethereum/go-ethereum/common"
3132
"github.com/ethereum/go-ethereum/common/hexutil"
3233
"github.com/ethereum/go-ethereum/common/lru"
@@ -50,6 +51,8 @@ const (
5051
checkpointInterval = 1024 // Number of blocks after which to save the vote snapshot to the database
5152
inmemorySnapshots = 128 // Number of recent vote snapshots to keep in memory
5253
inmemorySignatures = 4096 // Number of recent block signatures to keep in memory
54+
55+
wiggleTime = 500 * time.Millisecond // Random delay (per signer) to allow concurrent signers
5356
)
5457

5558
// Clique proof-of-authority protocol constants.
@@ -138,6 +141,9 @@ var (
138141
errRecentlySigned = errors.New("recently signed")
139142
)
140143

144+
// SignerFn hashes and signs the data to be signed by a backing account.
145+
type SignerFn func(signer accounts.Account, mimeType string, message []byte) ([]byte, error)
146+
141147
// ecrecover extracts the Ethereum account address from a signed header.
142148
func ecrecover(header *types.Header, sigcache *sigLRU) (common.Address, error) {
143149
// If the signature's already cached, return that
@@ -179,6 +185,7 @@ type Clique struct {
179185
proposals map[common.Address]bool // Current list of proposals we are pushing
180186

181187
signer common.Address // Ethereum address of the signing key
188+
signFn SignerFn // Signer function to authorize hashes with
182189
lock sync.RWMutex // Protects the signer and proposals fields
183190

184191
// The fields below are for testing only
@@ -635,17 +642,82 @@ func (c *Clique) FinalizeAndAssemble(chain consensus.ChainHeaderReader, header *
635642

636643
// Authorize injects a private key into the consensus engine to mint new blocks
637644
// with.
638-
func (c *Clique) Authorize(signer common.Address) {
645+
func (c *Clique) Authorize(signer common.Address, signFn SignerFn) {
639646
c.lock.Lock()
640647
defer c.lock.Unlock()
641648

642649
c.signer = signer
650+
c.signFn = signFn
643651
}
644652

645653
// Seal implements consensus.Engine, attempting to create a sealed block using
646654
// the local signing credentials.
647655
func (c *Clique) Seal(chain consensus.ChainHeaderReader, block *types.Block, results chan<- *types.Block, stop <-chan struct{}) error {
648-
panic("clique (poa) sealing not supported any more")
656+
header := block.Header()
657+
658+
// Sealing the genesis block is not supported
659+
number := header.Number.Uint64()
660+
if number == 0 {
661+
return errUnknownBlock
662+
}
663+
// For 0-period chains, refuse to seal empty blocks (no reward but would spin sealing)
664+
if c.config.Period == 0 && len(block.Transactions()) == 0 {
665+
return errors.New("sealing paused while waiting for transactions")
666+
}
667+
// Don't hold the signer fields for the entire sealing procedure
668+
c.lock.RLock()
669+
signer, signFn := c.signer, c.signFn
670+
c.lock.RUnlock()
671+
672+
// Bail out if we're unauthorized to sign a block
673+
snap, err := c.snapshot(chain, number-1, header.ParentHash, nil)
674+
if err != nil {
675+
return err
676+
}
677+
if _, authorized := snap.Signers[signer]; !authorized {
678+
return errUnauthorizedSigner
679+
}
680+
// If we're amongst the recent signers, wait for the next block
681+
for seen, recent := range snap.Recents {
682+
if recent == signer {
683+
// Signer is among recents, only wait if the current block doesn't shift it out
684+
if limit := uint64(len(snap.Signers)/2 + 1); number < limit || seen > number-limit {
685+
return errors.New("signed recently, must wait for others")
686+
}
687+
}
688+
}
689+
// Sweet, the protocol permits us to sign the block, wait for our time
690+
delay := time.Unix(int64(header.Time), 0).Sub(time.Now()) // nolint: gosimple
691+
if header.Difficulty.Cmp(diffNoTurn) == 0 {
692+
// It's not our turn explicitly to sign, delay it a bit
693+
wiggle := time.Duration(len(snap.Signers)/2+1) * wiggleTime
694+
delay += time.Duration(rand.Int63n(int64(wiggle)))
695+
696+
log.Trace("Out-of-turn signing requested", "wiggle", common.PrettyDuration(wiggle))
697+
}
698+
// Sign all the things!
699+
sighash, err := signFn(accounts.Account{Address: signer}, accounts.MimetypeClique, CliqueRLP(header))
700+
if err != nil {
701+
return err
702+
}
703+
copy(header.Extra[len(header.Extra)-extraSeal:], sighash)
704+
// Wait until sealing is terminated or delay timeout.
705+
log.Trace("Waiting for slot to sign and propagate", "delay", common.PrettyDuration(delay))
706+
go func() {
707+
select {
708+
case <-stop:
709+
return
710+
case <-time.After(delay):
711+
}
712+
713+
select {
714+
case results <- block.WithSeal(header):
715+
default:
716+
log.Warn("Sealing result is not read by miner", "sealhash", SealHash(header))
717+
}
718+
}()
719+
720+
return nil
649721
}
650722

651723
// CalcDifficulty is the difficulty adjustment algorithm. It returns the difficulty

eth/backend.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -548,7 +548,7 @@ func (s *Ethereum) StartMining() error {
548548
return fmt.Errorf("signer missing: %v", err)
549549
}
550550

551-
cli.Authorize(eb)
551+
cli.Authorize(eb, wallet.SignData)
552552
}
553553

554554
if bor, ok := s.engine.(*bor.Bor); ok {

internal/cli/server/server.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -231,7 +231,7 @@ func NewServer(config *Config, opts ...serverOption) (*Server, error) {
231231
return nil, fmt.Errorf("signer missing: %v", err)
232232
}
233233

234-
cli.Authorize(eb)
234+
cli.Authorize(eb, wallet.SignData)
235235

236236
authorized = true
237237
}

0 commit comments

Comments
 (0)