-
Notifications
You must be signed in to change notification settings - Fork 51
Expand file tree
/
Copy pathremovals.go
More file actions
128 lines (112 loc) · 4.24 KB
/
Copy pathremovals.go
File metadata and controls
128 lines (112 loc) · 4.24 KB
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
package contract
import (
"context"
"math/big"
"strconv"
"strings"
"github.com/ethereum/go-ethereum/accounts/abi"
"golang.org/x/xerrors"
)
// This file is hand-maintained, unlike the generated PDPVerifier bindings. It
// carries the removal-queue entrypoint and custom errors added by
// https://github.com/FilOzone/pdp/pull/297, which are not yet in the checked-in
// ABI. Delete it and use the generated bindings once PDPVerifier.abi is
// regenerated against a release containing processPieceDeletions.
const removalQueueABIJSON = `[
{"type":"function","name":"processPieceDeletions","inputs":[{"name":"setId","type":"uint256","internalType":"uint256"},{"name":"removalCount","type":"uint256","internalType":"uint256"}],"outputs":[],"stateMutability":"nonpayable"},
{"type":"error","name":"OnlyStorageProvider","inputs":[]},
{"type":"error","name":"InvalidPieceDeletionBatch","inputs":[]},
{"type":"error","name":"EmptyRemovalBatch","inputs":[]},
{"type":"error","name":"PendingPieceDeletions","inputs":[{"name":"count","type":"uint256","internalType":"uint256"}]},
{"type":"error","name":"NoPiecesToProve","inputs":[]}
]`
var removalQueueABI abi.ABI
func init() {
parsed, err := abi.JSON(strings.NewReader(removalQueueABIJSON))
if err != nil {
panic("failed to parse PDPVerifier removal-queue ABI fragment: " + err.Error())
}
removalQueueABI = parsed
}
// RemovalQueueABI exposes the hand-maintained fragment so callers can resolve
// the new custom errors for revert classification.
func RemovalQueueABI() *abi.ABI {
return &removalQueueABI
}
// PackProcessPieceDeletions builds calldata draining removalCount entries from
// the tail of a data set's scheduled-removal queue.
func PackProcessPieceDeletions(setID, removalCount *big.Int) ([]byte, error) {
data, err := removalQueueABI.Pack("processPieceDeletions", setID, removalCount)
if err != nil {
return nil, xerrors.Errorf("packing processPieceDeletions: %w", err)
}
return data, nil
}
// PieceDeletionProcessingMinVersion is the lowest PDPVerifier VERSION that
// exposes processPieceDeletions. Below it, nextProvingPeriod still drains the
// removal queue itself and Curio must not attempt to drain it separately.
//
// TODO: confirm against the release that lands FilOzone/pdp#297. The currently
// deployed contract reports "3.4.0"; this is a placeholder for the next bump.
const PieceDeletionProcessingMinVersion = "3.5.0"
// SupportsPieceDeletionProcessing reports whether the deployed PDPVerifier
// exposes processPieceDeletions.
//
// The value is read rather than cached for the process lifetime: PDPVerifier is
// a UUPS proxy and can be upgraded in place underneath a running Curio.
func SupportsPieceDeletionProcessing(ctx context.Context, verifier *PDPVerifier) (bool, error) {
version, err := verifier.VERSION(EthCallOpts(ctx))
if err != nil {
return false, xerrors.Errorf("reading PDPVerifier VERSION: %w", err)
}
cmp, err := compareSemver(version, PieceDeletionProcessingMinVersion)
if err != nil {
return false, xerrors.Errorf("comparing PDPVerifier version %q: %w", version, err)
}
return cmp >= 0, nil
}
// compareSemver orders two dotted version strings, returning -1, 0 or 1. Any
// pre-release or build suffix is ignored: "3.5.0-rc1" compares equal to "3.5.0",
// which is the conservative choice for a feature gate on a release candidate.
func compareSemver(a, b string) (int, error) {
aParts, err := parseSemver(a)
if err != nil {
return 0, err
}
bParts, err := parseSemver(b)
if err != nil {
return 0, err
}
for i := range aParts {
switch {
case aParts[i] < bParts[i]:
return -1, nil
case aParts[i] > bParts[i]:
return 1, nil
}
}
return 0, nil
}
func parseSemver(v string) ([3]int, error) {
var out [3]int
v = strings.TrimSpace(v)
v = strings.TrimPrefix(v, "v")
if idx := strings.IndexAny(v, "-+"); idx >= 0 {
v = v[:idx]
}
fields := strings.Split(v, ".")
if len(fields) == 0 || len(fields) > 3 {
return out, xerrors.Errorf("malformed version %q", v)
}
for i, field := range fields {
n, err := strconv.Atoi(field)
if err != nil {
return out, xerrors.Errorf("malformed version %q: component %q is not a number", v, field)
}
if n < 0 {
return out, xerrors.Errorf("malformed version %q: negative component", v)
}
out[i] = n
}
return out, nil
}