Wire up faults in fPoSt
This commit is contained in:
parent
866715b7c4
commit
2e95a53679
@ -508,7 +508,7 @@ func (sma StorageMinerActor) SubmitFallbackPoSt(act *types.Actor, vmctx types.VM
|
|||||||
}
|
}
|
||||||
|
|
||||||
if ok, lerr := sectorbuilder.VerifyFallbackPost(vmctx.Context(), mi.SectorSize,
|
if ok, lerr := sectorbuilder.VerifyFallbackPost(vmctx.Context(), mi.SectorSize,
|
||||||
sectorbuilder.NewSortedPublicSectorInfo(sectorInfos), seed[:], params.Proof, candidates, proverID); !ok || lerr != nil {
|
sectorbuilder.NewSortedPublicSectorInfo(sectorInfos), seed[:], params.Proof, candidates, proverID, 0); !ok || lerr != nil { // TODO: FORK - set faults to len(faults)
|
||||||
if lerr != nil {
|
if lerr != nil {
|
||||||
// TODO: study PoST errors
|
// TODO: study PoST errors
|
||||||
return nil, aerrors.Absorb(lerr, 4, "PoST error")
|
return nil, aerrors.Absorb(lerr, 4, "PoST error")
|
||||||
@ -824,7 +824,7 @@ func (sma StorageMinerActor) DeclareFaults(act *types.Actor, vmctx types.VMConte
|
|||||||
self.LastFaultSubmission = vmctx.BlockHeight()
|
self.LastFaultSubmission = vmctx.BlockHeight()
|
||||||
|
|
||||||
nstate, aerr := vmctx.Storage().Put(self)
|
nstate, aerr := vmctx.Storage().Put(self)
|
||||||
if err != nil {
|
if err != nil { // TODO: FORK: should be aerr
|
||||||
return nil, aerr
|
return nil, aerr
|
||||||
}
|
}
|
||||||
if err := vmctx.Storage().Commit(oldstate, nstate); err != nil {
|
if err := vmctx.Storage().Commit(oldstate, nstate); err != nil {
|
||||||
|
@ -176,7 +176,7 @@ const sha256bits = 256
|
|||||||
|
|
||||||
func IsTicketWinner(partialTicket []byte, ssizeI uint64, snum uint64, totpow BigInt) bool {
|
func IsTicketWinner(partialTicket []byte, ssizeI uint64, snum uint64, totpow BigInt) bool {
|
||||||
ssize := NewInt(ssizeI)
|
ssize := NewInt(ssizeI)
|
||||||
ssampled := ElectionPostChallengeCount(snum)
|
ssampled := ElectionPostChallengeCount(snum, 0) // TODO: faults in epost?
|
||||||
/*
|
/*
|
||||||
Need to check that
|
Need to check that
|
||||||
(h(vrfout) + 1) / (max(h) + 1) <= e * sectorSize / totalPower
|
(h(vrfout) + 1) / (max(h) + 1) <= e * sectorSize / totalPower
|
||||||
@ -213,12 +213,12 @@ func IsTicketWinner(partialTicket []byte, ssizeI uint64, snum uint64, totpow Big
|
|||||||
return lhs.Cmp(rhs) < 0
|
return lhs.Cmp(rhs) < 0
|
||||||
}
|
}
|
||||||
|
|
||||||
func ElectionPostChallengeCount(sectors uint64) uint64 {
|
func ElectionPostChallengeCount(sectors uint64, faults int) uint64 {
|
||||||
if sectors == 0 {
|
if sectors == 0 {
|
||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
// ceil(sectors / build.SectorChallengeRatioDiv)
|
// ceil(sectors / build.SectorChallengeRatioDiv)
|
||||||
return (sectors-1)/build.SectorChallengeRatioDiv + 1
|
return (sectors-uint64(faults)-1)/build.SectorChallengeRatioDiv + 1
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *Ticket) Equals(ot *Ticket) bool {
|
func (t *Ticket) Equals(ot *Ticket) bool {
|
||||||
|
@ -423,7 +423,7 @@ func (c *wsConn) handleWsConn(ctx context.Context) {
|
|||||||
if !ok {
|
if !ok {
|
||||||
if c.incomingErr != nil {
|
if c.incomingErr != nil {
|
||||||
if !websocket.IsCloseError(c.incomingErr, websocket.CloseNormalClosure) {
|
if !websocket.IsCloseError(c.incomingErr, websocket.CloseNormalClosure) {
|
||||||
log.Warnw("websocket error", "error", c.incomingErr)
|
log.Debugw("websocket error", "error", c.incomingErr)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return // remote closed
|
return // remote closed
|
||||||
|
84
lib/sectorbuilder/scrub.go
Normal file
84
lib/sectorbuilder/scrub.go
Normal file
@ -0,0 +1,84 @@
|
|||||||
|
package sectorbuilder
|
||||||
|
|
||||||
|
import (
|
||||||
|
"io/ioutil"
|
||||||
|
"os"
|
||||||
|
"path/filepath"
|
||||||
|
|
||||||
|
sectorbuilder "github.com/filecoin-project/filecoin-ffi"
|
||||||
|
"golang.org/x/xerrors"
|
||||||
|
)
|
||||||
|
|
||||||
|
type Fault struct {
|
||||||
|
SectorID uint64
|
||||||
|
|
||||||
|
Err error
|
||||||
|
}
|
||||||
|
|
||||||
|
func (sb *SectorBuilder) Scrub(sectorSet sectorbuilder.SortedPublicSectorInfo) []*Fault {
|
||||||
|
var faults []*Fault
|
||||||
|
|
||||||
|
for _, sector := range sectorSet.Values() {
|
||||||
|
err := sb.checkSector(sector.SectorID)
|
||||||
|
if err != nil {
|
||||||
|
faults = append(faults, &Fault{SectorID: sector.SectorID, Err: err})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return faults
|
||||||
|
}
|
||||||
|
|
||||||
|
func (sb *SectorBuilder) checkSector(sectorID uint64) error {
|
||||||
|
cache, err := sb.sectorCacheDir(sectorID)
|
||||||
|
if err != nil {
|
||||||
|
return xerrors.Errorf("getting sector cache dir: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := assertFile(filepath.Join(cache, "p_aux"), 96, 96); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if err := assertFile(filepath.Join(cache, "sc-01-data-tree-r-last.dat"), (2*sb.ssize)-32, (2*sb.ssize)-32); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: better validate this
|
||||||
|
if err := assertFile(filepath.Join(cache, "t_aux"), 100, 32000); err != nil { // TODO: what should this actually be?
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
dent, err := ioutil.ReadDir(cache)
|
||||||
|
if err != nil {
|
||||||
|
return xerrors.Errorf("reading cache dir %s", cache)
|
||||||
|
}
|
||||||
|
if len(dent) != 3 {
|
||||||
|
return xerrors.Errorf("found %d files in %s, expected 3", len(dent), cache)
|
||||||
|
}
|
||||||
|
|
||||||
|
sealed, err := sb.SealedSectorPath(sectorID)
|
||||||
|
if err != nil {
|
||||||
|
return xerrors.Errorf("getting sealed sector path: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := assertFile(filepath.Join(sealed), sb.ssize, sb.ssize); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func assertFile(path string, minSz uint64, maxSz uint64) error {
|
||||||
|
st, err := os.Stat(path)
|
||||||
|
if err != nil {
|
||||||
|
return xerrors.Errorf("stat %s: %w", path, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if st.IsDir() {
|
||||||
|
return xerrors.Errorf("expected %s to be a regular file", path)
|
||||||
|
}
|
||||||
|
|
||||||
|
if uint64(st.Size()) < minSz || uint64(st.Size()) > maxSz {
|
||||||
|
return xerrors.Errorf("%s wasn't within size bounds, expected %d < f < %d, got %d", minSz, maxSz, st.Size())
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
@ -623,7 +623,7 @@ func (sb *SectorBuilder) ComputeElectionPoSt(sectorInfo SortedPublicSectorInfo,
|
|||||||
var cseed [CommLen]byte
|
var cseed [CommLen]byte
|
||||||
copy(cseed[:], challengeSeed)
|
copy(cseed[:], challengeSeed)
|
||||||
|
|
||||||
privsects, err := sb.pubSectorToPriv(sectorInfo)
|
privsects, err := sb.pubSectorToPriv(sectorInfo, nil) // TODO: faults
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@ -634,20 +634,29 @@ func (sb *SectorBuilder) ComputeElectionPoSt(sectorInfo SortedPublicSectorInfo,
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (sb *SectorBuilder) GenerateEPostCandidates(sectorInfo SortedPublicSectorInfo, challengeSeed [CommLen]byte, faults []uint64) ([]EPostCandidate, error) {
|
func (sb *SectorBuilder) GenerateEPostCandidates(sectorInfo SortedPublicSectorInfo, challengeSeed [CommLen]byte, faults []uint64) ([]EPostCandidate, error) {
|
||||||
privsectors, err := sb.pubSectorToPriv(sectorInfo)
|
privsectors, err := sb.pubSectorToPriv(sectorInfo, faults)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
challengeCount := types.ElectionPostChallengeCount(uint64(len(sectorInfo.Values())))
|
challengeCount := types.ElectionPostChallengeCount(uint64(len(sectorInfo.Values())), len(faults))
|
||||||
|
|
||||||
proverID := addressToProverID(sb.Miner)
|
proverID := addressToProverID(sb.Miner)
|
||||||
return sectorbuilder.GenerateCandidates(sb.ssize, proverID, challengeSeed, challengeCount, privsectors)
|
return sectorbuilder.GenerateCandidates(sb.ssize, proverID, challengeSeed, challengeCount, privsectors)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (sb *SectorBuilder) pubSectorToPriv(sectorInfo SortedPublicSectorInfo) (SortedPrivateSectorInfo, error) {
|
func (sb *SectorBuilder) pubSectorToPriv(sectorInfo SortedPublicSectorInfo, faults []uint64) (SortedPrivateSectorInfo, error) {
|
||||||
|
fmap := map[uint64]struct{}{}
|
||||||
|
for _, fault := range faults {
|
||||||
|
fmap[fault] = struct{}{}
|
||||||
|
}
|
||||||
|
|
||||||
var out []sectorbuilder.PrivateSectorInfo
|
var out []sectorbuilder.PrivateSectorInfo
|
||||||
for _, s := range sectorInfo.Values() {
|
for _, s := range sectorInfo.Values() {
|
||||||
|
if _, faulty := fmap[s.SectorID]; faulty {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
cachePath, err := sb.sectorCacheDir(s.SectorID)
|
cachePath, err := sb.sectorCacheDir(s.SectorID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return SortedPrivateSectorInfo{}, xerrors.Errorf("getting cache path for sector %d: %w", s.SectorID, err)
|
return SortedPrivateSectorInfo{}, xerrors.Errorf("getting cache path for sector %d: %w", s.SectorID, err)
|
||||||
@ -669,12 +678,12 @@ func (sb *SectorBuilder) pubSectorToPriv(sectorInfo SortedPublicSectorInfo) (Sor
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (sb *SectorBuilder) GenerateFallbackPoSt(sectorInfo SortedPublicSectorInfo, challengeSeed [CommLen]byte, faults []uint64) ([]EPostCandidate, []byte, error) {
|
func (sb *SectorBuilder) GenerateFallbackPoSt(sectorInfo SortedPublicSectorInfo, challengeSeed [CommLen]byte, faults []uint64) ([]EPostCandidate, []byte, error) {
|
||||||
privsectors, err := sb.pubSectorToPriv(sectorInfo)
|
privsectors, err := sb.pubSectorToPriv(sectorInfo, faults)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, nil, err
|
return nil, nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
challengeCount := fallbackPostChallengeCount(uint64(len(sectorInfo.Values())))
|
challengeCount := fallbackPostChallengeCount(uint64(len(sectorInfo.Values())), len(faults))
|
||||||
|
|
||||||
proverID := addressToProverID(sb.Miner)
|
proverID := addressToProverID(sb.Miner)
|
||||||
candidates, err := sectorbuilder.GenerateCandidates(sb.ssize, proverID, challengeSeed, challengeCount, privsectors)
|
candidates, err := sectorbuilder.GenerateCandidates(sb.ssize, proverID, challengeSeed, challengeCount, privsectors)
|
||||||
@ -690,8 +699,8 @@ func (sb *SectorBuilder) Stop() {
|
|||||||
close(sb.stopping)
|
close(sb.stopping)
|
||||||
}
|
}
|
||||||
|
|
||||||
func fallbackPostChallengeCount(sectors uint64) uint64 {
|
func fallbackPostChallengeCount(sectors uint64, faults int) uint64 {
|
||||||
challengeCount := types.ElectionPostChallengeCount(sectors)
|
challengeCount := types.ElectionPostChallengeCount(sectors, faults)
|
||||||
if challengeCount > build.MaxFallbackPostChallengeCount {
|
if challengeCount > build.MaxFallbackPostChallengeCount {
|
||||||
return build.MaxFallbackPostChallengeCount
|
return build.MaxFallbackPostChallengeCount
|
||||||
}
|
}
|
||||||
|
@ -37,12 +37,12 @@ func NewSortedPublicSectorInfo(sectors []sectorbuilder.PublicSectorInfo) SortedP
|
|||||||
}
|
}
|
||||||
|
|
||||||
func VerifyElectionPost(ctx context.Context, sectorSize uint64, sectorInfo SortedPublicSectorInfo, challengeSeed []byte, proof []byte, candidates []EPostCandidate, proverID address.Address) (bool, error) {
|
func VerifyElectionPost(ctx context.Context, sectorSize uint64, sectorInfo SortedPublicSectorInfo, challengeSeed []byte, proof []byte, candidates []EPostCandidate, proverID address.Address) (bool, error) {
|
||||||
challengeCount := types.ElectionPostChallengeCount(uint64(len(sectorInfo.Values())))
|
challengeCount := types.ElectionPostChallengeCount(uint64(len(sectorInfo.Values())), 0)
|
||||||
return verifyPost(ctx, sectorSize, sectorInfo, challengeCount, challengeSeed, proof, candidates, proverID)
|
return verifyPost(ctx, sectorSize, sectorInfo, challengeCount, challengeSeed, proof, candidates, proverID)
|
||||||
}
|
}
|
||||||
|
|
||||||
func VerifyFallbackPost(ctx context.Context, sectorSize uint64, sectorInfo SortedPublicSectorInfo, challengeSeed []byte, proof []byte, candidates []EPostCandidate, proverID address.Address) (bool, error) {
|
func VerifyFallbackPost(ctx context.Context, sectorSize uint64, sectorInfo SortedPublicSectorInfo, challengeSeed []byte, proof []byte, candidates []EPostCandidate, proverID address.Address, faults int) (bool, error) {
|
||||||
challengeCount := fallbackPostChallengeCount(uint64(len(sectorInfo.Values())))
|
challengeCount := fallbackPostChallengeCount(uint64(len(sectorInfo.Values())), faults)
|
||||||
return verifyPost(ctx, sectorSize, sectorInfo, challengeCount, challengeSeed, proof, candidates, proverID)
|
return verifyPost(ctx, sectorSize, sectorInfo, challengeCount, challengeSeed, proof, candidates, proverID)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -50,6 +50,57 @@ func (s *fpostScheduler) doPost(ctx context.Context, eps uint64, ts *types.TipSe
|
|||||||
}()
|
}()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (s *fpostScheduler) checkFaults(ctx context.Context, ssi sectorbuilder.SortedPublicSectorInfo) ([]uint64, error) {
|
||||||
|
faults := s.sb.Scrub(ssi)
|
||||||
|
var faultIDs []uint64
|
||||||
|
|
||||||
|
if len(faults) > 0 {
|
||||||
|
params := &actors.DeclareFaultsParams{Faults: types.NewBitField()}
|
||||||
|
|
||||||
|
for _, fault := range faults {
|
||||||
|
log.Warnf("fault detected: sector %d: %s", fault.SectorID, fault.Err)
|
||||||
|
faultIDs = append(faultIDs, fault.SectorID)
|
||||||
|
|
||||||
|
// TODO: omit already declared (with finality in mind though..)
|
||||||
|
params.Faults.Set(fault.SectorID)
|
||||||
|
}
|
||||||
|
|
||||||
|
log.Warnf("DECLARING %d FAULTS", len(faults))
|
||||||
|
|
||||||
|
enc, aerr := actors.SerializeParams(params)
|
||||||
|
if aerr != nil {
|
||||||
|
return nil, xerrors.Errorf("could not serialize declare faults parameters: %w", aerr)
|
||||||
|
}
|
||||||
|
|
||||||
|
msg := &types.Message{
|
||||||
|
To: s.actor,
|
||||||
|
From: s.worker,
|
||||||
|
Method: actors.MAMethods.DeclareFaults,
|
||||||
|
Params: enc,
|
||||||
|
Value: types.NewInt(0),
|
||||||
|
GasLimit: types.NewInt(10000000), // i dont know help
|
||||||
|
GasPrice: types.NewInt(1),
|
||||||
|
}
|
||||||
|
|
||||||
|
sm, err := s.api.MpoolPushMessage(ctx, msg)
|
||||||
|
if err != nil {
|
||||||
|
return nil, xerrors.Errorf("pushing faults message to mpool: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
rec, err := s.api.StateWaitMsg(ctx, sm.Cid())
|
||||||
|
if err != nil {
|
||||||
|
return nil, xerrors.Errorf("waiting for declare faults: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if rec.Receipt.ExitCode != 0 {
|
||||||
|
return nil, xerrors.Errorf("declare faults exit %d", rec.Receipt.ExitCode)
|
||||||
|
}
|
||||||
|
log.Infof("Faults declared successfully")
|
||||||
|
}
|
||||||
|
|
||||||
|
return faultIDs, nil
|
||||||
|
}
|
||||||
|
|
||||||
func (s *fpostScheduler) runPost(ctx context.Context, eps uint64, ts *types.TipSet) (*actors.SubmitFallbackPoStParams, error) {
|
func (s *fpostScheduler) runPost(ctx context.Context, eps uint64, ts *types.TipSet) (*actors.SubmitFallbackPoStParams, error) {
|
||||||
ctx, span := trace.StartSpan(ctx, "storage.runPost")
|
ctx, span := trace.StartSpan(ctx, "storage.runPost")
|
||||||
defer span.End()
|
defer span.End()
|
||||||
@ -68,8 +119,12 @@ func (s *fpostScheduler) runPost(ctx context.Context, eps uint64, ts *types.TipS
|
|||||||
|
|
||||||
log.Infow("running fPoSt", "chain-random", rand, "eps", eps, "height", ts.Height())
|
log.Infow("running fPoSt", "chain-random", rand, "eps", eps, "height", ts.Height())
|
||||||
|
|
||||||
|
faults, err := s.checkFaults(ctx, ssi)
|
||||||
|
if err != nil {
|
||||||
|
log.Errorf("Failed to declare faults: %+v", err)
|
||||||
|
}
|
||||||
|
|
||||||
tsStart := time.Now()
|
tsStart := time.Now()
|
||||||
var faults []uint64 // TODO
|
|
||||||
|
|
||||||
var seed [32]byte
|
var seed [32]byte
|
||||||
copy(seed[:], rand)
|
copy(seed[:], rand)
|
||||||
|
Loading…
Reference in New Issue
Block a user