mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-08-13 15:33:47 +00:00
Merge pull request #65 from maticnetwork/revert-active-seal
fix: revert cancel active seal / remove errRecentlySigned
This commit is contained in:
commit
cdf49567ee
7 changed files with 62 additions and 103 deletions
|
|
@ -121,18 +121,8 @@ var (
|
||||||
// errOutOfRangeChain is returned if an authorization list is attempted to
|
// errOutOfRangeChain is returned if an authorization list is attempted to
|
||||||
// be modified via out-of-range or non-contiguous headers.
|
// be modified via out-of-range or non-contiguous headers.
|
||||||
errOutOfRangeChain = errors.New("out of range or non-contiguous chain")
|
errOutOfRangeChain = errors.New("out of range or non-contiguous chain")
|
||||||
|
|
||||||
// errRecentlySigned is returned if a header is signed by an authorized entity
|
|
||||||
// that already signed a header recently, thus is temporarily not allowed to.
|
|
||||||
errRecentlySigned = errors.New("recently signed")
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// ActiveSealingOp keeps the context of the active sealing operation
|
|
||||||
type ActiveSealingOp struct {
|
|
||||||
number uint64
|
|
||||||
cancel context.CancelFunc
|
|
||||||
}
|
|
||||||
|
|
||||||
// SignerFn is a signer callback function to request a header to be signed by a
|
// SignerFn is a signer callback function to request a header to be signed by a
|
||||||
// backing account.
|
// backing account.
|
||||||
type SignerFn func(accounts.Account, string, []byte) ([]byte, error)
|
type SignerFn func(accounts.Account, string, []byte) ([]byte, error)
|
||||||
|
|
@ -238,9 +228,8 @@ type Bor struct {
|
||||||
stateReceiverABI abi.ABI
|
stateReceiverABI abi.ABI
|
||||||
HeimdallClient IHeimdallClient
|
HeimdallClient IHeimdallClient
|
||||||
|
|
||||||
stateDataFeed event.Feed
|
stateDataFeed event.Feed
|
||||||
scope event.SubscriptionScope
|
scope event.SubscriptionScope
|
||||||
activeSealingOp *ActiveSealingOp
|
|
||||||
// The fields below are for testing only
|
// The fields below are for testing only
|
||||||
fakeDiff bool // Skip difficulty verifications
|
fakeDiff bool // Skip difficulty verifications
|
||||||
}
|
}
|
||||||
|
|
@ -566,7 +555,8 @@ func (c *Bor) verifySeal(chain consensus.ChainReader, header *types.Header, pare
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if !snap.ValidatorSet.HasAddress(signer.Bytes()) {
|
if !snap.ValidatorSet.HasAddress(signer.Bytes()) {
|
||||||
return &UnauthorizedSignerError{number, signer.Bytes()}
|
// Check the UnauthorizedSignerError.Error() msg to see why we pass number-1
|
||||||
|
return &UnauthorizedSignerError{number - 1, signer.Bytes()}
|
||||||
}
|
}
|
||||||
|
|
||||||
succession, err := snap.GetSignerSuccessionNumber(signer)
|
succession, err := snap.GetSignerSuccessionNumber(signer)
|
||||||
|
|
@ -728,9 +718,6 @@ func (c *Bor) Authorize(signer common.Address, signFn SignerFn) {
|
||||||
// Seal implements consensus.Engine, attempting to create a sealed block using
|
// Seal implements consensus.Engine, attempting to create a sealed block using
|
||||||
// the local signing credentials.
|
// the local signing credentials.
|
||||||
func (c *Bor) Seal(chain consensus.ChainReader, block *types.Block, results chan<- *types.Block, stop <-chan struct{}) error {
|
func (c *Bor) Seal(chain consensus.ChainReader, block *types.Block, results chan<- *types.Block, stop <-chan struct{}) error {
|
||||||
// if c.activeSealingOp != nil {
|
|
||||||
// return &SealingInFlightError{c.activeSealingOp.number}
|
|
||||||
// }
|
|
||||||
header := block.Header()
|
header := block.Header()
|
||||||
|
|
||||||
// Sealing the genesis block is not supported
|
// Sealing the genesis block is not supported
|
||||||
|
|
@ -755,7 +742,8 @@ func (c *Bor) Seal(chain consensus.ChainReader, block *types.Block, results chan
|
||||||
|
|
||||||
// Bail out if we're unauthorized to sign a block
|
// Bail out if we're unauthorized to sign a block
|
||||||
if !snap.ValidatorSet.HasAddress(signer.Bytes()) {
|
if !snap.ValidatorSet.HasAddress(signer.Bytes()) {
|
||||||
return &UnauthorizedSignerError{number, signer.Bytes()}
|
// Check the UnauthorizedSignerError.Error() msg to see why we pass number-1
|
||||||
|
return &UnauthorizedSignerError{number - 1, signer.Bytes()}
|
||||||
}
|
}
|
||||||
|
|
||||||
successionNumber, err := snap.GetSignerSuccessionNumber(signer)
|
successionNumber, err := snap.GetSignerSuccessionNumber(signer)
|
||||||
|
|
@ -777,17 +765,12 @@ func (c *Bor) Seal(chain consensus.ChainReader, block *types.Block, results chan
|
||||||
|
|
||||||
// Wait until sealing is terminated or delay timeout.
|
// Wait until sealing is terminated or delay timeout.
|
||||||
log.Trace("Waiting for slot to sign and propagate", "delay", common.PrettyDuration(delay))
|
log.Trace("Waiting for slot to sign and propagate", "delay", common.PrettyDuration(delay))
|
||||||
shouldSeal := make(chan bool)
|
|
||||||
go c.WaitForSealingOp(number, shouldSeal, delay, stop)
|
|
||||||
go func() {
|
go func() {
|
||||||
defer func() {
|
select {
|
||||||
close(shouldSeal)
|
case <-stop:
|
||||||
c.activeSealingOp = nil
|
log.Debug("Discarding sealing operation for block", "number", number)
|
||||||
}()
|
|
||||||
switch <-shouldSeal {
|
|
||||||
case false:
|
|
||||||
return
|
return
|
||||||
case true:
|
case <-time.After(delay):
|
||||||
if wiggle > 0 {
|
if wiggle > 0 {
|
||||||
log.Info(
|
log.Info(
|
||||||
"Sealing out-of-turn",
|
"Sealing out-of-turn",
|
||||||
|
|
@ -803,38 +786,15 @@ func (c *Bor) Seal(chain consensus.ChainReader, block *types.Block, results chan
|
||||||
"headerDifficulty", header.Difficulty,
|
"headerDifficulty", header.Difficulty,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
select {
|
select {
|
||||||
case results <- block.WithSeal(header):
|
case results <- block.WithSeal(header):
|
||||||
default:
|
default:
|
||||||
log.Warn("Sealing result was not read by miner", "sealhash", SealHash(header))
|
log.Warn("Sealing result was not read by miner", "number", number, "sealhash", SealHash(header))
|
||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// WaitForSealingOp blocks until delay elapses or stop signal is received
|
|
||||||
func (c *Bor) WaitForSealingOp(number uint64, shouldSeal chan bool, delay time.Duration, stop <-chan struct{}) {
|
|
||||||
ctx, cancel := context.WithCancel(context.Background())
|
|
||||||
c.activeSealingOp = &ActiveSealingOp{number, cancel}
|
|
||||||
select {
|
|
||||||
case <-stop:
|
|
||||||
shouldSeal <- false
|
|
||||||
case <-ctx.Done():
|
|
||||||
shouldSeal <- false
|
|
||||||
case <-time.After(delay):
|
|
||||||
shouldSeal <- true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// CancelActiveSealingOp cancels in-flight sealing process
|
|
||||||
func (c *Bor) CancelActiveSealingOp() {
|
|
||||||
if c.activeSealingOp != nil {
|
|
||||||
log.Debug("Discarding active sealing operation", "number", c.activeSealingOp.number)
|
|
||||||
c.activeSealingOp.cancel()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// CalcDifficulty is the difficulty adjustment algorithm. It returns the difficulty
|
// CalcDifficulty is the difficulty adjustment algorithm. It returns the difficulty
|
||||||
// that a new block should have based on the previous blocks in the chain and the
|
// that a new block should have based on the previous blocks in the chain and the
|
||||||
// current signer.
|
// current signer.
|
||||||
|
|
|
||||||
|
|
@ -160,3 +160,30 @@ func TestOutOfTurnSigning(t *testing.T) {
|
||||||
_, err = chain.InsertChain([]*types.Block{block})
|
_, err = chain.InsertChain([]*types.Block{block})
|
||||||
assert.Nil(t, err)
|
assert.Nil(t, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestSignerNotFound(t *testing.T) {
|
||||||
|
init := buildEthereumInstance(t, rawdb.NewMemoryDatabase())
|
||||||
|
chain := init.ethereum.BlockChain()
|
||||||
|
engine := init.ethereum.Engine()
|
||||||
|
_bor := engine.(*bor.Bor)
|
||||||
|
|
||||||
|
res, _ := loadSpanFromFile(t)
|
||||||
|
h := &mocks.IHeimdallClient{}
|
||||||
|
h.On("FetchWithRetry", "bor", "span", "1").Return(res, nil)
|
||||||
|
_bor.SetHeimdallClient(h)
|
||||||
|
|
||||||
|
db := init.ethereum.ChainDb()
|
||||||
|
block := init.genesis.ToBlock(db)
|
||||||
|
|
||||||
|
// random signer account that is not a part of the validator set
|
||||||
|
signer := "3714d99058cd64541433d59c6b391555b2fd9b54629c2b717a6c9c00d1127b6b"
|
||||||
|
signerKey, _ := hex.DecodeString(signer)
|
||||||
|
key, _ = crypto.HexToECDSA(signer)
|
||||||
|
addr = crypto.PubkeyToAddress(key.PublicKey)
|
||||||
|
|
||||||
|
block = buildNextBlock(t, _bor, chain, block, signerKey, init.genesis.Config.Bor)
|
||||||
|
_, err := chain.InsertChain([]*types.Block{block})
|
||||||
|
assert.Equal(t,
|
||||||
|
*err.(*bor.UnauthorizedSignerError),
|
||||||
|
bor.UnauthorizedSignerError{Number: 0, Signer: addr.Bytes()})
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -84,9 +84,9 @@ func TestGetSignerSuccessionNumber_ProposerNotFound(t *testing.T) {
|
||||||
signer := snap.ValidatorSet.Validators[3].Address
|
signer := snap.ValidatorSet.Validators[3].Address
|
||||||
_, err := snap.GetSignerSuccessionNumber(signer)
|
_, err := snap.GetSignerSuccessionNumber(signer)
|
||||||
assert.NotNil(t, err)
|
assert.NotNil(t, err)
|
||||||
e, ok := err.(*bor.ProposerNotFoundError)
|
e, ok := err.(*bor.UnauthorizedProposerError)
|
||||||
assert.True(t, ok)
|
assert.True(t, ok)
|
||||||
assert.Equal(t, dummyProposerAddress, e.Address)
|
assert.Equal(t, dummyProposerAddress.Bytes(), e.Proposer)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestGetSignerSuccessionNumber_SignerNotFound(t *testing.T) {
|
func TestGetSignerSuccessionNumber_SignerNotFound(t *testing.T) {
|
||||||
|
|
@ -97,9 +97,9 @@ func TestGetSignerSuccessionNumber_SignerNotFound(t *testing.T) {
|
||||||
dummySignerAddress := randomAddress()
|
dummySignerAddress := randomAddress()
|
||||||
_, err := snap.GetSignerSuccessionNumber(dummySignerAddress)
|
_, err := snap.GetSignerSuccessionNumber(dummySignerAddress)
|
||||||
assert.NotNil(t, err)
|
assert.NotNil(t, err)
|
||||||
e, ok := err.(*bor.SignerNotFoundError)
|
e, ok := err.(*bor.UnauthorizedSignerError)
|
||||||
assert.True(t, ok)
|
assert.True(t, ok)
|
||||||
assert.Equal(t, dummySignerAddress, e.Address)
|
assert.Equal(t, dummySignerAddress.Bytes(), e.Signer)
|
||||||
}
|
}
|
||||||
|
|
||||||
func buildRandomValidatorSet(numVals int) []*bor.Validator {
|
func buildRandomValidatorSet(numVals int) []*bor.Validator {
|
||||||
|
|
|
||||||
|
|
@ -2,30 +2,8 @@ package bor
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
"github.com/maticnetwork/bor/common"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// Will include any new bor consensus errors here in an attempt to make error messages more descriptive
|
|
||||||
|
|
||||||
// ProposerNotFoundError is returned if the given proposer address is not present in the validator set
|
|
||||||
type ProposerNotFoundError struct {
|
|
||||||
Address common.Address
|
|
||||||
}
|
|
||||||
|
|
||||||
func (e *ProposerNotFoundError) Error() string {
|
|
||||||
return fmt.Sprintf("Proposer: %s not found", e.Address.Hex())
|
|
||||||
}
|
|
||||||
|
|
||||||
// SignerNotFoundError is returned when the signer address is not present in the validator set
|
|
||||||
type SignerNotFoundError struct {
|
|
||||||
Address common.Address
|
|
||||||
}
|
|
||||||
|
|
||||||
func (e *SignerNotFoundError) Error() string {
|
|
||||||
return fmt.Sprintf("Signer: %s not found", e.Address.Hex())
|
|
||||||
}
|
|
||||||
|
|
||||||
// TotalVotingPowerExceededError is returned when the maximum allowed total voting power is exceeded
|
// TotalVotingPowerExceededError is returned when the maximum allowed total voting power is exceeded
|
||||||
type TotalVotingPowerExceededError struct {
|
type TotalVotingPowerExceededError struct {
|
||||||
Sum int64
|
Sum int64
|
||||||
|
|
@ -69,17 +47,6 @@ func (e *MaxCheckpointLengthExceededError) Error() string {
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
type SealingInFlightError struct {
|
|
||||||
Number uint64
|
|
||||||
}
|
|
||||||
|
|
||||||
func (e *SealingInFlightError) Error() string {
|
|
||||||
return fmt.Sprintf(
|
|
||||||
"Requested concurrent block sealing. Sealing for block %d is already in progress",
|
|
||||||
e.Number,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
// MismatchingValidatorsError is returned if a last block in sprint contains a
|
// MismatchingValidatorsError is returned if a last block in sprint contains a
|
||||||
// list of validators different from the one that local node calculated
|
// list of validators different from the one that local node calculated
|
||||||
type MismatchingValidatorsError struct {
|
type MismatchingValidatorsError struct {
|
||||||
|
|
@ -110,7 +77,21 @@ func (e *BlockTooSoonError) Error() string {
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
// UnauthorizedSignerError is returned if a header is signed by a non-authorized entity.
|
// UnauthorizedProposerError is returned if a header is [being] signed by an unauthorized entity.
|
||||||
|
type UnauthorizedProposerError struct {
|
||||||
|
Number uint64
|
||||||
|
Proposer []byte
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e *UnauthorizedProposerError) Error() string {
|
||||||
|
return fmt.Sprintf(
|
||||||
|
"Proposer 0x%x is not a part of the producer set at block %d",
|
||||||
|
e.Proposer,
|
||||||
|
e.Number,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
// UnauthorizedSignerError is returned if a header is [being] signed by an unauthorized entity.
|
||||||
type UnauthorizedSignerError struct {
|
type UnauthorizedSignerError struct {
|
||||||
Number uint64
|
Number uint64
|
||||||
Signer []byte
|
Signer []byte
|
||||||
|
|
@ -118,9 +99,9 @@ type UnauthorizedSignerError struct {
|
||||||
|
|
||||||
func (e *UnauthorizedSignerError) Error() string {
|
func (e *UnauthorizedSignerError) Error() string {
|
||||||
return fmt.Sprintf(
|
return fmt.Sprintf(
|
||||||
"Validator set for block %d doesn't contain the signer 0x%x\n",
|
"Signer 0x%x is not a part of the producer set at block %d",
|
||||||
e.Number,
|
|
||||||
e.Signer,
|
e.Signer,
|
||||||
|
e.Number,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -26,7 +26,6 @@ import (
|
||||||
"github.com/maticnetwork/bor/core/types"
|
"github.com/maticnetwork/bor/core/types"
|
||||||
"github.com/maticnetwork/bor/ethdb"
|
"github.com/maticnetwork/bor/ethdb"
|
||||||
"github.com/maticnetwork/bor/internal/ethapi"
|
"github.com/maticnetwork/bor/internal/ethapi"
|
||||||
"github.com/maticnetwork/bor/log"
|
|
||||||
"github.com/maticnetwork/bor/params"
|
"github.com/maticnetwork/bor/params"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
@ -191,24 +190,18 @@ func (s *Snapshot) GetSignerSuccessionNumber(signer common.Address) (int, error)
|
||||||
proposer := s.ValidatorSet.GetProposer().Address
|
proposer := s.ValidatorSet.GetProposer().Address
|
||||||
proposerIndex, _ := s.ValidatorSet.GetByAddress(proposer)
|
proposerIndex, _ := s.ValidatorSet.GetByAddress(proposer)
|
||||||
if proposerIndex == -1 {
|
if proposerIndex == -1 {
|
||||||
return -1, &ProposerNotFoundError{proposer}
|
return -1, &UnauthorizedProposerError{s.Number, proposer.Bytes()}
|
||||||
}
|
}
|
||||||
signerIndex, _ := s.ValidatorSet.GetByAddress(signer)
|
signerIndex, _ := s.ValidatorSet.GetByAddress(signer)
|
||||||
if signerIndex == -1 {
|
if signerIndex == -1 {
|
||||||
return -1, &SignerNotFoundError{signer}
|
return -1, &UnauthorizedSignerError{s.Number, signer.Bytes()}
|
||||||
}
|
}
|
||||||
limit := len(validators)/2 + 1
|
|
||||||
|
|
||||||
tempIndex := signerIndex
|
tempIndex := signerIndex
|
||||||
if proposerIndex != tempIndex && limit > 0 {
|
if proposerIndex != tempIndex {
|
||||||
if tempIndex < proposerIndex {
|
if tempIndex < proposerIndex {
|
||||||
tempIndex = tempIndex + len(validators)
|
tempIndex = tempIndex + len(validators)
|
||||||
}
|
}
|
||||||
|
|
||||||
if tempIndex-proposerIndex > limit {
|
|
||||||
log.Info("errRecentlySigned", "proposerIndex", validators[proposerIndex].Address.Hex(), "signerIndex", validators[signerIndex].Address.Hex())
|
|
||||||
return -1, errRecentlySigned
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return tempIndex - proposerIndex, nil
|
return tempIndex - proposerIndex, nil
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -120,7 +120,6 @@ type Engine interface {
|
||||||
type Bor interface {
|
type Bor interface {
|
||||||
Engine
|
Engine
|
||||||
IsValidatorAction(chain ChainReader, from common.Address, tx *types.Transaction) bool
|
IsValidatorAction(chain ChainReader, from common.Address, tx *types.Transaction) bool
|
||||||
CancelActiveSealingOp()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// PoW is a consensus engine based on proof-of-work.
|
// PoW is a consensus engine based on proof-of-work.
|
||||||
|
|
|
||||||
|
|
@ -1718,7 +1718,6 @@ func (bc *BlockChain) insertChain(chain types.Blocks, verifySeals bool) (int, []
|
||||||
if lastCanon != nil && bc.CurrentBlock().Hash() == lastCanon.Hash() {
|
if lastCanon != nil && bc.CurrentBlock().Hash() == lastCanon.Hash() {
|
||||||
events = append(events, ChainHeadEvent{lastCanon})
|
events = append(events, ChainHeadEvent{lastCanon})
|
||||||
}
|
}
|
||||||
bc.engine.(consensus.Bor).CancelActiveSealingOp()
|
|
||||||
return it.index, events, coalescedLogs, err
|
return it.index, events, coalescedLogs, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue