@@ -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