-
Notifications
You must be signed in to change notification settings - Fork 0
/
manager.go
326 lines (272 loc) · 7.87 KB
/
manager.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
package fork
import (
"errors"
"github.com/hashicorp/go-hclog"
"github.com/plingatech/go-plgchain/consensus/ibft/hook"
"github.com/plingatech/go-plgchain/consensus/ibft/signer"
"github.com/plingatech/go-plgchain/secrets"
"github.com/plingatech/go-plgchain/state"
"github.com/plingatech/go-plgchain/types"
"github.com/plingatech/go-plgchain/validators"
"github.com/plingatech/go-plgchain/validators/store"
"github.com/plingatech/go-plgchain/validators/store/contract"
)
const (
loggerName = "fork_manager"
snapshotMetadataFilename = "metadata"
snapshotSnapshotsFilename = "snapshots"
)
var (
ErrForkNotFound = errors.New("fork not found")
ErrSignerNotFound = errors.New("signer not found")
ErrValidatorStoreNotFound = errors.New("validator set not found")
ErrKeyManagerNotFound = errors.New("key manager not found")
)
// ValidatorStore is an interface that ForkManager calls for Validator Store
type ValidatorStore interface {
store.ValidatorStore
// Close defines termination process
Close() error
// GetValidators is a method to return validators at the given height
GetValidators(height, epochSize, forkFrom uint64) (validators.Validators, error)
}
// HookRegister is an interface that ForkManager calls for hook registrations
type HooksRegister interface {
// RegisterHooks register hooks for the given block height
RegisterHooks(hooks *hook.Hooks, height uint64)
}
// HooksInterface is an interface of hooks to be called by IBFT
// This interface is referred from fork and ibft package
type HooksInterface interface {
ShouldWriteTransactions(uint64) bool
ModifyHeader(*types.Header, types.Address) error
VerifyHeader(*types.Header) error
VerifyBlock(*types.Block) error
ProcessHeader(*types.Header) error
PreCommitState(*types.Header, *state.Transition) error
PostInsertBlock(*types.Block) error
}
// ForkManager is the module that has Fork configuration and multiple version of submodules
// and returns the proper submodule at specified height
type ForkManager struct {
logger hclog.Logger
blockchain store.HeaderGetter
executor contract.Executor
secretsManager secrets.SecretsManager
// configuration
forks IBFTForks
filePath string
epochSize uint64
// submodule lookup
keyManagers map[validators.ValidatorType]signer.KeyManager
validatorStores map[store.SourceType]ValidatorStore
hooksRegisters map[IBFTType]HooksRegister
}
// NewForkManager is a constructor of ForkManager
func NewForkManager(
logger hclog.Logger,
blockchain store.HeaderGetter,
executor contract.Executor,
secretManager secrets.SecretsManager,
filePath string,
epochSize uint64,
ibftConfig map[string]interface{},
) (*ForkManager, error) {
forks, err := GetIBFTForks(ibftConfig)
if err != nil {
return nil, err
}
fm := &ForkManager{
logger: logger.Named(loggerName),
blockchain: blockchain,
executor: executor,
secretsManager: secretManager,
filePath: filePath,
epochSize: epochSize,
forks: forks,
keyManagers: make(map[validators.ValidatorType]signer.KeyManager),
validatorStores: make(map[store.SourceType]ValidatorStore),
hooksRegisters: make(map[IBFTType]HooksRegister),
}
// Need initialization of signers in the constructor
// because hash calculation is called from blockchain initialization
if err := fm.initializeKeyManagers(); err != nil {
return nil, err
}
return fm, nil
}
// Initialize initializes ForkManager on initialization phase
func (m *ForkManager) Initialize() error {
if err := m.initializeValidatorStores(); err != nil {
return err
}
m.initializeHooksRegisters()
return nil
}
// Close calls termination process of submodules
func (m *ForkManager) Close() error {
for _, store := range m.validatorStores {
if err := store.Close(); err != nil {
return err
}
}
return nil
}
// GetSigner returns a proper signer at specified height
func (m *ForkManager) GetSigner(height uint64) (signer.Signer, error) {
keyManager, err := m.getKeyManager(height)
if err != nil {
return nil, err
}
var parentKeyManager signer.KeyManager
if height > 1 {
if parentKeyManager, err = m.getKeyManager(height - 1); err != nil {
return nil, err
}
}
return signer.NewSigner(
keyManager,
parentKeyManager,
), nil
}
// GetValidatorStore returns a proper validator set at specified height
func (m *ForkManager) GetValidatorStore(height uint64) (ValidatorStore, error) {
fork := m.forks.getFork(height)
if fork == nil {
return nil, ErrForkNotFound
}
set := m.getValidatorStoreByIBFTFork(fork)
if set == nil {
return nil, ErrValidatorStoreNotFound
}
return set, nil
}
// GetValidators returns validators at specified height
func (m *ForkManager) GetValidators(height uint64) (validators.Validators, error) {
fork := m.forks.getFork(height)
if fork == nil {
return nil, ErrForkNotFound
}
set := m.getValidatorStoreByIBFTFork(fork)
if set == nil {
return nil, ErrValidatorStoreNotFound
}
return set.GetValidators(
height,
m.epochSize,
fork.From.Value,
)
}
// GetHooks returns a hooks at specified height
func (m *ForkManager) GetHooks(height uint64) HooksInterface {
hooks := &hook.Hooks{}
for _, r := range m.hooksRegisters {
r.RegisterHooks(hooks, height)
}
return hooks
}
func (m *ForkManager) getValidatorStoreByIBFTFork(fork *IBFTFork) ValidatorStore {
set, ok := m.validatorStores[ibftTypesToSourceType[fork.Type]]
if !ok {
return nil
}
return set
}
func (m *ForkManager) getKeyManager(height uint64) (signer.KeyManager, error) {
fork := m.forks.getFork(height)
if fork == nil {
return nil, ErrForkNotFound
}
keyManager, ok := m.keyManagers[fork.ValidatorType]
if !ok {
return nil, ErrKeyManagerNotFound
}
return keyManager, nil
}
// initializeKeyManagers initialize all key managers based on Fork configuration
func (m *ForkManager) initializeKeyManagers() error {
for _, fork := range m.forks {
if err := m.initializeKeyManager(fork.ValidatorType); err != nil {
return err
}
}
return nil
}
// initializeKeyManager initializes the sp
func (m *ForkManager) initializeKeyManager(valType validators.ValidatorType) error {
if _, ok := m.keyManagers[valType]; ok {
return nil
}
keyManager, err := signer.NewKeyManagerFromType(m.secretsManager, valType)
if err != nil {
return err
}
m.keyManagers[valType] = keyManager
return nil
}
// initializeValidatorStores initializes all validator sets based on Fork configuration
func (m *ForkManager) initializeValidatorStores() error {
for _, fork := range m.forks {
sourceType := ibftTypesToSourceType[fork.Type]
if err := m.initializeValidatorStore(sourceType); err != nil {
return err
}
}
return nil
}
// initializeValidatorStore initializes the specified validator set
func (m *ForkManager) initializeValidatorStore(setType store.SourceType) error {
if _, ok := m.validatorStores[setType]; ok {
return nil
}
var (
valStore ValidatorStore
err error
)
switch setType {
case store.Snapshot:
valStore, err = NewSnapshotValidatorStoreWrapper(
m.logger,
m.blockchain,
m.GetSigner,
m.filePath,
m.epochSize,
)
case store.Contract:
valStore, err = NewContractValidatorStoreWrapper(
m.logger,
m.blockchain,
m.executor,
m.GetSigner,
)
}
if err != nil {
return err
}
m.validatorStores[setType] = valStore
return nil
}
// initializeHooksRegisters initialize all HookRegisters to be used
func (m *ForkManager) initializeHooksRegisters() {
for _, fork := range m.forks {
m.initializeHooksRegister(fork.Type)
}
}
// initializeHooksRegister initialize HookRegister by IBFTType
func (m *ForkManager) initializeHooksRegister(ibftType IBFTType) {
if _, ok := m.hooksRegisters[ibftType]; ok {
return
}
switch ibftType {
case PoA:
m.hooksRegisters[PoA] = NewPoAHookRegisterer(
m.getValidatorStoreByIBFTFork,
m.forks,
)
case PoS:
m.hooksRegisters[PoS] = NewPoSHookRegister(
m.forks,
m.epochSize,
)
}
}