@@ -18,61 +18,65 @@ package backend
18
18
19
19
import (
20
20
"crypto/ecdsa"
21
+ "math/big"
21
22
"sync"
23
+ "time"
22
24
23
25
"github.com/ethereum/go-ethereum/common"
24
26
"github.com/ethereum/go-ethereum/consensus"
25
27
"github.com/ethereum/go-ethereum/consensus/istanbul"
26
28
istanbulCore "github.com/ethereum/go-ethereum/consensus/istanbul/core"
27
29
"github.com/ethereum/go-ethereum/consensus/istanbul/validator"
28
- "github.com/ethereum/go-ethereum/core"
29
30
"github.com/ethereum/go-ethereum/core/types"
30
31
"github.com/ethereum/go-ethereum/crypto"
31
32
"github.com/ethereum/go-ethereum/ethdb"
32
33
"github.com/ethereum/go-ethereum/event"
33
34
"github.com/ethereum/go-ethereum/log"
35
+ "github.com/ethereum/go-ethereum/miner"
34
36
lru "github.com/hashicorp/golang-lru"
35
37
)
36
38
37
39
// New creates an Ethereum backend for Istanbul core engine.
38
40
func New (config * istanbul.Config , eventMux * event.TypeMux , privateKey * ecdsa.PrivateKey , db ethdb.Database ) consensus.Istanbul {
39
41
// Allocate the snapshot caches and create the engine
40
42
recents , _ := lru .NewARC (inmemorySnapshots )
41
- backend := & simpleBackend {
43
+ backend := & backend {
42
44
config : config ,
43
45
eventMux : eventMux ,
44
46
istanbulEventMux : new (event.TypeMux ),
45
47
privateKey : privateKey ,
46
48
address : crypto .PubkeyToAddress (privateKey .PublicKey ),
47
- logger : log .New ("backend" , "simple" ),
49
+ logger : log .New (),
48
50
db : db ,
49
51
commitCh : make (chan * types.Block , 1 ),
50
52
recents : recents ,
51
53
candidates : make (map [common.Address ]bool ),
54
+ coreStarted : false ,
52
55
}
56
+ backend .core = istanbulCore .New (backend , backend .config )
53
57
return backend
54
58
}
55
59
56
60
// ----------------------------------------------------------------------------
57
61
58
- type simpleBackend struct {
62
+ type backend struct {
59
63
config * istanbul.Config
60
64
eventMux * event.TypeMux
61
65
istanbulEventMux * event.TypeMux
62
66
privateKey * ecdsa.PrivateKey
63
67
address common.Address
64
68
core istanbulCore.Engine
65
69
logger log.Logger
66
- quitSync chan struct {}
67
70
db ethdb.Database
68
- timeout uint64
69
71
chain consensus.ChainReader
70
- inserter func (block * types.Block ) error
72
+ inserter func (types.Blocks ) ( int , error )
71
73
72
74
// the channels for istanbul engine notifications
73
75
commitCh chan * types.Block
74
76
proposedBlockHash common.Hash
75
77
sealMu sync.Mutex
78
+ coreStarted bool
79
+ coreMu sync.Mutex
76
80
77
81
// Current list of candidates we are pushing
78
82
candidates map [common.Address ]bool
@@ -83,29 +87,18 @@ type simpleBackend struct {
83
87
}
84
88
85
89
// Address implements istanbul.Backend.Address
86
- func (sb * simpleBackend ) Address () common.Address {
90
+ func (sb * backend ) Address () common.Address {
87
91
return sb .address
88
92
}
89
93
90
94
// 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 ())
105
97
}
106
98
107
99
// 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 )
109
102
for _ , val := range valSet .List () {
110
103
if val .Address () == sb .Address () {
111
104
// send to self
@@ -116,14 +109,21 @@ func (sb *simpleBackend) Broadcast(valSet istanbul.ValidatorSet, payload []byte)
116
109
117
110
} else {
118
111
// send to other peers
119
- sb . Send ( payload , val .Address ())
112
+ targets [ val .Address ()] = true
120
113
}
121
114
}
115
+
116
+ if len (targets ) > 0 {
117
+ go sb .eventMux .Post (istanbul.ConsensusDataEvent {
118
+ Targets : targets ,
119
+ Data : payload ,
120
+ })
121
+ }
122
122
return nil
123
123
}
124
124
125
125
// 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 {
127
127
// Check if the proposal is a valid block
128
128
block := & types.Block {}
129
129
block , ok := proposal .(* types.Block )
@@ -154,49 +154,58 @@ func (sb *simpleBackend) Commit(proposal istanbul.Proposal, seals []byte) error
154
154
// TODO: how do we check the block is inserted correctly?
155
155
return nil
156
156
}
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
159
166
}
160
167
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 {
163
170
header := sb .chain .CurrentHeader ()
164
171
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 {})
166
173
return nil
167
174
}
168
175
169
176
// EventMux implements istanbul.Backend.EventMux
170
- func (sb * simpleBackend ) EventMux () * event.TypeMux {
177
+ func (sb * backend ) EventMux () * event.TypeMux {
171
178
return sb .istanbulEventMux
172
179
}
173
180
174
181
// 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 ) {
176
183
// Check if the proposal is a valid block
177
184
block := & types.Block {}
178
185
block , ok := proposal .(* types.Block )
179
186
if ! ok {
180
187
sb .logger .Error ("Invalid proposal, %v" , proposal )
181
- return errInvalidProposal
188
+ return 0 , errInvalidProposal
182
189
}
183
190
// verify the header of proposed block
184
191
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
188
197
}
189
- return nil
198
+ return 0 , err
190
199
}
191
200
192
201
// Sign implements istanbul.Backend.Sign
193
- func (sb * simpleBackend ) Sign (data []byte ) ([]byte , error ) {
202
+ func (sb * backend ) Sign (data []byte ) ([]byte , error ) {
194
203
hashData := crypto .Keccak256 ([]byte (data ))
195
204
return crypto .Sign (hashData , sb .privateKey )
196
205
}
197
206
198
207
// 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 {
200
209
signer , err := istanbul .GetSignatureAddress (data , sig )
201
210
if err != nil {
202
211
log .Error ("Failed to get signer address" , "err" , err )
@@ -208,3 +217,33 @@ func (sb *simpleBackend) CheckSignature(data []byte, address common.Address, sig
208
217
}
209
218
return nil
210
219
}
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