@@ -2,306 +2,24 @@ package services
2
2
3
3
import (
4
4
"context"
5
- "encoding/hex"
6
- "encoding/json"
7
5
"fmt"
8
- "math"
9
- "os"
10
6
11
- "github.com/btcsuite/btcd/btcec/v2"
12
- "github.com/btcsuite/btcd/btcutil"
13
-
14
- "github.com/babylonchain/babylon/btcstaking"
7
+ "github.com/babylonchain/networks/parameters/parser"
15
8
)
16
9
17
- func checkPositive (value uint64 ) error {
18
- if value == 0 {
19
- return fmt .Errorf ("value must be positive" )
20
- }
21
- return nil
22
- }
23
-
24
- func parseTimeLockValue (timelock uint64 ) (uint16 , error ) {
25
- if timelock > math .MaxUint16 {
26
- return 0 , fmt .Errorf ("timelock value %d is too large. Max: %d" , timelock , math .MaxUint16 )
27
- }
28
-
29
- if err := checkPositive (timelock ); err != nil {
30
- return 0 , fmt .Errorf ("invalid timelock value: %w" , err )
31
- }
32
-
33
- return uint16 (timelock ), nil
34
- }
35
-
36
- func parseConfirmationDepthValue (confirmationDepth uint64 ) (uint16 , error ) {
37
- if confirmationDepth > math .MaxUint16 {
38
- return 0 , fmt .Errorf ("confirmation depth value %d is too large. Max: %d" , confirmationDepth , math .MaxUint16 )
39
- }
40
-
41
- if err := checkPositive (confirmationDepth ); err != nil {
42
- return 0 , fmt .Errorf ("invalid confirmation depth value: %w" , err )
43
- }
44
-
45
- return uint16 (confirmationDepth ), nil
46
- }
47
-
48
- func parseBtcValue (value uint64 ) (btcutil.Amount , error ) {
49
- if value > math .MaxInt64 {
50
- return 0 , fmt .Errorf ("value %d is too large. Max: %d" , value , math .MaxInt64 )
51
- }
52
-
53
- if err := checkPositive (value ); err != nil {
54
- return 0 , fmt .Errorf ("invalid btc value value: %w" , err )
55
- }
56
- // retrun amount in satoshis
57
- return btcutil .Amount (value ), nil
10
+ type VersionedParamsRetriever struct {
11
+ * parser.ParsedGlobalParams
58
12
}
59
13
60
- func parseUint32 (value uint64 ) (uint32 , error ) {
61
- if value > math .MaxUint32 {
62
- return 0 , fmt .Errorf ("value %d is too large. Max: %d" , value , math .MaxUint32 )
63
- }
64
-
65
- if err := checkPositive (value ); err != nil {
66
- return 0 , fmt .Errorf ("invalid value: %w" , err )
67
- }
68
-
69
- return uint32 (value ), nil
70
- }
71
-
72
- // parseCovenantPubKeyFromHex parses public key string to btc public key
73
- // the input should be 33 bytes
74
- func parseCovenantPubKeyFromHex (pkStr string ) (* btcec.PublicKey , error ) {
75
- pkBytes , err := hex .DecodeString (pkStr )
14
+ func NewVersionedParamsRetriever (path string ) (* VersionedParamsRetriever , error ) {
15
+ parsedGlobalParams , err := parser .NewParsedGlobalParamsFromFile (path )
76
16
if err != nil {
77
17
return nil , err
78
18
}
79
-
80
- pk , err := btcec .ParsePubKey (pkBytes )
81
- if err != nil {
82
- return nil , err
83
- }
84
-
85
- return pk , nil
19
+ return & VersionedParamsRetriever {parsedGlobalParams }, nil
86
20
}
87
-
88
- var _ ParamsRetriever = (* ParsedGlobalParams )(nil )
89
-
90
- type VersionedGlobalParams struct {
91
- Version uint64 `json:"version"`
92
- ActivationHeight uint64 `json:"activation_height"`
93
- StakingCap uint64 `json:"staking_cap"`
94
- Tag string `json:"tag"`
95
- CovenantPks []string `json:"covenant_pks"`
96
- CovenantQuorum uint64 `json:"covenant_quorum"`
97
- UnbondingTime uint64 `json:"unbonding_time"`
98
- UnbondingFee uint64 `json:"unbonding_fee"`
99
- MaxStakingAmount uint64 `json:"max_staking_amount"`
100
- MinStakingAmount uint64 `json:"min_staking_amount"`
101
- MaxStakingTime uint64 `json:"max_staking_time"`
102
- MinStakingTime uint64 `json:"min_staking_time"`
103
- ConfirmationDepth uint64 `json:"confirmation_depth"`
104
- }
105
-
106
- type GlobalParams struct {
107
- Versions []* VersionedGlobalParams `json:"versions"`
108
- }
109
-
110
- type ParsedGlobalParams struct {
111
- Versions []* ParsedVersionedGlobalParams
112
- }
113
-
114
- type ParsedVersionedGlobalParams struct {
115
- Version uint64
116
- ActivationHeight uint64
117
- StakingCap btcutil.Amount
118
- Tag []byte
119
- CovenantPks []* btcec.PublicKey
120
- CovenantQuorum uint32
121
- UnbondingTime uint16
122
- UnbondingFee btcutil.Amount
123
- MaxStakingAmount btcutil.Amount
124
- MinStakingAmount btcutil.Amount
125
- MaxStakingTime uint16
126
- MinStakingTime uint16
127
- ConfirmationDepth uint16
128
- }
129
-
130
- func NewGlobalParams (filePath string ) (* ParsedGlobalParams , error ) {
131
- data , err := os .ReadFile (filePath )
132
- if err != nil {
133
- return nil , err
134
- }
135
-
136
- var globalParams GlobalParams
137
- err = json .Unmarshal (data , & globalParams )
138
- if err != nil {
139
- return nil , err
140
- }
141
-
142
- parsedGlobalParams , err := ParseGlobalParams (& globalParams )
143
-
144
- if err != nil {
145
- return nil , err
146
- }
147
-
148
- return parsedGlobalParams , nil
149
- }
150
-
151
- func parseVersionedGlobalParams (p * VersionedGlobalParams ) (* ParsedVersionedGlobalParams , error ) {
152
- tag , err := hex .DecodeString (p .Tag )
153
-
154
- if err != nil {
155
- return nil , fmt .Errorf ("invalid tag: %w" , err )
156
- }
157
-
158
- if len (tag ) != btcstaking .MagicBytesLen {
159
- return nil , fmt .Errorf ("invalid tag length, expected %d, got %d" , btcstaking .MagicBytesLen , len (p .Tag ))
160
- }
161
-
162
- if len (p .CovenantPks ) == 0 {
163
- return nil , fmt .Errorf ("empty covenant public keys" )
164
- }
165
- if p .CovenantQuorum > uint64 (len (p .CovenantPks )) {
166
- return nil , fmt .Errorf ("covenant quorum cannot be more than the amount of covenants" )
167
- }
168
-
169
- quroum , err := parseUint32 (p .CovenantQuorum )
170
- if err != nil {
171
- return nil , fmt .Errorf ("invalid covenant quorum: %w" , err )
172
- }
173
-
174
- var covenantKeys []* btcec.PublicKey
175
- for _ , covPk := range p .CovenantPks {
176
- pk , err := parseCovenantPubKeyFromHex (covPk )
177
- if err != nil {
178
- return nil , fmt .Errorf ("invalid covenant public key %s: %w" , covPk , err )
179
- }
180
-
181
- covenantKeys = append (covenantKeys , pk )
182
- }
183
-
184
- maxStakingAmount , err := parseBtcValue (p .MaxStakingAmount )
185
-
186
- if err != nil {
187
- return nil , fmt .Errorf ("invalid max_staking_amount: %w" , err )
188
- }
189
-
190
- minStakingAmount , err := parseBtcValue (p .MinStakingAmount )
191
-
192
- if err != nil {
193
- return nil , fmt .Errorf ("invalid min_staking_amount: %w" , err )
194
- }
195
-
196
- if maxStakingAmount <= minStakingAmount {
197
- return nil , fmt .Errorf ("max-staking-amount must be larger than min-staking-amount" )
198
- }
199
-
200
- ubTime , err := parseTimeLockValue (p .UnbondingTime )
201
- if err != nil {
202
- return nil , fmt .Errorf ("invalid unbonding_time: %w" , err )
203
- }
204
-
205
- ubFee , err := parseBtcValue (p .UnbondingFee )
206
- if err != nil {
207
- return nil , fmt .Errorf ("invalid unbonding_fee: %w" , err )
208
- }
209
-
210
- maxStakingTime , err := parseTimeLockValue (p .MaxStakingTime )
211
- if err != nil {
212
- return nil , fmt .Errorf ("invalid max_staking_time: %w" , err )
213
- }
214
-
215
- minStakingTime , err := parseTimeLockValue (p .MinStakingTime )
216
- if err != nil {
217
- return nil , fmt .Errorf ("invalid min_staking_time: %w" , err )
218
- }
219
-
220
- // NOTE: Allow config when max-staking-time is equal to min-staking-time, as then
221
- // we can configure a fixed staking time.
222
- if maxStakingTime < minStakingTime {
223
- return nil , fmt .Errorf ("max-staking-time must be larger or equalt min-staking-time" )
224
- }
225
-
226
- confirmationDepth , err := parseConfirmationDepthValue (p .ConfirmationDepth )
227
- if err != nil {
228
- return nil , fmt .Errorf ("invalid confirmation_depth: %w" , err )
229
- }
230
-
231
- stakingCap , err := parseBtcValue (p .StakingCap )
232
- if err != nil {
233
- return nil , fmt .Errorf ("invalid staking_cap: %w" , err )
234
- }
235
-
236
- return & ParsedVersionedGlobalParams {
237
- Version : p .Version ,
238
- ActivationHeight : p .ActivationHeight ,
239
- StakingCap : stakingCap ,
240
- Tag : tag ,
241
- CovenantPks : covenantKeys ,
242
- CovenantQuorum : quroum ,
243
- UnbondingTime : ubTime ,
244
- UnbondingFee : ubFee ,
245
- MaxStakingAmount : maxStakingAmount ,
246
- MinStakingAmount : minStakingAmount ,
247
- MaxStakingTime : maxStakingTime ,
248
- MinStakingTime : minStakingTime ,
249
- ConfirmationDepth : confirmationDepth ,
250
- }, nil
251
- }
252
-
253
- func ParseGlobalParams (p * GlobalParams ) (* ParsedGlobalParams , error ) {
254
- if len (p .Versions ) == 0 {
255
- return nil , fmt .Errorf ("global params must have at least one version" )
256
- }
257
- var parsedVersions []* ParsedVersionedGlobalParams
258
-
259
- for _ , v := range p .Versions {
260
- vCopy := v
261
- cv , err := parseVersionedGlobalParams (vCopy )
262
-
263
- if err != nil {
264
- return nil , fmt .Errorf ("invalid params with version %d: %w" , vCopy .Version , err )
265
- }
266
-
267
- // Check latest version
268
- if len (parsedVersions ) > 0 {
269
- pv := parsedVersions [len (parsedVersions )- 1 ]
270
-
271
- if cv .Version != pv .Version + 1 {
272
- return nil , fmt .Errorf ("invalid params with version %d. versions should be monotonically increasing by 1" , cv .Version )
273
- }
274
- if cv .StakingCap < pv .StakingCap {
275
- return nil , fmt .Errorf ("invalid params with version %d. staking cap cannot be decreased in later versions" , cv .Version )
276
- }
277
- if cv .ActivationHeight < pv .ActivationHeight {
278
- return nil , fmt .Errorf ("invalid params with version %d. activation height cannot be overlapping between earlier and later versions" , cv .Version )
279
- }
280
- }
281
-
282
- parsedVersions = append (parsedVersions , cv )
283
- }
284
-
285
- return & ParsedGlobalParams {
286
- Versions : parsedVersions ,
287
- }, nil
288
- }
289
-
290
- func (g * ParsedGlobalParams ) getVersionedGlobalParamsByHeight (btcHeight uint64 ) * ParsedVersionedGlobalParams {
291
- // Iterate the list in reverse (i.e. decreasing ActivationHeight)
292
- // and identify the first element that has an activation height below
293
- // the specified BTC height.
294
- for i := len (g .Versions ) - 1 ; i >= 0 ; i -- {
295
- paramsVersion := g .Versions [i ]
296
- if paramsVersion .ActivationHeight <= btcHeight {
297
- return paramsVersion
298
- }
299
- }
300
- return nil
301
- }
302
-
303
- func (g * ParsedGlobalParams ) ParamsByHeight (_ context.Context , height uint64 ) (* SystemParams , error ) {
304
- versionedParams := g .getVersionedGlobalParamsByHeight (height )
21
+ func (g * VersionedParamsRetriever ) ParamsByHeight (_ context.Context , height uint64 ) (* SystemParams , error ) {
22
+ versionedParams := g .ParsedGlobalParams .GetVersionedGlobalParamsByHeight (height )
305
23
if versionedParams == nil {
306
24
return nil , fmt .Errorf ("no global params for height %d" , height )
307
25
}
0 commit comments