@@ -18,6 +18,7 @@ package backend
1818
1919import (
2020 "crypto/ecdsa"
21+ "math/big"
2122 "sync"
2223 "time"
2324
@@ -35,6 +36,11 @@ import (
3536 lru "github.com/hashicorp/golang-lru"
3637)
3738
39+ const (
40+ // fetcherID is the ID indicates the block is from Istanbul engine
41+ fetcherID = "istanbul"
42+ )
43+
3844// New creates an Ethereum backend for Istanbul core engine.
3945func New (config * istanbul.Config , privateKey * ecdsa.PrivateKey , db ethdb.Database ) consensus.Istanbul {
4046 // Allocate the snapshot caches and create the engine
@@ -70,14 +76,15 @@ type backend struct {
7076 logger log.Logger
7177 db ethdb.Database
7278 chain consensus.ChainReader
73- inserter func (types.Blocks ) (int , error )
79+ currentBlock func () * types.Block
80+ hasBadBlock func (hash common.Hash ) bool
7481
7582 // the channels for istanbul engine notifications
7683 commitCh chan * types.Block
7784 proposedBlockHash common.Hash
7885 sealMu sync.Mutex
7986 coreStarted bool
80- coreMu sync.Mutex
87+ coreMu sync.RWMutex
8188
8289 // Current list of candidates we are pushing
8390 candidates map [common.Address ]bool
@@ -180,16 +187,11 @@ func (sb *backend) Commit(proposal istanbul.Proposal, seals [][]byte) error {
180187 if sb .proposedBlockHash == block .Hash () {
181188 // feed block hash to Seal() and wait the Seal() result
182189 sb .commitCh <- block
183- // TODO: how do we check the block is inserted correctly?
184190 return nil
185191 }
186- // if I'm not a proposer, insert the block directly and broadcast NewCommittedEvent
187- if _ , err := sb .inserter (types.Blocks {block }); err != nil && err != core .ErrKnownBlock {
188- return err
189- }
190192
191193 if sb .broadcaster != nil {
192- go sb .broadcaster .BroadcastBlock ( block , false )
194+ sb .broadcaster .Enqueue ( fetcherID , block )
193195 }
194196 return nil
195197}
@@ -208,6 +210,22 @@ func (sb *backend) Verify(proposal istanbul.Proposal) (time.Duration, error) {
208210 sb .logger .Error ("Invalid proposal, %v" , proposal )
209211 return 0 , errInvalidProposal
210212 }
213+
214+ // check bad block
215+ if sb .HasBadProposal (block .Hash ()) {
216+ return 0 , core .ErrBlacklistedHash
217+ }
218+
219+ // check block body
220+ txnHash := types .DeriveSha (block .Transactions ())
221+ uncleHash := types .CalcUncleHash (block .Uncles ())
222+ if txnHash != block .Header ().TxHash {
223+ return 0 , errMismatchTxhashes
224+ }
225+ if uncleHash != nilUncleHash {
226+ return 0 , errInvalidUncleHash
227+ }
228+
211229 // verify the header of proposed block
212230 err := sb .VerifyHeader (sb .chain , block .Header (), false )
213231 // ignore errEmptyCommittedSeals error because we don't have the committed seals yet
@@ -239,6 +257,11 @@ func (sb *backend) CheckSignature(data []byte, address common.Address, sig []byt
239257 return nil
240258}
241259
260+ // HasPropsal implements istanbul.Backend.HashBlock
261+ func (sb * backend ) HasPropsal (hash common.Hash , number * big.Int ) bool {
262+ return sb .chain .GetHeader (hash , number .Uint64 ()) != nil
263+ }
264+
242265// GetProposer implements istanbul.Backend.GetProposer
243266func (sb * backend ) GetProposer (number uint64 ) common.Address {
244267 if h := sb .chain .GetHeaderByNumber (number ); h != nil {
@@ -248,6 +271,14 @@ func (sb *backend) GetProposer(number uint64) common.Address {
248271 return common.Address {}
249272}
250273
274+ // ParentValidators implements istanbul.Backend.GetParentValidators
275+ func (sb * backend ) ParentValidators (proposal istanbul.Proposal ) istanbul.ValidatorSet {
276+ if block , ok := proposal .(* types.Block ); ok {
277+ return sb .getValidators (block .Number ().Uint64 ()- 1 , block .ParentHash ())
278+ }
279+ return validator .NewSet (nil , sb .config .ProposerPolicy )
280+ }
281+
251282func (sb * backend ) getValidators (number uint64 , hash common.Hash ) istanbul.ValidatorSet {
252283 snap , err := sb .snapshot (sb .chain , number , hash , nil )
253284 if err != nil {
@@ -257,23 +288,25 @@ func (sb *backend) getValidators(number uint64, hash common.Hash) istanbul.Valid
257288}
258289
259290func (sb * backend ) LastProposal () (istanbul.Proposal , common.Address ) {
260- if sb .chain == nil {
261- sb .logger .Error ("Failed to access blockchain" )
262- return nil , common.Address {}
263- }
264-
265- h := sb .chain .CurrentHeader ()
291+ block := sb .currentBlock ()
266292
267293 var proposer common.Address
268- if h .Number .Cmp (common .Big0 ) > 0 {
294+ if block .Number () .Cmp (common .Big0 ) > 0 {
269295 var err error
270- proposer , err = sb .Author (h )
296+ proposer , err = sb .Author (block . Header () )
271297 if err != nil {
272298 sb .logger .Error ("Failed to get block proposer" , "err" , err )
273299 return nil , common.Address {}
274300 }
275301 }
276302
277303 // Return header only block here since we don't need block body
278- return types .NewBlockWithHeader (h ), proposer
304+ return block , proposer
305+ }
306+
307+ func (sb * backend ) HasBadProposal (hash common.Hash ) bool {
308+ if sb .hasBadBlock == nil {
309+ return false
310+ }
311+ return sb .hasBadBlock (hash )
279312}
0 commit comments