Skip to content

Commit d79acce

Browse files
committed
feat: test post cli: Vanilla Proof test command
1 parent 1fb3d0f commit d79acce

File tree

8 files changed

+662
-365
lines changed

8 files changed

+662
-365
lines changed

cmd/curio/internal/translations/catalog.go

Lines changed: 359 additions & 357 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

cmd/curio/internal/translations/locales/en/out.gotext.json

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1156,6 +1156,13 @@
11561156
"translatorComment": "Copied from source.",
11571157
"fuzzy": true
11581158
},
1159+
{
1160+
"id": "Compute WindowPoSt vanilla proofs and verify them.",
1161+
"message": "Compute WindowPoSt vanilla proofs and verify them.",
1162+
"translation": "Compute WindowPoSt vanilla proofs and verify them.",
1163+
"translatorComment": "Copied from source.",
1164+
"fuzzy": true
1165+
},
11591166
{
11601167
"id": "Collection of debugging utilities",
11611168
"message": "Collection of debugging utilities",
Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,11 @@
11
{
22
"language": "ko",
3-
"messages": []
3+
"messages": [
4+
{
5+
"id": "Compute WindowPoSt vanilla proofs and verify them.",
6+
"translation": "",
7+
"message": "Compute WindowPoSt vanilla proofs and verify them.",
8+
"placeholder": null
9+
}
10+
]
411
}
Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,11 @@
11
{
22
"language": "zh",
3-
"messages": []
3+
"messages": [
4+
{
5+
"id": "Compute WindowPoSt vanilla proofs and verify them.",
6+
"translation": "",
7+
"message": "Compute WindowPoSt vanilla proofs and verify them.",
8+
"placeholder": null
9+
}
10+
]
411
}

cmd/curio/test-cli.go

Lines changed: 248 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,26 +1,37 @@
11
package main
22

33
import (
4+
"bytes"
45
"context"
56
"database/sql"
67
"encoding/json"
78
"errors"
89
"fmt"
910
"os"
11+
"runtime"
12+
"sync"
1013
"time"
1114

1215
"github.com/samber/lo"
16+
"github.com/snadrus/must"
1317
"github.com/urfave/cli/v2"
1418
"github.com/yugabyte/pgx/v5"
1519
"golang.org/x/xerrors"
1620

21+
ffi "github.com/filecoin-project/filecoin-ffi"
1722
"github.com/filecoin-project/go-address"
23+
"github.com/filecoin-project/go-state-types/abi"
24+
"github.com/filecoin-project/go-state-types/builtin"
25+
"github.com/filecoin-project/go-state-types/crypto"
1826
"github.com/filecoin-project/go-state-types/dline"
27+
"github.com/filecoin-project/go-state-types/proof"
1928

2029
"github.com/filecoin-project/curio/cmd/curio/internal/translations"
2130
"github.com/filecoin-project/curio/cmd/curio/tasks"
2231
"github.com/filecoin-project/curio/deps"
2332
"github.com/filecoin-project/curio/harmony/harmonydb"
33+
cuproof "github.com/filecoin-project/curio/lib/proof"
34+
"github.com/filecoin-project/curio/lib/storiface"
2435
)
2536

2637
var testCmd = &cli.Command{
@@ -43,6 +54,7 @@ var wdPostCmd = &cli.Command{
4354
Subcommands: []*cli.Command{
4455
wdPostHereCmd,
4556
wdPostTaskCmd,
57+
wdPostVanillaCmd,
4658
},
4759
}
4860

@@ -216,6 +228,10 @@ It will not send any messages to the chain. Since it can compute any deadline, o
216228
Usage: translations.T("partition to compute WindowPoSt for"),
217229
Value: 0,
218230
},
231+
&cli.StringFlag{
232+
Name: "addr",
233+
Usage: translations.T("SP ID to compute WindowPoSt for"),
234+
},
219235
},
220236
Action: func(cctx *cli.Context) error {
221237

@@ -225,6 +241,14 @@ It will not send any messages to the chain. Since it can compute any deadline, o
225241
return err
226242
}
227243

