-
Notifications
You must be signed in to change notification settings - Fork 319
/
candidate_statereader.go
155 lines (129 loc) · 3.62 KB
/
candidate_statereader.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
// Copyright (c) 2020 IoTeX Foundation
// This is an alpha (internal) release and is not suitable for production. This source code is provided 'as is' and no
// warranties are given as to title or non-infringement, merchantability or fitness for purpose and, to the extent
// permitted by law, all liability for your use of the code is disclaimed. This source code is governed by Apache
// License 2.0 that can be found in the LICENSE file.
package staking
import (
"math/big"
"github.com/pkg/errors"
"github.com/iotexproject/iotex-address/address"
"github.com/iotexproject/iotex-core/action/protocol"
"github.com/iotexproject/iotex-core/state"
)
type (
// CandidateStateReader contains candidate center and bucket pool
CandidateStateReader interface {
Height() uint64
SR() protocol.StateReader
BaseView() *ViewData
GetCandidateByName(string) *Candidate
GetCandidateByOwner(address.Address) *Candidate
AllCandidates() CandidateList
TotalStakedAmount() *big.Int
ActiveBucketsCount() uint64
}
candSR struct {
protocol.StateReader
height uint64
view *ViewData
}
// ViewData is the data that need to be stored in protocol's view
ViewData struct {
candCenter *CandidateCenter
bucketPool *BucketPool
}
)
func (c *candSR) Height() uint64 {
return c.height
}
func (c *candSR) SR() protocol.StateReader {
return c.StateReader
}
func (c *candSR) BaseView() *ViewData {
return c.view
}
func (c *candSR) GetCandidateByName(name string) *Candidate {
return c.view.candCenter.GetByName(name)
}
func (c *candSR) GetCandidateByOwner(owner address.Address) *Candidate {
return c.view.candCenter.GetByOwner(owner)
}
func (c *candSR) AllCandidates() CandidateList {
return c.view.candCenter.All()
}
func (c *candSR) TotalStakedAmount() *big.Int {
return c.view.bucketPool.Total()
}
func (c *candSR) ActiveBucketsCount() uint64 {
return c.view.bucketPool.Count()
}
// GetStakingStateReader returns a candidate state reader that reflects the base view
func GetStakingStateReader(sr protocol.StateReader) (CandidateStateReader, error) {
c, err := ConstructBaseView(sr)
if err != nil {
if errors.Cause(err) == protocol.ErrNoName {
// the view does not exist yet, create it
view, height, err := CreateBaseView(sr, true)
if err != nil {
return nil, err
}
return &candSR{
StateReader: sr,
height: height,
view: view,
}, nil
}
return nil, err
}
return c, nil
}
// ConstructBaseView returns a candidate state reader that reflects the base view
// it will be used read-only
func ConstructBaseView(sr protocol.StateReader) (CandidateStateReader, error) {
if sr == nil {
return nil, ErrMissingField
}
height, err := sr.Height()
if err != nil {
return nil, err
}
v, err := sr.ReadView(protocolID)
if err != nil {
return nil, err
}
view, ok := v.(*ViewData)
if !ok {
return nil, errors.Wrap(ErrTypeAssertion, "expecting *ViewData")
}
return &candSR{
StateReader: sr,
height: height,
view: &ViewData{
candCenter: view.candCenter,
bucketPool: view.bucketPool,
},
}, nil
}
// CreateBaseView creates the base view from state reader
func CreateBaseView(sr protocol.StateReader, enableSMStorage bool) (*ViewData, uint64, error) {
if sr == nil {
return nil, 0, ErrMissingField
}
all, height, err := getAllCandidates(sr)
if err != nil && errors.Cause(err) != state.ErrStateNotExist {
return nil, height, err
}
center, err := NewCandidateCenter(all)
if err != nil {
return nil, height, err
}
pool, err := NewBucketPool(sr, enableSMStorage)
if err != nil {
return nil, height, err
}
return &ViewData{
candCenter: center,
bucketPool: pool,
}, height, nil
}