-
Notifications
You must be signed in to change notification settings - Fork 0
/
validate.go
169 lines (149 loc) · 4.35 KB
/
validate.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
// Copyright (C) 2023, Ava Labs, Inc. All rights reserved.
// See the file LICENSE for licensing terms.
package upgradecmd
import (
"encoding/json"
"errors"
"fmt"
"math"
"math/big"
"reflect"
"time"
"github.com/lasthyphen/subnet-evm/params"
)
var (
errInvalidPrecompiles = errors.New("invalid precompiles")
errNoBlockTimestamp = errors.New("no blockTimestamp value set")
errBlockTimestampInvalid = errors.New("blockTimestamp is invalid")
errBlockTimestampInthePast = errors.New("blockTimestamp is in the past")
errNoPrecompiles = errors.New("no precompiles present")
errEmptyPrecompile = errors.New("the precompile has no content")
errNoUpcomingUpgrades = errors.New("no valid upcoming activation timestamp found")
errNewUpgradesNotContainsLock = errors.New("the new upgrade file does not contain the content of the lock file")
)
func validateUpgradeBytes(file []byte, lockFile []byte) ([]params.PrecompileUpgrade, error) {
upgrades, err := getAllUpgrades(file)
if err != nil {
return nil, err
}
if len(lockFile) > 0 {
lockUpgrades, err := getAllUpgrades(lockFile)
if err != nil {
return nil, err
}
match := 0
for _, lu := range lockUpgrades {
for _, u := range upgrades {
if reflect.DeepEqual(u, lu) {
match++
break
}
}
}
if match != len(lockUpgrades) {
return nil, errNewUpgradesNotContainsLock
}
}
allTimestamps, err := getAllTimestamps(upgrades)
if err != nil {
return nil, err
}
for _, ts := range allTimestamps {
if time.Unix(ts, 0).Before(time.Now()) {
return nil, errBlockTimestampInthePast
}
}
return upgrades, nil
}
func getAllTimestamps(upgrades []params.PrecompileUpgrade) ([]int64, error) {
var allTimestamps []int64
if len(upgrades) == 0 {
return nil, errNoBlockTimestamp
}
for _, upgrade := range upgrades {
if upgrade.ContractDeployerAllowListConfig != nil {
ts, err := validateTimestamp(upgrade.ContractDeployerAllowListConfig.BlockTimestamp)
if err != nil {
return nil, err
}
allTimestamps = append(allTimestamps, ts)
}
if upgrade.FeeManagerConfig != nil {
ts, err := validateTimestamp(upgrade.FeeManagerConfig.BlockTimestamp)
if err != nil {
return nil, err
}
allTimestamps = append(allTimestamps, ts)
}
if upgrade.ContractNativeMinterConfig != nil {
ts, err := validateTimestamp(upgrade.ContractNativeMinterConfig.BlockTimestamp)
if err != nil {
return nil, err
}
allTimestamps = append(allTimestamps, ts)
}
if upgrade.TxAllowListConfig != nil {
ts, err := validateTimestamp(upgrade.TxAllowListConfig.BlockTimestamp)
if err != nil {
return nil, err
}
allTimestamps = append(allTimestamps, ts)
}
}
if len(allTimestamps) == 0 {
return nil, errNoBlockTimestamp
}
return allTimestamps, nil
}
func validateTimestamp(ts *big.Int) (int64, error) {
if ts == nil {
return 0, errNoBlockTimestamp
}
if !ts.IsInt64() {
return 0, errBlockTimestampInvalid
}
val := ts.Int64()
if val == int64(0) {
return 0, errBlockTimestampInvalid
}
return val, nil
}
func getEarliestTimestamp(upgrades []params.PrecompileUpgrade) (int64, error) {
allTimestamps, err := getAllTimestamps(upgrades)
if err != nil {
return 0, err
}
earliest := int64(math.MaxInt64)
for _, ts := range allTimestamps {
// we may also not necessarily need to check
// if after now, but to know if something is upcoming,
// seems appropriate
if ts < earliest && time.Unix(ts, 0).After(time.Now()) {
earliest = ts
}
}
// this should not happen as we have timestamp validation
// but might be required if called in a different context
if earliest == math.MaxInt64 {
return earliest, errNoUpcomingUpgrades
}
return earliest, nil
}
func getAllUpgrades(file []byte) ([]params.PrecompileUpgrade, error) {
var precompiles params.UpgradeConfig
if err := json.Unmarshal(file, &precompiles); err != nil {
return nil, fmt.Errorf("failed parsing JSON - %s: %w", err.Error(), errInvalidPrecompiles)
}
if len(precompiles.PrecompileUpgrades) == 0 {
return nil, errNoPrecompiles
}
for _, upgrade := range precompiles.PrecompileUpgrades {
if upgrade.ContractDeployerAllowListConfig == nil &&
upgrade.ContractNativeMinterConfig == nil &&
upgrade.FeeManagerConfig == nil &&
upgrade.TxAllowListConfig == nil {
return nil, errEmptyPrecompile
}
}
return precompiles.PrecompileUpgrades, nil
}