@@ -18,61 +18,65 @@ package backend
1818
1919import  (
2020	"crypto/ecdsa" 
21+ 	"math/big" 
2122	"sync" 
23+ 	"time" 
2224
2325	"github.com/ethereum/go-ethereum/common" 
2426	"github.com/ethereum/go-ethereum/consensus" 
2527	"github.com/ethereum/go-ethereum/consensus/istanbul" 
2628	istanbulCore "github.com/ethereum/go-ethereum/consensus/istanbul/core" 
2729	"github.com/ethereum/go-ethereum/consensus/istanbul/validator" 
28- 	"github.com/ethereum/go-ethereum/core" 
2930	"github.com/ethereum/go-ethereum/core/types" 
3031	"github.com/ethereum/go-ethereum/crypto" 
3132	"github.com/ethereum/go-ethereum/ethdb" 
3233	"github.com/ethereum/go-ethereum/event" 
3334	"github.com/ethereum/go-ethereum/log" 
35+ 	"github.com/ethereum/go-ethereum/miner" 
3436	lru "github.com/hashicorp/golang-lru" 
3537)
3638
3739// New creates an Ethereum backend for Istanbul core engine. 
3840func  New (config  * istanbul.Config , eventMux  * event.TypeMux , privateKey  * ecdsa.PrivateKey , db  ethdb.Database ) consensus.Istanbul  {
3941	// Allocate the snapshot caches and create the engine 
4042	recents , _  :=  lru .NewARC (inmemorySnapshots )
41- 	backend  :=  & simpleBackend {
43+ 	backend  :=  & backend {
4244		config :           config ,
4345		eventMux :         eventMux ,
4446		istanbulEventMux : new (event.TypeMux ),
4547		privateKey :       privateKey ,
4648		address :          crypto .PubkeyToAddress (privateKey .PublicKey ),
47- 		logger :           log .New ("backend" ,  "simple" ),
49+ 		logger :           log .New (),
4850		db :               db ,
4951		commitCh :         make (chan  * types.Block , 1 ),
5052		recents :          recents ,
5153		candidates :       make (map [common.Address ]bool ),
54+ 		coreStarted :      false ,
5255	}
56+ 	backend .core  =  istanbulCore .New (backend , backend .config )
5357	return  backend 
5458}
5559
5660// ---------------------------------------------------------------------------- 
5761
58- type  simpleBackend  struct  {
62+ type  backend  struct  {
5963	config            * istanbul.Config 
6064	eventMux          * event.TypeMux 
6165	istanbulEventMux  * event.TypeMux 
6266	privateKey        * ecdsa.PrivateKey 
6367	address           common.Address 
6468	core              istanbulCore.Engine 
6569	logger            log.Logger 
66- 	quitSync          chan  struct {}
6770	db                ethdb.Database 
68- 	timeout           uint64 
6971	chain             consensus.ChainReader 
70- 	inserter          func (block   * types.Block )  error 
72+ 	inserter          func (types.Blocks ) ( int ,  error ) 
7173
7274	// the channels for istanbul engine notifications 
7375	commitCh           chan  * types.Block 
7476	proposedBlockHash  common.Hash 
7577	sealMu             sync.Mutex 
78+ 	coreStarted        bool 
79+ 	coreMu             sync.Mutex 
7680
7781	// Current list of candidates we are pushing 
7882	candidates  map [common.Address ]bool 
@@ -83,29 +87,18 @@ type simpleBackend struct {
8387}
8488
8589// Address implements istanbul.Backend.Address 
86- func  (sb  * simpleBackend ) Address () common.Address  {
90+ func  (sb  * backend ) Address () common.Address  {
8791	return  sb .address 
8892}
8993
9094// Validators implements istanbul.Backend.Validators 
91- func  (sb  * simpleBackend ) Validators (proposal  istanbul.Proposal ) istanbul.ValidatorSet  {
92- 	snap , err  :=  sb .snapshot (sb .chain , proposal .Number ().Uint64 (), proposal .Hash (), nil )
93- 	if  err  !=  nil  {
94- 		return  validator .NewSet (nil , sb .config .ProposerPolicy )
95- 	}
96- 	return  snap .ValSet 
97- }
98- 
99- func  (sb  * simpleBackend ) Send (payload  []byte , target  common.Address ) error  {
100- 	go  sb .eventMux .Post (istanbul.ConsensusDataEvent {
101- 		Target : target ,
102- 		Data :   payload ,
103- 	})
104- 	return  nil 
95+ func  (sb  * backend ) Validators (proposal  istanbul.Proposal ) istanbul.ValidatorSet  {
96+ 	return  sb .getValidators (proposal .Number ().Uint64 (), proposal .Hash ())
10597}
10698
10799// Broadcast implements istanbul.Backend.Send 
108- func  (sb  * simpleBackend ) Broadcast (valSet  istanbul.ValidatorSet , payload  []byte ) error  {
100+ func  (sb  * backend ) Broadcast (valSet  istanbul.ValidatorSet , payload  []byte ) error  {
101+ 	targets  :=  make (map [common.Address ]bool )
109102	for  _ , val  :=  range  valSet .List () {
110103		if  val .Address () ==  sb .Address () {
111104			// send to self 
@@ -116,14 +109,21 @@ func (sb *simpleBackend) Broadcast(valSet istanbul.ValidatorSet, payload []byte)
116109
117110		} else  {
118111			// send to other peers 
119- 			sb . Send ( payload ,  val .Address ()) 
112+ 			targets [ val .Address ()]  =   true 
120113		}
121114	}
115+ 
116+ 	if  len (targets ) >  0  {
117+ 		go  sb .eventMux .Post (istanbul.ConsensusDataEvent {
118+ 			Targets : targets ,
119+ 			Data :    payload ,
120+ 		})
121+ 	}
122122	return  nil 
123123}
124124
125125// Commit implements istanbul.Backend.Commit 
126- func  (sb  * simpleBackend ) Commit (proposal  istanbul.Proposal , seals  []byte ) error  {
126+ func  (sb  * backend ) Commit (proposal  istanbul.Proposal , seals  [] []byte ) error  {
127127	// Check if the proposal is a valid block 
128128	block  :=  & types.Block {}
129129	block , ok  :=  proposal .(* types.Block )
@@ -154,49 +154,58 @@ func (sb *simpleBackend) Commit(proposal istanbul.Proposal, seals []byte) error
154154		// TODO: how do we check the block is inserted correctly? 
155155		return  nil 
156156	}
157- 
158- 	return  sb .inserter (block )
157+ 	// if I'm not a proposer, insert the block directly and broadcast NewCommittedEvent 
158+ 	if  _ , err  :=  sb .inserter (types.Blocks {block }); err  !=  nil  {
159+ 		return  err 
160+ 	}
161+ 	msg  :=  istanbul.NewCommittedEvent {
162+ 		Block : block ,
163+ 	}
164+ 	go  sb .eventMux .Post (msg )
165+ 	return  nil 
159166}
160167
161- // NextRound will broadcast ChainHeadEvent  to trigger next seal() 
162- func  (sb  * simpleBackend ) NextRound () error  {
168+ // NextRound will broadcast NewBlockEvent  to trigger next seal() 
169+ func  (sb  * backend ) NextRound () error  {
163170	header  :=  sb .chain .CurrentHeader ()
164171	sb .logger .Debug ("NextRound" , "address" , sb .Address (), "current_hash" , header .Hash (), "current_number" , header .Number )
165- 	go  sb .eventMux .Post (core. ChainHeadEvent {})
172+ 	go  sb .eventMux .Post (miner. NewBlockEvent {})
166173	return  nil 
167174}
168175
169176// EventMux implements istanbul.Backend.EventMux 
170- func  (sb  * simpleBackend ) EventMux () * event.TypeMux  {
177+ func  (sb  * backend ) EventMux () * event.TypeMux  {
171178	return  sb .istanbulEventMux 
172179}
173180
174181// Verify implements istanbul.Backend.Verify 
175- func  (sb  * simpleBackend ) Verify (proposal  istanbul.Proposal ) error  {
182+ func  (sb  * backend ) Verify (proposal  istanbul.Proposal ) (time. Duration ,  error )  {
176183	// Check if the proposal is a valid block 
177184	block  :=  & types.Block {}
178185	block , ok  :=  proposal .(* types.Block )
179186	if  ! ok  {
180187		sb .logger .Error ("Invalid proposal, %v" , proposal )
181- 		return  errInvalidProposal 
188+ 		return  0 ,  errInvalidProposal 
182189	}
183190	// verify the header of proposed block 
184191	err  :=  sb .VerifyHeader (sb .chain , block .Header (), false )
185- 	// Ignore errEmptyCommittedSeals error because we don't have the committed seals yet 
186- 	if  err  !=  nil  &&  err  !=  errEmptyCommittedSeals  {
187- 		return  err 
192+ 	// ignore errEmptyCommittedSeals error because we don't have the committed seals yet 
193+ 	if  err  ==  nil  ||  err  ==  errEmptyCommittedSeals  {
194+ 		return  0 , nil 
195+ 	} else  if  err  ==  consensus .ErrFutureBlock  {
196+ 		return  time .Unix (block .Header ().Time .Int64 (), 0 ).Sub (now ()), consensus .ErrFutureBlock 
188197	}
189- 	return  nil 
198+ 	return  0 ,  err 
190199}
191200
192201// Sign implements istanbul.Backend.Sign 
193- func  (sb  * simpleBackend ) Sign (data  []byte ) ([]byte , error ) {
202+ func  (sb  * backend ) Sign (data  []byte ) ([]byte , error ) {
194203	hashData  :=  crypto .Keccak256 ([]byte (data ))
195204	return  crypto .Sign (hashData , sb .privateKey )
196205}
197206
198207// CheckSignature implements istanbul.Backend.CheckSignature 
199- func  (sb  * simpleBackend ) CheckSignature (data  []byte , address  common.Address , sig  []byte ) error  {
208+ func  (sb  * backend ) CheckSignature (data  []byte , address  common.Address , sig  []byte ) error  {
200209	signer , err  :=  istanbul .GetSignatureAddress (data , sig )
201210	if  err  !=  nil  {
202211		log .Error ("Failed to get signer address" , "err" , err )
@@ -208,3 +217,33 @@ func (sb *simpleBackend) CheckSignature(data []byte, address common.Address, sig
208217	}
209218	return  nil 
210219}
220+ 
221+ // HasBlock implements istanbul.Backend.HashBlock 
222+ func  (sb  * backend ) HasBlock (hash  common.Hash , number  * big.Int ) bool  {
223+ 	return  sb .chain .GetHeader (hash , number .Uint64 ()) !=  nil 
224+ }
225+ 
226+ // GetProposer implements istanbul.Backend.GetProposer 
227+ func  (sb  * backend ) GetProposer (number  uint64 ) common.Address  {
228+ 	if  h  :=  sb .chain .GetHeaderByNumber (number ); h  !=  nil  {
229+ 		a , _  :=  sb .Author (h )
230+ 		return  a 
231+ 	}
232+ 	return  common.Address {}
233+ }
234+ 
235+ // ParentValidators implements istanbul.Backend.GetParentValidators 
236+ func  (sb  * backend ) ParentValidators (proposal  istanbul.Proposal ) istanbul.ValidatorSet  {
237+ 	if  block , ok  :=  proposal .(* types.Block ); ok  {
238+ 		return  sb .getValidators (block .Number ().Uint64 ()- 1 , block .ParentHash ())
239+ 	}
240+ 	return  validator .NewSet (nil , sb .config .ProposerPolicy )
241+ }
242+ 
243+ func  (sb  * backend ) getValidators (number  uint64 , hash  common.Hash ) istanbul.ValidatorSet  {
244+ 	snap , err  :=  sb .snapshot (sb .chain , number , hash , nil )
245+ 	if  err  !=  nil  {
246+ 		return  validator .NewSet (nil , sb .config .ProposerPolicy )
247+ 	}
248+ 	return  snap .ValSet 
249+ }
0 commit comments