Add a test for Window Post

This commit is contained in:
Łukasz Magiera 2020-06-01 14:49:48 +02:00
parent cd2bf04a6b
commit ee29a92021
5 changed files with 222 additions and 7 deletions

View File

@ -11,6 +11,7 @@ import (
"github.com/filecoin-project/sector-storage/stores" "github.com/filecoin-project/sector-storage/stores"
"github.com/filecoin-project/sector-storage/storiface" "github.com/filecoin-project/sector-storage/storiface"
"github.com/filecoin-project/specs-actors/actors/abi" "github.com/filecoin-project/specs-actors/actors/abi"
sealing "github.com/filecoin-project/storage-fsm"
"github.com/filecoin-project/lotus/chain/types" "github.com/filecoin-project/lotus/chain/types"
) )
@ -119,4 +120,4 @@ func (st *SealSeed) Equals(ost *SealSeed) bool {
return bytes.Equal(st.Value, ost.Value) && st.Epoch == ost.Epoch return bytes.Equal(st.Value, ost.Value) && st.Epoch == ost.Epoch
} }
type SectorState string type SectorState = sealing.SectorState

View File

@ -20,6 +20,7 @@ type TestStorageNode struct {
} }
var PresealGenesis = -1 var PresealGenesis = -1
const GenesisPreseals = 2
type StorageMiner struct { type StorageMiner struct {
Full int Full int

168
api/test/window_post.go Normal file
View File

@ -0,0 +1,168 @@
package test
import (
"context"
"fmt"
"os"
"strings"
"testing"
"time"
"github.com/stretchr/testify/require"
"github.com/filecoin-project/specs-actors/actors/abi"
miner2 "github.com/filecoin-project/specs-actors/actors/builtin/miner"
sealing "github.com/filecoin-project/storage-fsm"
"github.com/filecoin-project/lotus/chain/types"
"github.com/filecoin-project/lotus/node/impl"
)
func TestPledgeSector(t *testing.T, b APIBuilder, blocktime time.Duration, nSectors int) {
os.Setenv("BELLMAN_NO_GPU", "1")
ctx := context.Background()
n, sn := b(t, 1, oneMiner)
client := n[0].FullNode.(*impl.FullNodeAPI)
miner := sn[0]
addrinfo, err := client.NetAddrsListen(ctx)
if err != nil {
t.Fatal(err)
}
if err := miner.NetConnect(ctx, addrinfo); err != nil {
t.Fatal(err)
}
time.Sleep(time.Second)
mine := true
done := make(chan struct{})
go func() {
defer close(done)
for mine {
time.Sleep(blocktime)
if err := sn[0].MineOne(ctx, func(bool) {}); err != nil {
t.Error(err)
}
}
}()
pledgeSectors(t, ctx, miner, nSectors)
mine = false
<-done
}
func pledgeSectors(t *testing.T, ctx context.Context, miner TestStorageNode, n int) {
for i := 0; i < n; i++ {
err := miner.PledgeSector(ctx)
require.NoError(t, err)
}
for {
s, err := miner.SectorsList(ctx) // Note - the test builder doesn't import genesis sectors into FSM
require.NoError(t, err)
fmt.Printf("Sectors: %d\n", len(s))
if len(s) >= n {
break
}
time.Sleep(100 * time.Millisecond)
}
fmt.Printf("All sectors is fsm\n")
s, err := miner.SectorsList(ctx)
require.NoError(t, err)
toCheck := map[abi.SectorNumber]struct{}{}
for _, number := range s {
toCheck[number] = struct{}{}
}
for len(toCheck) > 0 {
for n := range toCheck {
st, err := miner.SectorsStatus(ctx, n)
require.NoError(t, err)
if st.State == sealing.Proving {
delete(toCheck, n)
}
if strings.Contains(string(st.State), "Fail") {
t.Fatal("sector in a failed state", st.State)
}
}
time.Sleep(100 * time.Millisecond)
fmt.Printf("WaitSeal: %d\n", len(s))
}
}
func TestWindowPost(t *testing.T, b APIBuilder, blocktime time.Duration, nSectors int) {
os.Setenv("BELLMAN_NO_GPU", "1")
ctx := context.Background()
n, sn := b(t, 1, oneMiner)
client := n[0].FullNode.(*impl.FullNodeAPI)
miner := sn[0]
addrinfo, err := client.NetAddrsListen(ctx)
if err != nil {
t.Fatal(err)
}
if err := miner.NetConnect(ctx, addrinfo); err != nil {
t.Fatal(err)
}
time.Sleep(time.Second)
mine := true
done := make(chan struct{})
go func() {
defer close(done)
for mine {
time.Sleep(blocktime)
if err := sn[0].MineOne(ctx, func(bool) {}); err != nil {
t.Error(err)
}
}
}()
pledgeSectors(t, ctx, miner, nSectors)
maddr, err := miner.ActorAddress(ctx)
require.NoError(t, err)
di, err := client.StateMinerProvingDeadline(ctx, maddr, types.EmptyTSK)
require.NoError(t, err)
fmt.Printf("Running one proving periods\n")
for {
head, err := client.ChainHead(ctx)
require.NoError(t, err)
if head.Height() > di.PeriodStart + (miner2.WPoStProvingPeriod) + 2 {
break
}
if head.Height() % 100 == 0 {
fmt.Printf("@%d\n", head.Height())
}
time.Sleep(blocktime)
}
p, err := client.StateMinerPower(ctx, maddr, types.EmptyTSK)
require.NoError(t, err)
ssz, err := miner.ActorSectorSize(ctx, maddr)
require.NoError(t, err)
require.Equal(t, p.MinerPower, p.TotalPower)
require.Equal(t, p.MinerPower.RawBytePower, types.NewInt(uint64(ssz) * uint64(nSectors + GenesisPreseals)))
// TODO: Inject faults here
mine = false
<-done
}

View File

@ -83,7 +83,7 @@ func testStorageNode(ctx context.Context, t *testing.T, waddr address.Address, a
require.NoError(t, err) require.NoError(t, err)
nic := storedcounter.New(ds, datastore.NewKey(modules.StorageCounterDSPrefix)) nic := storedcounter.New(ds, datastore.NewKey(modules.StorageCounterDSPrefix))
for i := 0; i < nGenesisPreseals; i++ { for i := 0; i < test.GenesisPreseals; i++ {
_, err := nic.Next() _, err := nic.Next()
require.NoError(t, err) require.NoError(t, err)
} }
@ -188,7 +188,7 @@ func builder(t *testing.T, nFull int, storage []test.StorageMiner) ([]test.TestN
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }
genm, k, err := seed.PreSeal(maddr, abi.RegisteredProof_StackedDRG2KiBPoSt, 0, nGenesisPreseals, tdir, []byte("make genesis mem random"), nil) genm, k, err := seed.PreSeal(maddr, abi.RegisteredProof_StackedDRG2KiBPoSt, 0, test.GenesisPreseals, tdir, []byte("make genesis mem random"), nil)
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }
@ -282,8 +282,6 @@ func builder(t *testing.T, nFull int, storage []test.StorageMiner) ([]test.TestN
return fulls, storers return fulls, storers
} }
const nGenesisPreseals = 2
func mockSbBuilder(t *testing.T, nFull int, storage []test.StorageMiner) ([]test.TestNode, []test.TestStorageNode) { func mockSbBuilder(t *testing.T, nFull int, storage []test.StorageMiner) ([]test.TestNode, []test.TestStorageNode) {
ctx := context.Background() ctx := context.Background()
mn := mocknet.New(ctx) mn := mocknet.New(ctx)
@ -314,7 +312,7 @@ func mockSbBuilder(t *testing.T, nFull int, storage []test.StorageMiner) ([]test
preseals := storage[i].Preseal preseals := storage[i].Preseal
if preseals == test.PresealGenesis { if preseals == test.PresealGenesis {
preseals = nGenesisPreseals preseals = test.GenesisPreseals
} }
genm, k, err := mockstorage.PreSeal(2048, maddr, preseals) genm, k, err := mockstorage.PreSeal(2048, maddr, preseals)
@ -350,7 +348,7 @@ func mockSbBuilder(t *testing.T, nFull int, storage []test.StorageMiner) ([]test
templ := &genesis.Template{ templ := &genesis.Template{
Accounts: genaccs, Accounts: genaccs,
Miners: genms, Miners: genms,
Timestamp: uint64(time.Now().Unix() - 10000), Timestamp: uint64(time.Now().Unix() - (build.BlockDelay * 20000)),
} }
// END PRESEAL SECTION // END PRESEAL SECTION
@ -493,3 +491,41 @@ func TestDealMining(t *testing.T) {
test.TestDealMining(t, mockSbBuilder, 50*time.Millisecond, false) test.TestDealMining(t, mockSbBuilder, 50*time.Millisecond, false)
} }
func TestPledgeSectors(t *testing.T) {
logging.SetLogLevel("miner", "ERROR")
logging.SetLogLevel("chainstore", "ERROR")
logging.SetLogLevel("chain", "ERROR")
logging.SetLogLevel("sub", "ERROR")
logging.SetLogLevel("storageminer", "ERROR")
t.Run("1", func(t *testing.T) {
test.TestPledgeSector(t, mockSbBuilder, 50*time.Millisecond, 1)
})
t.Run("100", func(t *testing.T) {
test.TestPledgeSector(t, mockSbBuilder, 50*time.Millisecond, 100)
})
t.Run("1000", func(t *testing.T) {
if testing.Short() { // takes ~16s
t.Skip("skipping test in short mode")
}
test.TestPledgeSector(t, mockSbBuilder, 50*time.Millisecond, 1000)
})
}
func TestWindowedPost(t *testing.T) {
if testing.Short() {
t.Skip("this takes a while")
}
logging.SetLogLevel("miner", "ERROR")
logging.SetLogLevel("chainstore", "ERROR")
logging.SetLogLevel("chain", "ERROR")
logging.SetLogLevel("sub", "ERROR")
logging.SetLogLevel("storageminer", "ERROR")
test.TestWindowPost(t, mockSbBuilder, 3*time.Millisecond, 10)
}

View File

@ -189,6 +189,15 @@ func (s *WindowPoStScheduler) checkNextRecoveries(ctx context.Context, deadline
} }
func (s *WindowPoStScheduler) checkNextFaults(ctx context.Context, deadline uint64, deadlineSectors *abi.BitField, ts *types.TipSet) error { func (s *WindowPoStScheduler) checkNextFaults(ctx context.Context, deadline uint64, deadlineSectors *abi.BitField, ts *types.TipSet) error {
dc, err := deadlineSectors.Count()
if err != nil {
return xerrors.Errorf("counting deadline sectors: %w", err)
}
if dc == 0 {
// nothing can become faulty
return nil
}
toCheck, err := s.getSectorsToProve(ctx, deadlineSectors, true, ts) toCheck, err := s.getSectorsToProve(ctx, deadlineSectors, true, ts)
if err != nil { if err != nil {
return xerrors.Errorf("getting next sectors to prove: %w", err) return xerrors.Errorf("getting next sectors to prove: %w", err)