-
Notifications
You must be signed in to change notification settings - Fork 38
/
state.go
185 lines (150 loc) · 5.08 KB
/
state.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
package innerring
import (
"fmt"
"sort"
"github.com/nspcc-dev/neo-go/pkg/util"
"github.com/nspcc-dev/neofs-node/pkg/innerring/processors/governance"
auditClient "github.com/nspcc-dev/neofs-node/pkg/morph/client/audit"
"github.com/nspcc-dev/neofs-node/pkg/services/audit"
control "github.com/nspcc-dev/neofs-node/pkg/services/control/ir"
"github.com/nspcc-dev/neofs-node/pkg/util/state"
"github.com/spf13/viper"
"go.uber.org/zap"
)
const voteMethod = "vote"
var (
persistateMainChainLastBlockKey = []byte("main_chain_last_processed_block")
persistateSideChainLastBlockKey = []byte("side_chain_last_processed_block")
)
// EpochCounter is a getter for a global epoch counter.
func (s *Server) EpochCounter() uint64 {
return s.epochCounter.Load()
}
// SetEpochCounter is a setter for contract processors to update global
// epoch counter.
func (s *Server) SetEpochCounter(val uint64) {
s.epochCounter.Store(val)
if s.metrics != nil {
s.metrics.SetEpoch(val)
}
}
// EpochDuration is a getter for a global epoch duration.
func (s *Server) EpochDuration() uint64 {
return s.epochDuration.Load()
}
// SetEpochDuration is a setter for the Netmap processor to update global
// epoch duration.
func (s *Server) SetEpochDuration(val uint64) {
s.epochDuration.Store(val)
}
// IsActive is a getter for a global active flag state.
func (s *Server) IsActive() bool {
return s.InnerRingIndex() >= 0
}
// IsAlphabet is a getter for a global alphabet flag state.
func (s *Server) IsAlphabet() bool {
return s.AlphabetIndex() >= 0
}
// InnerRingIndex is a getter for a global index of node in inner ring list. Negative
// index means that node is not in the inner ring list.
func (s *Server) InnerRingIndex() int {
index, err := s.statusIndex.InnerRingIndex()
if err != nil {
s.log.Error("can't get inner ring index", zap.String("error", err.Error()))
return -1
}
return int(index)
}
// InnerRingSize is a getter for a global size of inner ring list. This value
// paired with inner ring index.
func (s *Server) InnerRingSize() int {
size, err := s.statusIndex.InnerRingSize()
if err != nil {
s.log.Error("can't get inner ring size", zap.String("error", err.Error()))
return 0
}
return int(size)
}
// AlphabetIndex is a getter for a global index of node in alphabet list.
// Negative index means that node is not in the alphabet list.
func (s *Server) AlphabetIndex() int {
index, err := s.statusIndex.AlphabetIndex()
if err != nil {
s.log.Error("can't get alphabet index", zap.String("error", err.Error()))
return -1
}
return int(index)
}
func (s *Server) voteForSidechainValidator(prm governance.VoteValidatorPrm) error {
validators := prm.Validators
index := s.InnerRingIndex()
if s.contracts.alphabet.indexOutOfRange(index) {
s.log.Info("ignore validator vote: node not in alphabet range")
return nil
}
if len(validators) == 0 {
s.log.Info("ignore validator vote: empty validators list")
return nil
}
epoch := s.EpochCounter()
var (
nonce uint32 = 1
vub uint32
vubP *uint32
err error
)
if prm.Hash != nil {
nonce, vub, err = s.morphClient.CalculateNonceAndVUB(*prm.Hash)
if err != nil {
return fmt.Errorf("could not calculate nonce and `validUntilBlock` values: %w", err)
}
vubP = &vub
}
s.contracts.alphabet.iterate(func(letter GlagoliticLetter, contract util.Uint160) {
err := s.morphClient.NotaryInvoke(contract, s.feeConfig.SideChainFee(), nonce, vubP, voteMethod, epoch, validators)
if err != nil {
s.log.Warn("can't invoke vote method in alphabet contract",
zap.Int8("alphabet_index", int8(letter)),
zap.Uint64("epoch", epoch),
zap.String("error", err.Error()))
}
})
return nil
}
// VoteForSidechainValidator calls vote method on alphabet contracts with
// the provided list of keys.
func (s *Server) VoteForSidechainValidator(prm governance.VoteValidatorPrm) error {
sort.Sort(prm.Validators)
return s.voteForSidechainValidator(prm)
}
// WriteReport composes the audit result structure from the audit report
// and sends it to Audit contract.
func (s *Server) WriteReport(r *audit.Report) error {
res := r.Result()
res.SetAuditorKey(s.pubKey)
prm := auditClient.PutPrm{}
prm.SetResult(res)
return s.auditClient.PutAuditResult(prm)
}
// ResetEpochTimer resets the block timer that produces events to update epoch
// counter in the netmap contract. It is used to synchronize this even production
// based on the block with a notification of the last epoch.
func (s *Server) ResetEpochTimer(h uint32) error {
s.epochTimer.Tick(h)
return s.epochTimer.Reset()
}
func (s *Server) setHealthStatus(hs control.HealthStatus) {
s.healthStatus.Store(hs)
}
// HealthStatus returns the current health status of the IR application.
func (s *Server) HealthStatus() control.HealthStatus {
return s.healthStatus.Load().(control.HealthStatus)
}
func initPersistentStateStorage(cfg *viper.Viper) (*state.PersistentStorage, error) {
persistPath := cfg.GetString("node.persistent_state.path")
persistStorage, err := state.NewPersistentStorage(persistPath)
if err != nil {
return nil, fmt.Errorf("persistent state init error: %w", err)
}
return persistStorage, nil
}