diff --git a/cmd/bor/chaincmd.go b/cmd/bor/chaincmd.go index bbb8792a16e83879cb37f70bc92e6561a7eb79e7..83d3261566ec92a157dde9adce7cee4c6fcff5ba 100644 --- a/cmd/bor/chaincmd.go +++ b/cmd/bor/chaincmd.go @@ -64,6 +64,7 @@ It expects the genesis file as argument.`, ArgsUsage: "<filename> (<filename 2> ... <filename N>) <genesisPath>", Flags: []cli.Flag{ utils.DataDirFlag, + utils.HeimdallURLFlag, utils.CacheFlag, utils.SyncModeFlag, utils.GCModeFlag, diff --git a/cmd/bor/config.go b/cmd/bor/config.go index 4929d826eb0be37d7b9cec6c3f56d8130a33ac4e..9202fec7c4daebd0b9775f94d19689979466101c 100644 --- a/cmd/bor/config.go +++ b/cmd/bor/config.go @@ -151,7 +151,7 @@ func enableWhisper(ctx *cli.Context) bool { func makeFullNode(ctx *cli.Context) *node.Node { stack, cfg := makeConfigNode(ctx) - cfg.Eth.HeimdallURL = ctx.String(utils.HeimdallURLFlag.Name) + cfg.Eth.HeimdallURL = ctx.GlobalString(utils.HeimdallURLFlag.Name) log.Info("Connecting to heimdall service on...", "heimdallURL", cfg.Eth.HeimdallURL) utils.RegisterEthService(stack, &cfg.Eth) diff --git a/cmd/utils/flags.go b/cmd/utils/flags.go index fa0aa9bf163027368bad09af0375bb4f6687c11f..78a70beabeba715c8758671bdbd8bd9f2295b669 100644 --- a/cmd/utils/flags.go +++ b/cmd/utils/flags.go @@ -1694,7 +1694,7 @@ func MakeChain(ctx *cli.Context, stack *node.Node) (chain *core.BlockChain, chai if config.Clique != nil { engine = clique.New(config.Clique, chainDb) } else if config.Bor != nil { - cfg := ð.Config{Genesis: genesis} + cfg := ð.Config{Genesis: genesis, HeimdallURL: ctx.GlobalString(HeimdallURLFlag.Name)} workspace, err := ioutil.TempDir("", "console-tester-") if err != nil { Fatalf("failed to create temporary keystore: %v", err) diff --git a/consensus/bor/bor.go b/consensus/bor/bor.go index 43ebe93fd4bfff80537dc1de358f7f45d820bd46..d0d66403bf7fb5d8eab4ea064dd0a308a097d38c 100644 --- a/consensus/bor/bor.go +++ b/consensus/bor/bor.go @@ -119,18 +119,8 @@ var ( // errOutOfRangeChain is returned if an authorization list is attempted to // be modified via out-of-range or non-contiguous headers. 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 // backing account. type SignerFn func(accounts.Account, string, []byte) ([]byte, error) @@ -237,9 +227,8 @@ type Bor struct { stateReceiverABI abi.ABI HeimdallClient IHeimdallClient - stateDataFeed event.Feed - scope event.SubscriptionScope - activeSealingOp *ActiveSealingOp + stateDataFeed event.Feed + scope event.SubscriptionScope // The fields below are for testing only fakeDiff bool // Skip difficulty verifications } @@ -566,7 +555,8 @@ func (c *Bor) verifySeal(chain consensus.ChainReader, header *types.Header, pare return err } 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) @@ -728,9 +718,6 @@ func (c *Bor) Authorize(signer common.Address, signFn SignerFn) { // Seal implements consensus.Engine, attempting to create a sealed block using // the local signing credentials. 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() // 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 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) @@ -777,17 +765,12 @@ func (c *Bor) Seal(chain consensus.ChainReader, block *types.Block, results chan // Wait until sealing is terminated or delay timeout. 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() { - defer func() { - close(shouldSeal) - c.activeSealingOp = nil - }() - switch <-shouldSeal { - case false: + select { + case <-stop: + log.Debug("Discarding sealing operation for block", "number", number) return - case true: + case <-time.After(delay): if wiggle > 0 { log.Info( "Sealing out-of-turn", @@ -803,38 +786,15 @@ func (c *Bor) Seal(chain consensus.ChainReader, block *types.Block, results chan "headerDifficulty", header.Difficulty, ) } - select { case results <- block.WithSeal(header): 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 } -// 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 // that a new block should have based on the previous blocks in the chain and the // current signer. diff --git a/consensus/bor/bor_test/bor_test.go b/consensus/bor/bor_test/bor_test.go index 56b2e38f8a11a3e33e9cc4723f592180dccea08c..0bd4a5065374794d3bbaedc8f850d34ee6cb3939 100644 --- a/consensus/bor/bor_test/bor_test.go +++ b/consensus/bor/bor_test/bor_test.go @@ -102,6 +102,30 @@ func TestOutOfTurnSigning(t *testing.T) { 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) + h, _ := getMockedHeimdallClient(t) + _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()}) +} + func getMockedHeimdallClient(t *testing.T) (*mocks.IHeimdallClient, *bor.HeimdallSpan) { res, heimdallSpan := loadSpanFromFile(t) h := &mocks.IHeimdallClient{} diff --git a/consensus/bor/bor_test/snapshot_test.go b/consensus/bor/bor_test/snapshot_test.go index 264c63295299f6967f16c4fd124bd4266a2f3a63..6eb43b3e60374dc594cdbd02209e8a73de81607e 100644 --- a/consensus/bor/bor_test/snapshot_test.go +++ b/consensus/bor/bor_test/snapshot_test.go @@ -84,9 +84,9 @@ func TestGetSignerSuccessionNumber_ProposerNotFound(t *testing.T) { signer := snap.ValidatorSet.Validators[3].Address _, err := snap.GetSignerSuccessionNumber(signer) assert.NotNil(t, err) - e, ok := err.(*bor.ProposerNotFoundError) + e, ok := err.(*bor.UnauthorizedProposerError) assert.True(t, ok) - assert.Equal(t, dummyProposerAddress, e.Address) + assert.Equal(t, dummyProposerAddress.Bytes(), e.Proposer) } func TestGetSignerSuccessionNumber_SignerNotFound(t *testing.T) { @@ -97,9 +97,9 @@ func TestGetSignerSuccessionNumber_SignerNotFound(t *testing.T) { dummySignerAddress := randomAddress() _, err := snap.GetSignerSuccessionNumber(dummySignerAddress) assert.NotNil(t, err) - e, ok := err.(*bor.SignerNotFoundError) + e, ok := err.(*bor.UnauthorizedSignerError) assert.True(t, ok) - assert.Equal(t, dummySignerAddress, e.Address) + assert.Equal(t, dummySignerAddress.Bytes(), e.Signer) } func buildRandomValidatorSet(numVals int) []*bor.Validator { diff --git a/consensus/bor/errors.go b/consensus/bor/errors.go index 76d9a3ee22e815c6d541107feaef18a1a191c180..fce71cd6f284784655b1ae691f689ce22c4e2c7a 100644 --- a/consensus/bor/errors.go +++ b/consensus/bor/errors.go @@ -3,30 +3,8 @@ package bor import ( "fmt" "time" - - "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 type TotalVotingPowerExceededError struct { Sum int64 @@ -70,17 +48,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 // list of validators different from the one that local node calculated type MismatchingValidatorsError struct { @@ -111,7 +78,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 { Number uint64 Signer []byte @@ -119,9 +100,9 @@ type UnauthorizedSignerError struct { func (e *UnauthorizedSignerError) Error() string { return fmt.Sprintf( - "Validator set for block %d doesn't contain the signer 0x%x\n", - e.Number, + "Signer 0x%x is not a part of the producer set at block %d", e.Signer, + e.Number, ) } diff --git a/consensus/bor/snapshot.go b/consensus/bor/snapshot.go index a62c2014b9996e71a39324a3d3c4e6b453414e8d..2ff7dec0cea12f83140de60e764097d7fbeed35f 100644 --- a/consensus/bor/snapshot.go +++ b/consensus/bor/snapshot.go @@ -26,7 +26,6 @@ import ( "github.com/maticnetwork/bor/core/types" "github.com/maticnetwork/bor/ethdb" "github.com/maticnetwork/bor/internal/ethapi" - "github.com/maticnetwork/bor/log" "github.com/maticnetwork/bor/params" ) @@ -191,24 +190,18 @@ func (s *Snapshot) GetSignerSuccessionNumber(signer common.Address) (int, error) proposer := s.ValidatorSet.GetProposer().Address proposerIndex, _ := s.ValidatorSet.GetByAddress(proposer) if proposerIndex == -1 { - return -1, &ProposerNotFoundError{proposer} + return -1, &UnauthorizedProposerError{s.Number, proposer.Bytes()} } signerIndex, _ := s.ValidatorSet.GetByAddress(signer) if signerIndex == -1 { - return -1, &SignerNotFoundError{signer} + return -1, &UnauthorizedSignerError{s.Number, signer.Bytes()} } - limit := len(validators)/2 + 1 tempIndex := signerIndex - if proposerIndex != tempIndex && limit > 0 { + if proposerIndex != tempIndex { if tempIndex < proposerIndex { 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 } diff --git a/consensus/consensus.go b/consensus/consensus.go index 689c840dae5caa000cd26d09eab533a7ca808619..e86583f394d0c6a56b7e28e1de5c8ac7184a97f9 100644 --- a/consensus/consensus.go +++ b/consensus/consensus.go @@ -116,12 +116,6 @@ type Engine interface { Close() error } -// Bor is a consensus engine developed by folks at Matic Network -type Bor interface { - Engine - CancelActiveSealingOp() -} - // PoW is a consensus engine based on proof-of-work. type PoW interface { Engine diff --git a/core/blockchain.go b/core/blockchain.go index 3ce4356929e29df8e2fc9faef54337d5b9b82aa5..e90ffbb30eac7c53fb032e225ccc53b1f3b040b3 100644 --- a/core/blockchain.go +++ b/core/blockchain.go @@ -1718,7 +1718,6 @@ func (bc *BlockChain) insertChain(chain types.Blocks, verifySeals bool) (int, [] if lastCanon != nil && bc.CurrentBlock().Hash() == lastCanon.Hash() { events = append(events, ChainHeadEvent{lastCanon}) } - bc.engine.(consensus.Bor).CancelActiveSealingOp() return it.index, events, coalescedLogs, err }