244+
var spAddr address.Address
245+
if cctx.IsSet("addr") {
246+
spAddr, err = address.NewFromString(cctx.String("addr"))
247+
if err != nil {
248+
return xerrors.Errorf("invalid sp address: %w", err)
249+
}
250+
}
251+
228252
wdPostTask, wdPoStSubmitTask, derlareRecoverTask, err := tasks.WindowPostScheduler(
229253
ctx, deps.Cfg.Fees, deps.Cfg.Proving, deps.Chain, deps.Verif, nil, nil, nil,
230254
deps.As, deps.Maddrs, deps.DB, deps.Stor, deps.Si, deps.Cfg.Subsystems.WindowPostMaxTasks)
@@ -244,6 +268,10 @@ It will not send any messages to the chain. Since it can compute any deadline, o
244268
di := dline.NewInfo(head.Height(), cctx.Uint64("deadline"), 0, 0, 0, 10 /*challenge window*/, 0, 0)
245269

246270
for maddr := range deps.Maddrs {
271+
if spAddr != address.Undef && address.Address(maddr) != spAddr {
272+
continue
273+
}
274+
247275
out, err := wdPostTask.DoPartition(ctx, head, address.Address(maddr), di, cctx.Uint64("partition"), true)
248276
if err != nil {
249277
fmt.Println("Error computing WindowPoSt for miner", maddr, err)
@@ -260,3 +288,223 @@ It will not send any messages to the chain. Since it can compute any deadline, o
260288
return nil
261289
},
262290
}
291+
292+
var wdPostVanillaCmd = &cli.Command{
293+
Name: "vanilla",
294+
Usage: translations.T("Compute WindowPoSt vanilla proofs and verify them."),
295+
Flags: []cli.Flag{
296+
&cli.Uint64Flag{
297+
Name: "deadline",
298+
Usage: translations.T("deadline to compute WindowPoSt for "),
299+
Value: 0,
300+
},
301+
&cli.StringSliceFlag{
302+
Name: "layers",
303+
Usage: translations.T("list of layers to be interpreted (atop defaults). Default: base"),
304+
},
305+
&cli.Uint64Flag{
306+
Name: "partition",
307+
Usage: translations.T("partition to compute WindowPoSt for"),
308+
Value: 0,
309+
},
310+
&cli.StringFlag{
311+
Name: "addr",
312+
Usage: translations.T("SP ID to compute WindowPoSt for"),
313+
},
314+
},
315+
Action: func(cctx *cli.Context) error {
316+
start := time.Now()
317+
318+
ctx := context.Background()
319+
deps, err := deps.GetDeps(ctx, cctx)
320+
if err != nil {
321+
return err
322+
}
323+
324+
var spAddr address.Address
325+
if cctx.IsSet("addr") {
326+
spAddr, err = address.NewFromString(cctx.String("addr"))
327+
if err != nil {
328+
return xerrors.Errorf("invalid sp address: %w", err)
329+
}
330+
}
331+
332+
wdPostTask, wdPoStSubmitTask, derlareRecoverTask, err := tasks.WindowPostScheduler(
333+
ctx, deps.Cfg.Fees, deps.Cfg.Proving, deps.Chain, deps.Verif, nil, nil, nil,
334+
deps.As, deps.Maddrs, deps.DB, deps.Stor, deps.Si, deps.Cfg.Subsystems.WindowPostMaxTasks)
335+
if err != nil {
336+
return err
337+
}
338+
_, _ = wdPoStSubmitTask, derlareRecoverTask
339+
340+
if len(deps.Maddrs) == 0 {
341+
return errors.New("no miners to compute WindowPoSt for")
342+
}
343+
head, err := deps.Chain.ChainHead(ctx)
344+
if err != nil {
345+
return xerrors.Errorf("failed to get chain head: %w", err)
346+
}
347+
348+
di := dline.NewInfo(head.Height(), cctx.Uint64("deadline"), 0, 0, 0, 10 /*challenge window*/, 0, 0)
349+
350+
for maddr := range deps.Maddrs {
351+
if spAddr != address.Undef && address.Address(maddr) != spAddr {
352+
continue
353+
}
354+
355+
maddr := address.Address(maddr)
356+
mid, err := address.IDFromAddress(maddr)
357+
if err != nil {
358+
return xerrors.Errorf("failed to get miner id: %w", err)
359+
}
360+
361+
buf := new(bytes.Buffer)
362+
if err := maddr.MarshalCBOR(buf); err != nil {
363+
return xerrors.Errorf("failed to marshal address to cbor: %w", err)
364+
}
365+
366+
headTs, err := deps.Chain.ChainHead(ctx)
367+
if err != nil {
368+
return xerrors.Errorf("getting current head: %w", err)
369+
}
370+
371+
rand, err := deps.Chain.StateGetRandomnessFromBeacon(ctx, crypto.DomainSeparationTag_WindowedPoStChallengeSeed, di.Challenge, buf.Bytes(), headTs.Key())
372+
if err != nil {
373+
return xerrors.Errorf("failed to get chain randomness from beacon for window post (ts=%d; deadline=%d): %w", headTs.Height(), di, err)
374+
}
375+
rand[31] &= 0x3f
376+
377+
parts, err := deps.Chain.StateMinerPartitions(ctx, maddr, di.Index, headTs.Key())
378+
if err != nil {
379+
return xerrors.Errorf("getting partitions: %w", err)
380+
}
381+
382+
if cctx.Uint64("partition") >= uint64(len(parts)) {
383+
return xerrors.Errorf("invalid partition: %d", cctx.Uint64("partition"))
384+
}
385+
386+
partition := parts[cctx.Uint64("partition")]
387+
388+
log.Infow("Getting sectors for proof", "partition", cctx.Uint64("partition"), "liveSectors", must.One(partition.LiveSectors.Count()), "allSectors", must.One(partition.AllSectors.Count()))
389+
390+
xsinfos, err := wdPostTask.SectorsForProof(ctx, maddr, partition.LiveSectors, partition.AllSectors, headTs)
391+
if err != nil {
392+
return xerrors.Errorf("getting sectors for proof: %w", err)
393+
}
394+
395+
if len(xsinfos) == 0 {
396+
return xerrors.Errorf("no sectors to prove")
397+
}
398+
399+
nv, err := deps.Chain.StateNetworkVersion(ctx, headTs.Key())
400+
if err != nil {
401+
return xerrors.Errorf("getting network version: %w", err)
402+
}
403+
404+
ppt, err := xsinfos[0].SealProof.RegisteredWindowPoStProofByNetworkVersion(nv)
405+
if err != nil {
406+
return xerrors.Errorf("failed to get window post type: %w", err)
407+
}
408+
409+
sectorNums := make([]abi.SectorNumber, len(xsinfos))
410+
sectorMap := make(map[abi.SectorNumber]proof.ExtendedSectorInfo)
411+
for i, s := range xsinfos {
412+
sectorNums[i] = s.SectorNumber
413+
sectorMap[s.SectorNumber] = s
414+
}
415+
416+
postChallenges, err := ffi.GeneratePoStFallbackSectorChallenges(ppt, abi.ActorID(mid), abi.PoStRandomness(rand), sectorNums)
417+
if err != nil {
418+
return xerrors.Errorf("generating fallback challenges: %w", err)
419+
}
420+
421+
maxPartitionSize, err := builtin.PoStProofWindowPoStPartitionSectors(ppt)
422+
if err != nil {
423+
return xerrors.Errorf("get sectors count of partition failed:%+v", err)
424+
}
425+
426+
sectors := make([]storiface.PostSectorChallenge, 0)
427+
for i := range postChallenges.Sectors {
428+
snum := postChallenges.Sectors[i]
429+
sinfo := sectorMap[snum]
430+
431+
sectors = append(sectors, storiface.PostSectorChallenge{
432+
SealProof: sinfo.SealProof,
433+
SectorNumber: snum,
434+
SealedCID: sinfo.SealedCID,
435+
Challenge: postChallenges.Challenges[snum],
436+
Update: sinfo.SectorKey != nil,
437+
})
438+
}
439+
elapsed := time.Since(start)
440+
log.Infow("Generated fallback challenges", "error", err, "elapsed", elapsed, "sectors", len(sectors), "maxPartitionSize", maxPartitionSize, "postChallenges", len(postChallenges.Challenges))
441+
442+
var outLk sync.Mutex
443+
444+
wg := sync.WaitGroup{}
445+
wg.Add(len(sectors))
446+
throttle := make(chan struct{}, runtime.NumCPU())
447+
448+
for i, s := range sectors {
449+
go func(i int, s storiface.PostSectorChallenge) {
450+
451+
throttle <- struct{}{}
452+
defer func() {
453+
<-throttle
454+
}()
455+
defer wg.Done()
456+
457+
start := time.Now()
458+
vanilla, err := deps.Stor.GenerateSingleVanillaProof(ctx, abi.ActorID(mid), s, ppt)
459+
elapsed := time.Since(start)
460+
461+
if err != nil || vanilla == nil {
462+
outLk.Lock()
463+
log.Errorw("Generated vanilla proof for sector", "sector", s.SectorNumber, "of", fmt.Sprintf("%d/%d", i+1, len(sectors)), "error", err, "elapsed", elapsed)
464+
log.Errorw("reading PoSt challenge for sector", "sector", s.SectorNumber, "vlen", len(vanilla), "error", err)
465+
outLk.Unlock()
466+
return
467+
}
468+
469+
// verify vproofs
470+
pvi := proof.WindowPoStVerifyInfo{
471+
Randomness: abi.PoStRandomness(rand),
472+
Proofs: []proof.PoStProof{},
473+
ChallengedSectors: []proof.SectorInfo{},
474+
}
475+
pvi.Proofs = append(pvi.Proofs, proof.PoStProof{
476+
PoStProof: ppt,
477+
ProofBytes: vanilla,
478+
})
479+
for _, s := range sectors {
480+
pvi.ChallengedSectors = append(pvi.ChallengedSectors, proof.SectorInfo{
481+
SealProof: s.SealProof,
482+
SectorNumber: s.SectorNumber,
483+
SealedCID: s.SealedCID,
484+
})
485+
}
486+
487+
verifyStart := time.Now()
488+
ok, err := cuproof.VerifyWindowPoStVanilla(pvi)
489+
verifyElapsed := time.Since(verifyStart)
490+
491+
outLk.Lock()
492+
if elapsed.Seconds() > 2 {
493+
log.Warnw("Generated vanilla proof for sector (slow)", "sector", s.SectorNumber, "of", fmt.Sprintf("%d/%d", i+1, len(sectors)), "elapsed", elapsed)
494+
} else {
495+
log.Debugw("Generated vanilla proof for sector", "sector", s.SectorNumber, "of", fmt.Sprintf("%d/%d", i+1, len(sectors)), "elapsed", elapsed)
496+
}
497+
if err != nil || !ok {
498+
log.Errorw("Verified window post vanilla proofs", "error", err, "elapsed", verifyElapsed, "ok", ok)
499+
} else {
500+
log.Debugw("Verified window post vanilla proofs", "elapsed", verifyElapsed, "ok", ok)
501+
}
502+
outLk.Unlock()
503+
}(i, s)
504+
}
505+
wg.Wait()
506+
}
507+
508+
return nil
509+
},
510+
}

