chore: test: refactor, fix and improve unmanaged miner (#12143)
from niporep work, including some necessary bits from there but are useful in general
This commit is contained in:
parent
40651abc0a
commit
a60a8c7f8a
@ -6,6 +6,7 @@ import (
|
||||
"crypto/rand"
|
||||
"fmt"
|
||||
"io"
|
||||
"math"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"testing"
|
||||
@ -224,82 +225,6 @@ func (tm *TestUnmanagedMiner) makeAndSaveCCSector(_ context.Context, sectorNumbe
|
||||
tm.cacheDirPaths[sectorNumber] = cacheDirPath
|
||||
}
|
||||
|
||||
func (tm *TestUnmanagedMiner) OnboardSectorWithPieces(ctx context.Context, proofType abi.RegisteredSealProof) (abi.SectorNumber, chan WindowPostResp,
|
||||
context.CancelFunc) {
|
||||
req := require.New(tm.t)
|
||||
sectorNumber := tm.currentSectorNum
|
||||
tm.currentSectorNum++
|
||||
|
||||
// Step 1: Wait for the pre-commitseal randomness to be available (we can only draw seal randomness from tipsets that have already achieved finality)
|
||||
preCommitSealRand := tm.waitPreCommitSealRandomness(ctx, sectorNumber)
|
||||
|
||||
// Step 2: Build a sector with non 0 Pieces that we want to onboard
|
||||
var pieces []abi.PieceInfo
|
||||
if !tm.mockProofs {
|
||||
pieces = tm.mkAndSavePiecesToOnboard(ctx, sectorNumber, proofType)
|
||||
} else {
|
||||
pieces = []abi.PieceInfo{{
|
||||
Size: abi.PaddedPieceSize(tm.options.sectorSize),
|
||||
PieceCID: cid.MustParse("baga6ea4seaqjtovkwk4myyzj56eztkh5pzsk5upksan6f5outesy62bsvl4dsha"),
|
||||
}}
|
||||
}
|
||||
|
||||
// Step 3: Generate a Pre-Commit for the CC sector -> this persists the proof on the `TestUnmanagedMiner` Miner State
|
||||
if !tm.mockProofs {
|
||||
tm.generatePreCommit(ctx, sectorNumber, preCommitSealRand, proofType, pieces)
|
||||
} else {
|
||||
tm.sealedCids[sectorNumber] = cid.MustParse("bagboea4b5abcatlxechwbp7kjpjguna6r6q7ejrhe6mdp3lf34pmswn27pkkiekz")
|
||||
tm.unsealedCids[sectorNumber] = cid.MustParse("baga6ea4seaqjtovkwk4myyzj56eztkh5pzsk5upksan6f5outesy62bsvl4dsha")
|
||||
}
|
||||
|
||||
// Step 4 : Submit the Pre-Commit to the network
|
||||
unsealedCid := tm.unsealedCids[sectorNumber]
|
||||
r, err := tm.submitMessage(ctx, &miner14.PreCommitSectorBatchParams2{
|
||||
Sectors: []miner14.SectorPreCommitInfo{{
|
||||
Expiration: 2880 * 300,
|
||||
SectorNumber: sectorNumber,
|
||||
SealProof: TestSpt,
|
||||
SealedCID: tm.sealedCids[sectorNumber],
|
||||
SealRandEpoch: preCommitSealRand,
|
||||
UnsealedCid: &unsealedCid,
|
||||
}},
|
||||
}, 1, builtin.MethodsMiner.PreCommitSectorBatch2)
|
||||
req.NoError(err)
|
||||
req.True(r.Receipt.ExitCode.IsSuccess())
|
||||
|
||||
// Step 5: Generate a ProveCommit for the CC sector
|
||||
waitSeedRandomness := tm.proveCommitWaitSeed(ctx, sectorNumber)
|
||||
|
||||
proveCommit := []byte{0xde, 0xad, 0xbe, 0xef} // mock prove commit
|
||||
if !tm.mockProofs {
|
||||
proveCommit = tm.generateProveCommit(ctx, sectorNumber, proofType, waitSeedRandomness, pieces)
|
||||
}
|
||||
|
||||
// Step 6: Submit the ProveCommit to the network
|
||||
tm.t.Log("Submitting ProveCommitSector ...")
|
||||
|
||||
var manifest []miner14.PieceActivationManifest
|
||||
for _, piece := range pieces {
|
||||
manifest = append(manifest, miner14.PieceActivationManifest{
|
||||
CID: piece.PieceCID,
|
||||
Size: piece.Size,
|
||||
})
|
||||
}
|
||||
|
||||
r, err = tm.submitMessage(ctx, &miner14.ProveCommitSectors3Params{
|
||||
SectorActivations: []miner14.SectorActivationManifest{{SectorNumber: sectorNumber, Pieces: manifest}},
|
||||
SectorProofs: [][]byte{proveCommit},
|
||||
RequireActivationSuccess: true,
|
||||
}, 1, builtin.MethodsMiner.ProveCommitSectors3)
|
||||
req.NoError(err)
|
||||
req.True(r.Receipt.ExitCode.IsSuccess())
|
||||
|
||||
tm.proofType[sectorNumber] = proofType
|
||||
|
||||
respCh, cancelFn := tm.wdPostLoop(ctx, sectorNumber, tm.sealedCids[sectorNumber], tm.sealedSectorPaths[sectorNumber], tm.cacheDirPaths[sectorNumber])
|
||||
return sectorNumber, respCh, cancelFn
|
||||
}
|
||||
|
||||
func (tm *TestUnmanagedMiner) mkStagedFileWithPieces(pt abi.RegisteredSealProof) ([]abi.PieceInfo, string) {
|
||||
paddedPieceSize := abi.PaddedPieceSize(tm.options.sectorSize)
|
||||
unpaddedPieceSize := paddedPieceSize.Unpadded()
|
||||
@ -340,39 +265,51 @@ func (tm *TestUnmanagedMiner) mkStagedFileWithPieces(pt abi.RegisteredSealProof)
|
||||
return publicPieces, unsealedSectorFile.Name()
|
||||
}
|
||||
|
||||
func (tm *TestUnmanagedMiner) SnapDeal(ctx context.Context, proofType abi.RegisteredSealProof, sectorNumber abi.SectorNumber) {
|
||||
if tm.mockProofs {
|
||||
tm.t.Fatal("snap deal with mock proofs currently not supported")
|
||||
func (tm *TestUnmanagedMiner) SnapDeal(ctx context.Context, proofType abi.RegisteredSealProof, sectorNumber abi.SectorNumber) []abi.PieceInfo {
|
||||
updateProofType := abi.SealProofInfos[proofType].UpdateProof
|
||||
var pieces []abi.PieceInfo
|
||||
var snapProof []byte
|
||||
var newSealedCid cid.Cid
|
||||
|
||||
if !tm.mockProofs {
|
||||
// generate sector key
|
||||
var unsealedPath string
|
||||
pieces, unsealedPath = tm.mkStagedFileWithPieces(proofType)
|
||||
|
||||
s, err := os.Stat(tm.sealedSectorPaths[sectorNumber])
|
||||
require.NoError(tm.t, err)
|
||||
|
||||
randomBytes := make([]byte, s.Size())
|
||||
_, err = io.ReadFull(rand.Reader, randomBytes)
|
||||
require.NoError(tm.t, err)
|
||||
|
||||
updatePath := requireTempFile(tm.t, bytes.NewReader(randomBytes), uint64(s.Size()))
|
||||
require.NoError(tm.t, updatePath.Close())
|
||||
updateDir := filepath.Join(tm.t.TempDir(), fmt.Sprintf("update-%d", sectorNumber))
|
||||
require.NoError(tm.t, os.MkdirAll(updateDir, 0700))
|
||||
|
||||
var newUnsealedCid cid.Cid
|
||||
newSealedCid, newUnsealedCid, err = ffi.SectorUpdate.EncodeInto(updateProofType, updatePath.Name(), updateDir,
|
||||
tm.sealedSectorPaths[sectorNumber], tm.cacheDirPaths[sectorNumber], unsealedPath, pieces)
|
||||
require.NoError(tm.t, err)
|
||||
|
||||
vp, err := ffi.SectorUpdate.GenerateUpdateVanillaProofs(updateProofType, tm.sealedCids[sectorNumber],
|
||||
newSealedCid, newUnsealedCid, updatePath.Name(), updateDir, tm.sealedSectorPaths[sectorNumber],
|
||||
tm.cacheDirPaths[sectorNumber])
|
||||
require.NoError(tm.t, err)
|
||||
|
||||
snapProof, err = ffi.SectorUpdate.GenerateUpdateProofWithVanilla(updateProofType, tm.sealedCids[sectorNumber],
|
||||
newSealedCid, newUnsealedCid, vp)
|
||||
require.NoError(tm.t, err)
|
||||
} else {
|
||||
pieces = []abi.PieceInfo{{
|
||||
Size: abi.PaddedPieceSize(tm.options.sectorSize),
|
||||
PieceCID: cid.MustParse("baga6ea4seaqlhznlutptgfwhffupyer6txswamerq5fc2jlwf2lys2mm5jtiaeq"),
|
||||
}}
|
||||
snapProof = []byte{0xde, 0xad, 0xbe, 0xef}
|
||||
newSealedCid = cid.MustParse("bagboea4b5abcatlxechwbp7kjpjguna6r6q7ejrhe6mdp3lf34pmswn27pkkieka")
|
||||
}
|
||||
|
||||
// generate sector key
|
||||
pieces, unsealedPath := tm.mkStagedFileWithPieces(proofType)
|
||||
updateProofType := abi.SealProofInfos[proofType].UpdateProof
|
||||
|
||||
s, err := os.Stat(tm.sealedSectorPaths[sectorNumber])
|
||||
require.NoError(tm.t, err)
|
||||
|
||||
randomBytes := make([]byte, s.Size())
|
||||
_, err = io.ReadFull(rand.Reader, randomBytes)
|
||||
require.NoError(tm.t, err)
|
||||
|
||||
updatePath := requireTempFile(tm.t, bytes.NewReader(randomBytes), uint64(s.Size()))
|
||||
require.NoError(tm.t, updatePath.Close())
|
||||
updateDir := filepath.Join(tm.t.TempDir(), fmt.Sprintf("update-%d", sectorNumber))
|
||||
require.NoError(tm.t, os.MkdirAll(updateDir, 0700))
|
||||
|
||||
newSealed, newUnsealed, err := ffi.SectorUpdate.EncodeInto(updateProofType, updatePath.Name(), updateDir,
|
||||
tm.sealedSectorPaths[sectorNumber], tm.cacheDirPaths[sectorNumber], unsealedPath, pieces)
|
||||
require.NoError(tm.t, err)
|
||||
|
||||
vp, err := ffi.SectorUpdate.GenerateUpdateVanillaProofs(updateProofType, tm.sealedCids[sectorNumber],
|
||||
newSealed, newUnsealed, updatePath.Name(), updateDir, tm.sealedSectorPaths[sectorNumber],
|
||||
tm.cacheDirPaths[sectorNumber])
|
||||
require.NoError(tm.t, err)
|
||||
|
||||
snapProof, err := ffi.SectorUpdate.GenerateUpdateProofWithVanilla(updateProofType, tm.sealedCids[sectorNumber],
|
||||
newSealed, newUnsealed, vp)
|
||||
require.NoError(tm.t, err)
|
||||
tm.waitForMutableDeadline(ctx, sectorNumber)
|
||||
|
||||
// submit proof
|
||||
@ -396,7 +333,7 @@ func (tm *TestUnmanagedMiner) SnapDeal(ctx context.Context, proofType abi.Regist
|
||||
Sector: sectorNumber,
|
||||
Deadline: sl.Deadline,
|
||||
Partition: sl.Partition,
|
||||
NewSealedCID: newSealed,
|
||||
NewSealedCID: newSealedCid,
|
||||
Pieces: manifest,
|
||||
},
|
||||
},
|
||||
@ -405,9 +342,11 @@ func (tm *TestUnmanagedMiner) SnapDeal(ctx context.Context, proofType abi.Regist
|
||||
RequireActivationSuccess: true,
|
||||
RequireNotificationSuccess: false,
|
||||
}
|
||||
r, err := tm.submitMessage(ctx, params, 1, builtin.MethodsMiner.ProveReplicaUpdates3)
|
||||
r, err := tm.SubmitMessage(ctx, params, 1, builtin.MethodsMiner.ProveReplicaUpdates3)
|
||||
require.NoError(tm.t, err)
|
||||
require.True(tm.t, r.Receipt.ExitCode.IsSuccess())
|
||||
|
||||
return pieces
|
||||
}
|
||||
|
||||
func (tm *TestUnmanagedMiner) waitForMutableDeadline(ctx context.Context, sectorNum abi.SectorNumber) {
|
||||
@ -440,66 +379,228 @@ func (tm *TestUnmanagedMiner) waitForMutableDeadline(ctx context.Context, sector
|
||||
}
|
||||
}
|
||||
|
||||
func (tm *TestUnmanagedMiner) OnboardCCSector(ctx context.Context, proofType abi.RegisteredSealProof) (abi.SectorNumber, chan WindowPostResp,
|
||||
context.CancelFunc) {
|
||||
req := require.New(tm.t)
|
||||
func (tm *TestUnmanagedMiner) NextSectorNumber() abi.SectorNumber {
|
||||
sectorNumber := tm.currentSectorNum
|
||||
tm.currentSectorNum++
|
||||
return sectorNumber
|
||||
}
|
||||
|
||||
func (tm *TestUnmanagedMiner) PrepareSectorForProveCommit(
|
||||
ctx context.Context,
|
||||
proofType abi.RegisteredSealProof,
|
||||
sectorNumber abi.SectorNumber,
|
||||
pieces []abi.PieceInfo,
|
||||
) (seedEpoch abi.ChainEpoch, proveCommit []byte) {
|
||||
|
||||
req := require.New(tm.t)
|
||||
|
||||
// Wait for the pre-commitseal randomness to be available (we can only draw seal randomness from tipsets that have already achieved finality)
|
||||
preCommitSealRandEpoch := tm.waitPreCommitSealRandomness(ctx, sectorNumber, proofType)
|
||||
|
||||
// Generate a Pre-Commit for the CC sector -> this persists the proof on the `TestUnmanagedMiner` Miner State
|
||||
tm.generatePreCommit(ctx, sectorNumber, preCommitSealRandEpoch, proofType, pieces)
|
||||
|
||||
// --------------------Create pre-commit for the CC sector -> we'll just pre-commit `sector size` worth of 0s for this CC sector
|
||||
|
||||
// Step 1: Wait for the pre-commitseal randomness to be available (we can only draw seal randomness from tipsets that have already achieved finality)
|
||||
preCommitSealRand := tm.waitPreCommitSealRandomness(ctx, sectorNumber)
|
||||
|
||||
if !tm.mockProofs {
|
||||
// Step 2: Write empty bytes that we want to seal i.e. create our CC sector
|
||||
tm.makeAndSaveCCSector(ctx, sectorNumber)
|
||||
|
||||
// Step 3: Generate a Pre-Commit for the CC sector -> this persists the proof on the `TestUnmanagedMiner` Miner State
|
||||
tm.generatePreCommit(ctx, sectorNumber, preCommitSealRand, proofType, []abi.PieceInfo{})
|
||||
} else {
|
||||
// skip the above steps and use a mock sealed CID
|
||||
tm.sealedCids[sectorNumber] = cid.MustParse("bagboea4b5abcatlxechwbp7kjpjguna6r6q7ejrhe6mdp3lf34pmswn27pkkiekz")
|
||||
if !proofType.IsNonInteractive() {
|
||||
// Submit the Pre-Commit to the network
|
||||
var uc *cid.Cid
|
||||
if len(pieces) > 0 {
|
||||
unsealedCid := tm.unsealedCids[sectorNumber]
|
||||
uc = &unsealedCid
|
||||
}
|
||||
r, err := tm.SubmitMessage(ctx, &miner14.PreCommitSectorBatchParams2{
|
||||
Sectors: []miner14.SectorPreCommitInfo{{
|
||||
Expiration: 2880 * 300,
|
||||
SectorNumber: sectorNumber,
|
||||
SealProof: proofType,
|
||||
SealedCID: tm.sealedCids[sectorNumber],
|
||||
SealRandEpoch: preCommitSealRandEpoch,
|
||||
UnsealedCid: uc,
|
||||
}},
|
||||
}, 1, builtin.MethodsMiner.PreCommitSectorBatch2)
|
||||
req.NoError(err)
|
||||
req.True(r.Receipt.ExitCode.IsSuccess())
|
||||
}
|
||||
|
||||
// Step 4 : Submit the Pre-Commit to the network
|
||||
r, err := tm.submitMessage(ctx, &miner14.PreCommitSectorBatchParams2{
|
||||
Sectors: []miner14.SectorPreCommitInfo{{
|
||||
Expiration: 2880 * 300,
|
||||
SectorNumber: sectorNumber,
|
||||
SealProof: TestSpt,
|
||||
SealedCID: tm.sealedCids[sectorNumber],
|
||||
SealRandEpoch: preCommitSealRand,
|
||||
}},
|
||||
}, 1, builtin.MethodsMiner.PreCommitSectorBatch2)
|
||||
req.NoError(err)
|
||||
req.True(r.Receipt.ExitCode.IsSuccess())
|
||||
// Generate a ProveCommit for the CC sector
|
||||
var seedRandomness abi.InteractiveSealRandomness
|
||||
seedEpoch, seedRandomness = tm.proveCommitWaitSeed(ctx, sectorNumber, proofType)
|
||||
|
||||
// Step 5: Generate a ProveCommit for the CC sector
|
||||
waitSeedRandomness := tm.proveCommitWaitSeed(ctx, sectorNumber)
|
||||
|
||||
proveCommit := []byte{0xde, 0xad, 0xbe, 0xef} // mock prove commit
|
||||
proveCommit = []byte{0xde, 0xad, 0xbe, 0xef} // mock prove commit
|
||||
if !tm.mockProofs {
|
||||
proveCommit = tm.generateProveCommit(ctx, sectorNumber, proofType, waitSeedRandomness, []abi.PieceInfo{})
|
||||
proveCommit = tm.generateProveCommit(ctx, sectorNumber, proofType, seedRandomness, pieces)
|
||||
}
|
||||
|
||||
return seedEpoch, proveCommit
|
||||
}
|
||||
|
||||
func (tm *TestUnmanagedMiner) SubmitProveCommit(
|
||||
ctx context.Context,
|
||||
proofType abi.RegisteredSealProof,
|
||||
sectorNumber abi.SectorNumber,
|
||||
seedEpoch abi.ChainEpoch,
|
||||
proveCommit []byte,
|
||||
pieceManifest []miner14.PieceActivationManifest,
|
||||
) {
|
||||
|
||||
req := require.New(tm.t)
|
||||
|
||||
if proofType.IsNonInteractive() {
|
||||
req.Nil(pieceManifest, "piece manifest should be nil for Non-interactive PoRep")
|
||||
}
|
||||
|
||||
// Step 6: Submit the ProveCommit to the network
|
||||
tm.t.Log("Submitting ProveCommitSector ...")
|
||||
if proofType.IsNonInteractive() {
|
||||
tm.t.Log("Submitting ProveCommitSector ...")
|
||||
|
||||
r, err = tm.submitMessage(ctx, &miner14.ProveCommitSectors3Params{
|
||||
SectorActivations: []miner14.SectorActivationManifest{{SectorNumber: sectorNumber}},
|
||||
SectorProofs: [][]byte{proveCommit},
|
||||
RequireActivationSuccess: true,
|
||||
}, 0, builtin.MethodsMiner.ProveCommitSectors3)
|
||||
req.NoError(err)
|
||||
req.True(r.Receipt.ExitCode.IsSuccess())
|
||||
var provingDeadline uint64 = 7
|
||||
if tm.IsUmmutableDeadline(ctx, provingDeadline) {
|
||||
// avoid immutable deadlines
|
||||
provingDeadline = 5
|
||||
}
|
||||
|
||||
actorIdNum, err := address.IDFromAddress(tm.ActorAddr)
|
||||
req.NoError(err)
|
||||
actorId := abi.ActorID(actorIdNum)
|
||||
|
||||
r, err := tm.SubmitMessage(ctx, &miner14.ProveCommitSectorsNIParams{
|
||||
Sectors: []miner14.SectorNIActivationInfo{{
|
||||
SealingNumber: sectorNumber,
|
||||
SealerID: actorId,
|
||||
SealedCID: tm.sealedCids[sectorNumber],
|
||||
SectorNumber: sectorNumber,
|
||||
SealRandEpoch: seedEpoch,
|
||||
Expiration: 2880 * 300,
|
||||
}},
|
||||
AggregateProof: proveCommit,
|
||||
SealProofType: proofType,
|
||||
AggregateProofType: abi.RegisteredAggregationProof_SnarkPackV2,
|
||||
ProvingDeadline: provingDeadline,
|
||||
RequireActivationSuccess: true,
|
||||
}, 1, builtin.MethodsMiner.ProveCommitSectorsNI)
|
||||
req.NoError(err)
|
||||
req.True(r.Receipt.ExitCode.IsSuccess())
|
||||
|
||||
// NI-PoRep lets us determine the deadline, so we can check that it's set correctly
|
||||
sp, err := tm.FullNode.StateSectorPartition(ctx, tm.ActorAddr, sectorNumber, r.TipSet)
|
||||
req.NoError(err)
|
||||
req.Equal(provingDeadline, sp.Deadline)
|
||||
} else {
|
||||
tm.t.Log("Submitting ProveCommitSector ...")
|
||||
|
||||
r, err := tm.SubmitMessage(ctx, &miner14.ProveCommitSectors3Params{
|
||||
SectorActivations: []miner14.SectorActivationManifest{{SectorNumber: sectorNumber, Pieces: pieceManifest}},
|
||||
SectorProofs: [][]byte{proveCommit},
|
||||
RequireActivationSuccess: true,
|
||||
}, 0, builtin.MethodsMiner.ProveCommitSectors3)
|
||||
req.NoError(err)
|
||||
req.True(r.Receipt.ExitCode.IsSuccess())
|
||||
}
|
||||
}
|
||||
|
||||
func (tm *TestUnmanagedMiner) OnboardCCSector(ctx context.Context, proofType abi.RegisteredSealProof) (abi.SectorNumber, chan WindowPostResp, context.CancelFunc) {
|
||||
sectorNumber := tm.NextSectorNumber()
|
||||
|
||||
if !tm.mockProofs {
|
||||
// Write empty bytes that we want to seal i.e. create our CC sector
|
||||
tm.makeAndSaveCCSector(ctx, sectorNumber)
|
||||
}
|
||||
|
||||
seedEpoch, proveCommit := tm.PrepareSectorForProveCommit(ctx, proofType, sectorNumber, []abi.PieceInfo{})
|
||||
|
||||
tm.SubmitProveCommit(ctx, proofType, sectorNumber, seedEpoch, proveCommit, nil)
|
||||
|
||||
tm.proofType[sectorNumber] = proofType
|
||||
|
||||
respCh, cancelFn := tm.wdPostLoop(ctx, sectorNumber, tm.sealedCids[sectorNumber], tm.sealedSectorPaths[sectorNumber], tm.cacheDirPaths[sectorNumber])
|
||||
|
||||
return sectorNumber, respCh, cancelFn
|
||||
}
|
||||
|
||||
func (tm *TestUnmanagedMiner) OnboardSectorWithPieces(ctx context.Context, proofType abi.RegisteredSealProof) (abi.SectorNumber, chan WindowPostResp, context.CancelFunc) {
|
||||
sectorNumber := tm.NextSectorNumber()
|
||||
|
||||
// Build a sector with non 0 Pieces that we want to onboard
|
||||
var pieces []abi.PieceInfo
|
||||
if !tm.mockProofs {
|
||||
pieces = tm.mkAndSavePiecesToOnboard(ctx, sectorNumber, proofType)
|
||||
} else {
|
||||
pieces = []abi.PieceInfo{{
|
||||
Size: abi.PaddedPieceSize(tm.options.sectorSize),
|
||||
PieceCID: cid.MustParse("baga6ea4seaqjtovkwk4myyzj56eztkh5pzsk5upksan6f5outesy62bsvl4dsha"),
|
||||
}}
|
||||
}
|
||||
|
||||
_, proveCommit := tm.PrepareSectorForProveCommit(ctx, proofType, sectorNumber, pieces)
|
||||
|
||||
// Submit the ProveCommit to the network
|
||||
tm.t.Log("Submitting ProveCommitSector ...")
|
||||
|
||||
var manifest []miner14.PieceActivationManifest
|
||||
for _, piece := range pieces {
|
||||
manifest = append(manifest, miner14.PieceActivationManifest{
|
||||
CID: piece.PieceCID,
|
||||
Size: piece.Size,
|
||||
})
|
||||
}
|
||||
|
||||
tm.SubmitProveCommit(ctx, proofType, sectorNumber, 0, proveCommit, manifest)
|
||||
|
||||
tm.proofType[sectorNumber] = proofType
|
||||
respCh, cancelFn := tm.wdPostLoop(ctx, sectorNumber, tm.sealedCids[sectorNumber], tm.sealedSectorPaths[sectorNumber], tm.cacheDirPaths[sectorNumber])
|
||||
|
||||
return sectorNumber, respCh, cancelFn
|
||||
}
|
||||
|
||||
// calculateNextPostEpoch calculates the first epoch of the deadline proving window
|
||||
// that is desired for the given sector for the specified miner.
|
||||
// This function returns the current epoch and the calculated proving epoch.
|
||||
func (tm *TestUnmanagedMiner) calculateNextPostEpoch(
|
||||
ctx context.Context,
|
||||
sectorNumber abi.SectorNumber,
|
||||
) (abi.ChainEpoch, abi.ChainEpoch, error) {
|
||||
// Retrieve the current blockchain head
|
||||
head, err := tm.FullNode.ChainHead(ctx)
|
||||
if err != nil {
|
||||
return 0, 0, fmt.Errorf("failed to get chain head: %w", err)
|
||||
}
|
||||
|
||||
// Obtain the proving deadline information for the miner
|
||||
di, err := tm.FullNode.StateMinerProvingDeadline(ctx, tm.ActorAddr, head.Key())
|
||||
if err != nil {
|
||||
return 0, 0, fmt.Errorf("failed to get proving deadline: %w", err)
|
||||
}
|
||||
|
||||
tm.t.Logf("Miner %s: WindowPoST(%d): ProvingDeadline: %+v", tm.ActorAddr, sectorNumber, di)
|
||||
|
||||
// Fetch the sector partition for the given sector number
|
||||
sp, err := tm.FullNode.StateSectorPartition(ctx, tm.ActorAddr, sectorNumber, head.Key())
|
||||
if err != nil {
|
||||
return 0, 0, fmt.Errorf("failed to get sector partition: %w", err)
|
||||
}
|
||||
|
||||
tm.t.Logf("Miner %s: WindowPoST(%d): SectorPartition: %+v", tm.ActorAddr, sectorNumber, sp)
|
||||
|
||||
// Calculate the start of the period, adjusting if the current deadline has passed
|
||||
periodStart := di.PeriodStart
|
||||
// calculate current deadline index because it won't be reliable from state until the first
|
||||
// challenge window cron tick after first sector onboarded
|
||||
currentDeadlineIdx := uint64(math.Abs(float64((di.CurrentEpoch - di.PeriodStart) / di.WPoStChallengeWindow)))
|
||||
if di.PeriodStart < di.CurrentEpoch && sp.Deadline <= currentDeadlineIdx {
|
||||
// If the deadline has passed in the current proving period, calculate for the next period
|
||||
// Note that di.Open may be > di.CurrentEpoch if the miner has just been enrolled in cron so
|
||||
// their deadlines haven't started rolling yet
|
||||
periodStart += di.WPoStProvingPeriod
|
||||
}
|
||||
|
||||
// Calculate the exact epoch when proving should occur
|
||||
provingEpoch := periodStart + di.WPoStChallengeWindow*abi.ChainEpoch(sp.Deadline)
|
||||
|
||||
tm.t.Logf("Miner %s: WindowPoST(%d): next ProvingEpoch: %d", tm.ActorAddr, sectorNumber, provingEpoch)
|
||||
|
||||
return di.CurrentEpoch, provingEpoch, nil
|
||||
}
|
||||
|
||||
func (tm *TestUnmanagedMiner) wdPostLoop(
|
||||
pctx context.Context,
|
||||
sectorNumber abi.SectorNumber,
|
||||
@ -598,7 +699,7 @@ func (tm *TestUnmanagedMiner) SubmitPostDispute(ctx context.Context, sectorNumbe
|
||||
|
||||
tm.t.Logf("Miner %s: Sector %d - Disputing WindowedPoSt to confirm validity at epoch %d", tm.ActorAddr, sectorNumber, disputeEpoch)
|
||||
|
||||
_, err = tm.submitMessage(ctx, &miner14.DisputeWindowedPoStParams{
|
||||
_, err = tm.SubmitMessage(ctx, &miner14.DisputeWindowedPoStParams{
|
||||
Deadline: sp.Deadline,
|
||||
PoStIndex: 0,
|
||||
}, 1, builtin.MethodsMiner.DisputeWindowedPoSt)
|
||||
@ -651,7 +752,7 @@ func (tm *TestUnmanagedMiner) submitWindowPost(ctx context.Context, sectorNumber
|
||||
return fmt.Errorf("Miner(%s): failed to get miner info for sector %d: %w", tm.ActorAddr, sectorNumber, err)
|
||||
}
|
||||
|
||||
r, err := tm.submitMessage(ctx, &miner14.SubmitWindowedPoStParams{
|
||||
r, err := tm.SubmitMessage(ctx, &miner14.SubmitWindowedPoStParams{
|
||||
ChainCommitEpoch: chainRandomnessEpoch,
|
||||
ChainCommitRand: chainRandomness,
|
||||
Deadline: sp.Deadline,
|
||||
@ -754,12 +855,16 @@ func (tm *TestUnmanagedMiner) generateWindowPost(
|
||||
|
||||
return proofBytes, nil
|
||||
}
|
||||
func (tm *TestUnmanagedMiner) waitPreCommitSealRandomness(ctx context.Context, sectorNumber abi.SectorNumber) abi.ChainEpoch {
|
||||
func (tm *TestUnmanagedMiner) waitPreCommitSealRandomness(ctx context.Context, sectorNumber abi.SectorNumber, proofType abi.RegisteredSealProof) abi.ChainEpoch {
|
||||
// We want to draw seal randomness from a tipset that has already achieved finality as PreCommits are expensive to re-generate.
|
||||
// Check if we already have an epoch that is already final and wait for such an epoch if we don't have one.
|
||||
head, err := tm.FullNode.ChainHead(ctx)
|
||||
require.NoError(tm.t, err)
|
||||
|
||||
if proofType.IsNonInteractive() {
|
||||
return head.Height() - 1 // no need to wait
|
||||
}
|
||||
|
||||
var sealRandEpoch abi.ChainEpoch
|
||||
if head.Height() > policy.SealRandomnessLookback {
|
||||
sealRandEpoch = head.Height() - policy.SealRandomnessLookback
|
||||
@ -775,53 +880,6 @@ func (tm *TestUnmanagedMiner) waitPreCommitSealRandomness(ctx context.Context, s
|
||||
return sealRandEpoch
|
||||
}
|
||||
|
||||
// calculateNextPostEpoch calculates the first epoch of the deadline proving window
|
||||
// that is desired for the given sector for the specified miner.
|
||||
// This function returns the current epoch and the calculated proving epoch.
|
||||
func (tm *TestUnmanagedMiner) calculateNextPostEpoch(
|
||||
ctx context.Context,
|
||||
sectorNumber abi.SectorNumber,
|
||||
) (abi.ChainEpoch, abi.ChainEpoch, error) {
|
||||
// Retrieve the current blockchain head
|
||||
head, err := tm.FullNode.ChainHead(ctx)
|
||||
if err != nil {
|
||||
return 0, 0, fmt.Errorf("failed to get chain head: %w", err)
|
||||
}
|
||||
|
||||
// Obtain the proving deadline information for the miner
|
||||
di, err := tm.FullNode.StateMinerProvingDeadline(ctx, tm.ActorAddr, head.Key())
|
||||
if err != nil {
|
||||
return 0, 0, fmt.Errorf("failed to get proving deadline: %w", err)
|
||||
}
|
||||
|
||||
tm.t.Logf("Miner %s: WindowPoST(%d): ProvingDeadline: %+v", tm.ActorAddr, sectorNumber, di)
|
||||
|
||||
// Fetch the sector partition for the given sector number
|
||||
sp, err := tm.FullNode.StateSectorPartition(ctx, tm.ActorAddr, sectorNumber, head.Key())
|
||||
if err != nil {
|
||||
return 0, 0, fmt.Errorf("failed to get sector partition: %w", err)
|
||||
}
|
||||
|
||||
tm.t.Logf("Miner %s: WindowPoST(%d): SectorPartition: %+v", tm.ActorAddr, sectorNumber, sp)
|
||||
|
||||
// Calculate the start of the period, adjusting if the current deadline has passed
|
||||
periodStart := di.PeriodStart
|
||||
// calculate current deadline index because it won't be reliable from state until the first
|
||||
// challenge window cron tick after first sector onboarded
|
||||
curIdx := (di.CurrentEpoch - di.PeriodStart) / di.WPoStChallengeWindow
|
||||
if di.PeriodStart < di.CurrentEpoch && sp.Deadline <= uint64(curIdx) {
|
||||
// If the deadline has passed in the current proving period, calculate for the next period
|
||||
periodStart += di.WPoStProvingPeriod
|
||||
}
|
||||
|
||||
// Calculate the exact epoch when proving should occur
|
||||
provingEpoch := periodStart + di.WPoStChallengeWindow*abi.ChainEpoch(sp.Deadline)
|
||||
|
||||
tm.t.Logf("Miner %s: WindowPoST(%d): next ProvingEpoch: %d", tm.ActorAddr, sectorNumber, provingEpoch)
|
||||
|
||||
return di.CurrentEpoch, provingEpoch, nil
|
||||
}
|
||||
|
||||
func (tm *TestUnmanagedMiner) generatePreCommit(
|
||||
ctx context.Context,
|
||||
sectorNumber abi.SectorNumber,
|
||||
@ -829,6 +887,15 @@ func (tm *TestUnmanagedMiner) generatePreCommit(
|
||||
proofType abi.RegisteredSealProof,
|
||||
pieceInfo []abi.PieceInfo,
|
||||
) {
|
||||
|
||||
if tm.mockProofs {
|
||||
tm.sealedCids[sectorNumber] = cid.MustParse("bagboea4b5abcatlxechwbp7kjpjguna6r6q7ejrhe6mdp3lf34pmswn27pkkiekz")
|
||||
if len(pieceInfo) > 0 {
|
||||
tm.unsealedCids[sectorNumber] = cid.MustParse("baga6ea4seaqjtovkwk4myyzj56eztkh5pzsk5upksan6f5outesy62bsvl4dsha")
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
req := require.New(tm.t)
|
||||
tm.t.Logf("Miner %s: Generating proof type %d PreCommit for sector %d...", tm.ActorAddr, proofType, sectorNumber)
|
||||
|
||||
@ -878,41 +945,48 @@ func (tm *TestUnmanagedMiner) generatePreCommit(
|
||||
tm.unsealedCids[sectorNumber] = unsealedCid
|
||||
}
|
||||
|
||||
func (tm *TestUnmanagedMiner) proveCommitWaitSeed(ctx context.Context, sectorNumber abi.SectorNumber) abi.InteractiveSealRandomness {
|
||||
func (tm *TestUnmanagedMiner) proveCommitWaitSeed(ctx context.Context, sectorNumber abi.SectorNumber, proofType abi.RegisteredSealProof) (abi.ChainEpoch, abi.InteractiveSealRandomness) {
|
||||
req := require.New(tm.t)
|
||||
head, err := tm.FullNode.ChainHead(ctx)
|
||||
req.NoError(err)
|
||||
|
||||
tm.t.Logf("Miner %s: Fetching pre-commit info for sector %d...", tm.ActorAddr, sectorNumber)
|
||||
preCommitInfo, err := tm.FullNode.StateSectorPreCommitInfo(ctx, tm.ActorAddr, sectorNumber, head.Key())
|
||||
req.NoError(err)
|
||||
seedRandomnessHeight := preCommitInfo.PreCommitEpoch + policy.GetPreCommitChallengeDelay()
|
||||
var seedRandomnessHeight abi.ChainEpoch
|
||||
|
||||
tm.t.Logf("Miner %s: Waiting %d epochs for seed randomness at epoch %d (current epoch %d) for sector %d...", tm.ActorAddr, seedRandomnessHeight-head.Height(), seedRandomnessHeight, head.Height(), sectorNumber)
|
||||
tm.FullNode.WaitTillChain(ctx, HeightAtLeast(seedRandomnessHeight+5))
|
||||
if proofType.IsNonInteractive() {
|
||||
seedRandomnessHeight = head.Height() - 1 // no need to wait, it just can't be current epoch
|
||||
} else {
|
||||
tm.t.Logf("Miner %s: Fetching pre-commit info for sector %d...", tm.ActorAddr, sectorNumber)
|
||||
preCommitInfo, err := tm.FullNode.StateSectorPreCommitInfo(ctx, tm.ActorAddr, sectorNumber, head.Key())
|
||||
req.NoError(err)
|
||||
seedRandomnessHeight = preCommitInfo.PreCommitEpoch + policy.GetPreCommitChallengeDelay()
|
||||
|
||||
tm.t.Logf("Miner %s: Waiting %d epochs for seed randomness at epoch %d (current epoch %d) for sector %d...", tm.ActorAddr, seedRandomnessHeight-head.Height(), seedRandomnessHeight, head.Height(), sectorNumber)
|
||||
tm.FullNode.WaitTillChain(ctx, HeightAtLeast(seedRandomnessHeight+5))
|
||||
|
||||
head, err = tm.FullNode.ChainHead(ctx)
|
||||
req.NoError(err)
|
||||
}
|
||||
|
||||
minerAddrBytes := new(bytes.Buffer)
|
||||
req.NoError(tm.ActorAddr.MarshalCBOR(minerAddrBytes))
|
||||
|
||||
head, err = tm.FullNode.ChainHead(ctx)
|
||||
req.NoError(err)
|
||||
|
||||
tm.t.Logf("Miner %s: Fetching seed randomness for sector %d...", tm.ActorAddr, sectorNumber)
|
||||
rand, err := tm.FullNode.StateGetRandomnessFromBeacon(ctx, crypto.DomainSeparationTag_InteractiveSealChallengeSeed, seedRandomnessHeight, minerAddrBytes.Bytes(), head.Key())
|
||||
req.NoError(err)
|
||||
seedRandomness := abi.InteractiveSealRandomness(rand)
|
||||
|
||||
tm.t.Logf("Miner %s: Obtained seed randomness for sector %d: %x", tm.ActorAddr, sectorNumber, seedRandomness)
|
||||
return seedRandomness
|
||||
return seedRandomnessHeight, seedRandomness
|
||||
}
|
||||
|
||||
func (tm *TestUnmanagedMiner) generateProveCommit(
|
||||
ctx context.Context,
|
||||
_ context.Context,
|
||||
sectorNumber abi.SectorNumber,
|
||||
proofType abi.RegisteredSealProof,
|
||||
seedRandomness abi.InteractiveSealRandomness,
|
||||
pieces []abi.PieceInfo,
|
||||
) []byte {
|
||||
|
||||
tm.t.Logf("Miner %s: Generating proof type %d Sector Proof for sector %d...", tm.ActorAddr, proofType, sectorNumber)
|
||||
req := require.New(tm.t)
|
||||
|
||||
@ -938,20 +1012,43 @@ func (tm *TestUnmanagedMiner) generateProveCommit(
|
||||
|
||||
tm.t.Logf("Miner %s: Running proof type %d SealCommitPhase2 for sector %d...", tm.ActorAddr, proofType, sectorNumber)
|
||||
|
||||
sectorProof, err := ffi.SealCommitPhase2(scp1, sectorNumber, actorId)
|
||||
req.NoError(err)
|
||||
var sectorProof []byte
|
||||
|
||||
if proofType.IsNonInteractive() {
|
||||
circuitProofs, err := ffi.SealCommitPhase2CircuitProofs(scp1, sectorNumber)
|
||||
req.NoError(err)
|
||||
asvpai := proof.AggregateSealVerifyProofAndInfos{
|
||||
Miner: actorId,
|
||||
SealProof: proofType,
|
||||
AggregateProof: abi.RegisteredAggregationProof_SnarkPackV2,
|
||||
Infos: []proof.AggregateSealVerifyInfo{{
|
||||
Number: sectorNumber,
|
||||
Randomness: tm.sealTickets[sectorNumber],
|
||||
InteractiveRandomness: make([]byte, 32),
|
||||
SealedCID: tm.sealedCids[sectorNumber],
|
||||
UnsealedCID: tm.unsealedCids[sectorNumber],
|
||||
}},
|
||||
}
|
||||
tm.t.Logf("Miner %s: Aggregating circuit proofs for sector %d: %+v", tm.ActorAddr, sectorNumber, asvpai)
|
||||
sectorProof, err = ffi.AggregateSealProofs(asvpai, [][]byte{circuitProofs})
|
||||
req.NoError(err)
|
||||
} else {
|
||||
sectorProof, err = ffi.SealCommitPhase2(scp1, sectorNumber, actorId)
|
||||
req.NoError(err)
|
||||
}
|
||||
|
||||
tm.t.Logf("Miner %s: Got proof type %d sector proof of length %d for sector %d", tm.ActorAddr, proofType, len(sectorProof), sectorNumber)
|
||||
|
||||
return sectorProof
|
||||
}
|
||||
|
||||
func (tm *TestUnmanagedMiner) submitMessage(
|
||||
func (tm *TestUnmanagedMiner) SubmitMessage(
|
||||
ctx context.Context,
|
||||
params cbg.CBORMarshaler,
|
||||
value uint64,
|
||||
method abi.MethodNum,
|
||||
) (*api.MsgLookup, error) {
|
||||
|
||||
enc, aerr := actors.SerializeParams(params)
|
||||
if aerr != nil {
|
||||
return nil, aerr
|
||||
@ -1034,14 +1131,10 @@ func (tm *TestUnmanagedMiner) WaitTillActivatedAndAssertPower(
|
||||
// Miner B should now have power
|
||||
tm.AssertPower(ctx, uint64(tm.options.sectorSize), uint64(tm.options.sectorSize))
|
||||
|
||||
if tm.mockProofs {
|
||||
// WindowPost Dispute should succeed as we are using mock proofs
|
||||
err := tm.SubmitPostDispute(ctx, sector)
|
||||
require.NoError(tm.t, err)
|
||||
} else {
|
||||
if !tm.mockProofs {
|
||||
// WindowPost Dispute should fail
|
||||
tm.AssertDisputeFails(ctx, sector)
|
||||
}
|
||||
} // else it would pass, which we don't want
|
||||
}
|
||||
|
||||
func (tm *TestUnmanagedMiner) AssertDisputeFails(ctx context.Context, sector abi.SectorNumber) {
|
||||
@ -1050,3 +1143,11 @@ func (tm *TestUnmanagedMiner) AssertDisputeFails(ctx context.Context, sector abi
|
||||
require.Contains(tm.t, err.Error(), "failed to dispute valid post")
|
||||
require.Contains(tm.t, err.Error(), "(RetCode=16)")
|
||||
}
|
||||
|
||||
func (tm *TestUnmanagedMiner) IsUmmutableDeadline(ctx context.Context, deadlineIndex uint64) bool {
|
||||
di, err := tm.FullNode.StateMinerProvingDeadline(ctx, tm.ActorAddr, types.EmptyTSK)
|
||||
require.NoError(tm.t, err)
|
||||
// don't rely on di.Index because if we haven't enrolled in cron it won't be ticking
|
||||
currentDeadline := uint64((di.CurrentEpoch - di.PeriodStart) / di.WPoStChallengeWindow)
|
||||
return currentDeadline == deadlineIndex || currentDeadline == deadlineIndex-1
|
||||
}
|
||||
|
@ -8,24 +8,28 @@ import (
|
||||
"github.com/stretchr/testify/require"
|
||||
|
||||
"github.com/filecoin-project/go-state-types/abi"
|
||||
"github.com/filecoin-project/go-state-types/network"
|
||||
|
||||
"github.com/filecoin-project/lotus/build"
|
||||
"github.com/filecoin-project/lotus/chain/actors/builtin/miner"
|
||||
"github.com/filecoin-project/lotus/itests/kit"
|
||||
)
|
||||
|
||||
// Manually onboard CC sectors, bypassing lotus-miner onboarding pathways
|
||||
func TestManualSectorOnboarding(t *testing.T) {
|
||||
const defaultSectorSize = abi.SectorSize(2 << 10) // 2KiB
|
||||
|
||||
req := require.New(t)
|
||||
|
||||
const defaultSectorSize = abi.SectorSize(2 << 10) // 2KiB
|
||||
sealProofType, err := miner.SealProofTypeFromSectorSize(defaultSectorSize, network.Version23, miner.SealProofVariant_Standard)
|
||||
req.NoError(err)
|
||||
|
||||
for _, withMockProofs := range []bool{true, false} {
|
||||
testName := "WithRealProofs"
|
||||
if withMockProofs {
|
||||
testName = "WithMockProofs"
|
||||
}
|
||||
t.Run(testName, func(t *testing.T) {
|
||||
if testName == "WithRealProofs" {
|
||||
if !withMockProofs {
|
||||
kit.Expensive(t)
|
||||
}
|
||||
kit.QuietMiningLogs()
|
||||
@ -85,7 +89,7 @@ func TestManualSectorOnboarding(t *testing.T) {
|
||||
var bRespCh chan kit.WindowPostResp
|
||||
var bWdPostCancelF context.CancelFunc
|
||||
|
||||
bSectorNum, bRespCh, bWdPostCancelF = minerB.OnboardCCSector(ctx, kit.TestSpt)
|
||||
bSectorNum, bRespCh, bWdPostCancelF = minerB.OnboardCCSector(ctx, sealProofType)
|
||||
// Miner B should still not have power as power can only be gained after sector is activated i.e. the first WindowPost is submitted for it
|
||||
minerB.AssertNoPower(ctx)
|
||||
// Ensure that the block miner checks for and waits for posts during the appropriate proving window from our new miner with a sector
|
||||
@ -106,13 +110,9 @@ func TestManualSectorOnboarding(t *testing.T) {
|
||||
minerC.WaitTillActivatedAndAssertPower(ctx, cRespCh, cSectorNum)
|
||||
|
||||
// Miner B has activated the CC sector -> upgrade it with snapdeals
|
||||
// Note: We can't activate a sector with mock proofs as the WdPost is successfully disputed and so no point
|
||||
// in snapping it as snapping is only for activated sectors
|
||||
if !withMockProofs {
|
||||
minerB.SnapDeal(ctx, kit.TestSpt, bSectorNum)
|
||||
// cancel the WdPost for the CC sector as the corresponding CommR is no longer valid
|
||||
bWdPostCancelF()
|
||||
}
|
||||
_ = minerB.SnapDeal(ctx, kit.TestSpt, bSectorNum)
|
||||
// cancel the WdPost for the CC sector as the corresponding CommR is no longer valid
|
||||
bWdPostCancelF()
|
||||
})
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user