Skip to content

Commit 471ab1e

Browse files
committed
chain piece deletion post proving
1 parent 546eb99 commit 471ab1e

9 files changed

Lines changed: 364 additions & 758 deletions

harmony/harmonydb/sql/20260818-pdpv0-deletion-drain.sql

Lines changed: 8 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -5,16 +5,15 @@
55
-- processPieceDeletions, and nextProvingPeriod reverts while the queue is
66
-- non-empty. See https://github.com/FilOzone/pdp/pull/297.
77
--
8-
-- This table is the work queue the drain watcher selects from. Rows are
9-
-- candidates rather than confirmed work: the task's first action is an on-chain
10-
-- queue read, and a row whose data set has an empty queue is simply dropped. So
11-
-- the seed below can be indiscriminate and needs no chain access at migration
12-
-- time.
8+
-- This table coordinates removal draining. Rows are candidates rather than
9+
-- confirmed work: the task's first action is an on-chain queue read, and a row
10+
-- whose data set has an empty queue is simply dropped. So the seed below can be
11+
-- indiscriminate and needs no chain access at migration time.
1312
--
1413
-- Two writers: this one-time seed, which picks up data sets already carrying a
1514
-- removal queue at upgrade time (including any stuck by FilOzone/pdp#283), and
16-
-- the DeletePiece intake path, which inserts a row alongside every
17-
-- schedulePieceDeletions send from here on.
15+
-- proving-period code, which inserts a row when it observes confirmed delete
16+
-- intent that still needs explicit draining.
1817

1918
CREATE TABLE IF NOT EXISTS pdpv0_deletion_drain (
2019
data_set BIGINT PRIMARY KEY REFERENCES pdp_data_sets(id) ON DELETE CASCADE,
@@ -28,16 +27,7 @@ CREATE TABLE IF NOT EXISTS pdpv0_deletion_drain (
2827
-- drains must be sequential because each one re-reads the queue length.
2928
msg_hash TEXT DEFAULT NULL,
3029

31-
-- Bumped when a drain send fails, bounding retries so a permanently failing
32-
-- data set cannot spin forever.
33-
failures BIGINT NOT NULL DEFAULT 0,
34-
35-
-- Set when the task claimed the row but could not act on it yet (for
36-
-- example the challenge window has not closed). Keeps the watcher from
37-
-- re-claiming and re-reading chain state on every tipset.
38-
blocked_at TIMESTAMPTZ DEFAULT NULL,
39-
40-
created_at TIMESTAMPTZ NOT NULL DEFAULT TIMEZONE('UTC', NOW())
30+
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
4131
);
4232

4333
COMMENT ON TABLE pdpv0_deletion_drain IS
@@ -48,7 +38,7 @@ CREATE INDEX IF NOT EXISTS idx_pdpv0_deletion_drain_pending
4838
ON pdpv0_deletion_drain (data_set)
4939
WHERE task_id IS NULL AND msg_hash IS NULL;
5040

51-
-- The confirmation watcher scans by in-flight message.
41+
-- Reorg rollback locates drain rows by in-flight message.
5242
CREATE INDEX IF NOT EXISTS idx_pdpv0_deletion_drain_msg_hash
5343
ON pdpv0_deletion_drain (msg_hash)
5444
WHERE msg_hash IS NOT NULL;

pdp-process-piece-deletions-findings.md

Lines changed: 0 additions & 514 deletions
This file was deleted.

pdp/contract/utils.go

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ import (
1717
"github.com/ethereum/go-ethereum/crypto"
1818
logging "github.com/ipfs/go-log/v2"
1919
"github.com/jellydator/ttlcache/v2"
20+
"golang.org/x/mod/semver"
2021
"golang.org/x/xerrors"
2122

2223
"github.com/filecoin-project/go-address"
@@ -56,6 +57,23 @@ const (
5657
CapIpniPeerIDDeprecated = "IPNIPeerID"
5758
)
5859

60+
const pdpVerifierProcessPieceDeletionsAfterVersion = "v3.4.0"
61+
62+
func SemverVersion(version string) string {
63+
if strings.HasPrefix(version, "v") {
64+
return version
65+
}
66+
return "v" + version
67+
}
68+
69+
func SupportsPieceDeletionProcessing(ctx context.Context, verifier *PDPVerifier) (bool, error) {
70+
version, err := verifier.VERSION(EthCallOpts(ctx))
71+
if err != nil {
72+
return false, xerrors.Errorf("failed to get PDPVerifier version: %w", err)
73+
}
74+
return semver.Compare(SemverVersion(version), pdpVerifierProcessPieceDeletionsAfterVersion) > 0, nil
75+
}
76+
5977
// PDPOfferingData converts a PDPOffering-like struct to capability key-value pairs
6078
type PDPOfferingData struct {
6179
ServiceURL string

tasks/pdpv0/error_detection.go

Lines changed: 4 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -31,11 +31,8 @@ var (
3131
ErrPDPVerifierDataSetNotLive abi.Error
3232
ErrPDPVerifierInsufficientChallengeDelay abi.Error
3333

34-
ErrPDPVerifierPendingPieceDeletions abi.Error
35-
ErrPDPVerifierInvalidPieceDeletionBatch abi.Error
36-
ErrPDPVerifierEmptyRemovalBatch abi.Error
37-
ErrPDPVerifierOnlyStorageProvider abi.Error
38-
ErrPDPVerifierNoPiecesToProve abi.Error
34+
ErrPDPVerifierPendingPieceDeletions abi.Error
35+
ErrPDPVerifierNoPiecesToProve abi.Error
3936

4037
// Unexpected proving invariant errors. Curio should not produce these in
4138
// normal PDPv0 initPP/nextPP/prove flow; classify them explicitly so they
@@ -83,29 +80,12 @@ func init() {
8380
panic("PDPVerifier ABI missing ExcessiveChallengeDelay error")
8481
}
8582

86-
removalQueue := contract.RemovalQueueABI()
87-
88-
ErrPDPVerifierPendingPieceDeletions, ok = removalQueue.Errors["PendingPieceDeletions"]
83+
ErrPDPVerifierPendingPieceDeletions, ok = parsedPDPVerifier.Errors["PendingPieceDeletions"]
8984
if !ok {
9085
panic("PDPVerifier removal ABI missing PendingPieceDeletions error")
9186
}
9287

93-
ErrPDPVerifierInvalidPieceDeletionBatch, ok = removalQueue.Errors["InvalidPieceDeletionBatch"]
94-
if !ok {
95-
panic("PDPVerifier removal ABI missing InvalidPieceDeletionBatch error")
96-
}
97-
98-
ErrPDPVerifierEmptyRemovalBatch, ok = removalQueue.Errors["EmptyRemovalBatch"]
99-
if !ok {
100-
panic("PDPVerifier removal ABI missing EmptyRemovalBatch error")
101-
}
102-
103-
ErrPDPVerifierOnlyStorageProvider, ok = removalQueue.Errors["OnlyStorageProvider"]
104-
if !ok {
105-
panic("PDPVerifier removal ABI missing OnlyStorageProvider error")
106-
}
107-
108-
ErrPDPVerifierNoPiecesToProve, ok = removalQueue.Errors["NoPiecesToProve"]
88+
ErrPDPVerifierNoPiecesToProve, ok = parsedPDPVerifier.Errors["NoPiecesToProve"]
10989
if !ok {
11090
panic("PDPVerifier removal ABI missing NoPiecesToProve error")
11191
}
@@ -267,22 +247,6 @@ func IsPendingPieceDeletionsError(err error) bool {
267247
return strings.Contains(strings.ToLower(err.Error()), contractErrorSelector(ErrPDPVerifierPendingPieceDeletions))
268248
}
269249

270-
func IsStaleRemovalQueueViewError(err error) bool {
271-
if err == nil {
272-
return false
273-
}
274-
errStr := strings.ToLower(err.Error())
275-
return strings.Contains(errStr, contractErrorSelector(ErrPDPVerifierInvalidPieceDeletionBatch)) ||
276-
strings.Contains(errStr, contractErrorSelector(ErrPDPVerifierEmptyRemovalBatch))
277-
}
278-
279-
func IsOnlyStorageProviderError(err error) bool {
280-
if err == nil {
281-
return false
282-
}
283-
return strings.Contains(strings.ToLower(err.Error()), contractErrorSelector(ErrPDPVerifierOnlyStorageProvider))
284-
}
285-
286250
func IsPDPVerifierDataSetNotLive(err error) bool {
287251
if err == nil {
288252
return false

tasks/pdpv0/task_next_pp.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -464,7 +464,7 @@ func handleNextProvingPeriodSendError(ctx context.Context, tx *harmonydb.Tx, pro
464464
}
465465
log.Warnw("Proving period scheduling blocked by pending piece deletions; draining first",
466466
"dataSetId", dataSetId, "subsystem", alertSubsystem, "height", currentHeight, "error", sendErr)
467-
return sendErr
467+
return nil
468468
case IsInsufficientChallengeDelayError(sendErr):
469469
// The challenge epoch was too close to the current block. Retry the
470470
// task so it recomputes challenge state and calldata instead of

0 commit comments

Comments
 (0)