documentation/en/curio-cli/curio.md

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -510,6 +510,7 @@ USAGE:
510510
COMMANDS:
511511
here, cli Compute WindowPoSt for performance and configuration testing.
512512
task, scheduled, schedule, async, asynchronous Test the windowpost scheduler by running it on the next available curio. If tasks fail all retries, you will need to ctrl+c to exit.
513+
vanilla Compute WindowPoSt vanilla proofs and verify them.
513514
help, h Shows a list of commands or help for one command
514515
515516
OPTIONS:
@@ -532,6 +533,7 @@ OPTIONS:
532533
--deadline value deadline to compute WindowPoSt for (default: 0)
533534
--layers value [ --layers value ] list of layers to be interpreted (atop defaults). Default: base
534535
--partition value partition to compute WindowPoSt for (default: 0)
536+
--addr value SP ID to compute WindowPoSt for
535537
--help, -h show help
536538
```
537539

@@ -550,6 +552,22 @@ OPTIONS:
550552
--help, -h show help
551553
```
552554

555+
#### curio test window-post vanilla
556+
```
557+
NAME:
558+
curio test window-post vanilla - Compute WindowPoSt vanilla proofs and verify them.
559+
560+
USAGE:
561+
curio test window-post vanilla [command options]
562+
563+
OPTIONS:
564+
--deadline value deadline to compute WindowPoSt for (default: 0)
565+
--layers value [ --layers value ] list of layers to be interpreted (atop defaults). Default: base
566+
--partition value partition to compute WindowPoSt for (default: 0)
567+
--addr value SP ID to compute WindowPoSt for
568+
--help, -h show help
569+
```
570+
553571
### curio test debug
554572
```
555573
NAME:

0 commit comments

Comments
 (0)