lotus/itests/deadlines_test.go

331 lines
10 KiB
Go
Raw Normal View History

2022-08-29 14:25:30 +00:00
// stm: #integration
2021-05-17 12:28:09 +00:00
package itests
import (
"bytes"
"context"
"testing"
"time"
2022-06-14 15:00:51 +00:00
"github.com/ipfs/go-cid"
cbor "github.com/ipfs/go-ipld-cbor"
"github.com/stretchr/testify/require"
2022-04-20 21:34:28 +00:00
"github.com/filecoin-project/go-address"
"github.com/filecoin-project/go-bitfield"
"github.com/filecoin-project/go-state-types/abi"
"github.com/filecoin-project/go-state-types/big"
2022-06-14 15:00:51 +00:00
"github.com/filecoin-project/go-state-types/builtin"
minertypes "github.com/filecoin-project/go-state-types/builtin/v8/miner"
"github.com/filecoin-project/go-state-types/exitcode"
2022-06-14 15:00:51 +00:00
miner2 "github.com/filecoin-project/specs-actors/v2/actors/builtin/miner"
"github.com/filecoin-project/lotus/api"
"github.com/filecoin-project/lotus/blockstore"
"github.com/filecoin-project/lotus/build"
"github.com/filecoin-project/lotus/chain/actors"
"github.com/filecoin-project/lotus/chain/actors/adt"
"github.com/filecoin-project/lotus/chain/actors/builtin/miner"
"github.com/filecoin-project/lotus/chain/types"
2021-06-18 18:45:29 +00:00
"github.com/filecoin-project/lotus/itests/kit"
"github.com/filecoin-project/lotus/node/impl"
"github.com/filecoin-project/lotus/storage/sealer/mock"
)
// TestDeadlineToggling:
func TestDeadlineToggling(t *testing.T) {
2021-12-13 12:41:04 +00:00
//stm: @CHAIN_SYNCER_LOAD_GENESIS_001, @CHAIN_SYNCER_FETCH_TIPSET_001,
//stm: @CHAIN_SYNCER_START_001, @CHAIN_SYNCER_SYNC_001, @BLOCKCHAIN_BEACON_VALIDATE_BLOCK_VALUES_01
//stm: @CHAIN_SYNCER_COLLECT_CHAIN_001, @CHAIN_SYNCER_COLLECT_HEADERS_001, @CHAIN_SYNCER_VALIDATE_TIPSET_001
//stm: @CHAIN_SYNCER_NEW_PEER_HEAD_001, @CHAIN_SYNCER_VALIDATE_MESSAGE_META_001, @CHAIN_SYNCER_STOP_001
2021-12-14 10:33:33 +00:00
//stm: @CHAIN_INCOMING_HANDLE_INCOMING_BLOCKS_001, @CHAIN_INCOMING_VALIDATE_BLOCK_PUBSUB_001, @CHAIN_INCOMING_VALIDATE_MESSAGE_PUBSUB_001
2021-12-15 14:30:42 +00:00
//stm: @MINER_SECTOR_LIST_001
2022-09-21 23:39:00 +00:00
kit.Expensive(t)
2021-06-18 18:45:29 +00:00
kit.QuietMiningLogs()
const sectorsC, sectorsD, sectorsB = 10, 9, 8
var (
provingPeriod abi.ChainEpoch = 2880
blocktime = 2 * time.Millisecond
)
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
var (
2021-06-18 18:45:29 +00:00
client kit.TestFullNode
2023-09-21 15:37:02 +00:00
minerA kit.TestMiner // A has some genesis sector, just keeps power
minerB kit.TestMiner // B pledges some sector, later fails some posts but stays alive
minerC kit.TestMiner // C pledges sectors, gains power, and later stops its PoSTs, but stays alive
minerD kit.TestMiner // D pledges sectors and later terminates them, losing all power, eventually deactivates cron
minerE kit.TestMiner // E pre-commits a sector but doesn't advance beyond that, cron should become inactive
)
opts := []kit.NodeOpt{kit.WithAllSubsystems()}
2023-09-21 15:37:02 +00:00
ens := kit.NewEnsemble(t, kit.MockProofs()).
FullNode(&client, opts...).
Miner(&minerA, &client, opts...).
Start().
InterconnectAll()
ens.BeginMining(blocktime)
2021-06-18 18:45:29 +00:00
opts = append(opts, kit.OwnerAddr(client.DefaultKey))
ens.Miner(&minerB, &client, opts...).
Miner(&minerC, &client, opts...).
Start()
defaultFrom, err := client.WalletDefaultAddress(ctx)
require.NoError(t, err)
maddrA, err := minerA.ActorAddress(ctx)
require.NoError(t, err)
build.Clock.Sleep(time.Second)
maddrB, err := minerB.ActorAddress(ctx)
require.NoError(t, err)
maddrC, err := minerC.ActorAddress(ctx)
require.NoError(t, err)
ssz, err := minerC.ActorSectorSize(ctx, maddrC)
require.NoError(t, err)
2023-09-21 15:37:02 +00:00
targetHeight := abi.ChainEpoch(0)
// pledge sectors on C, go through a PP, check for power
{
minerC.PledgeSectors(ctx, sectorsC, 0, nil)
2021-12-10 15:08:25 +00:00
//stm: @CHAIN_STATE_MINER_CALCULATE_DEADLINE_001
di, err := client.StateMinerProvingDeadline(ctx, maddrC, types.EmptyTSK)
require.NoError(t, err)
t.Log("Running one proving period (miner C)")
t.Logf("End for head.Height > %d", di.PeriodStart+di.WPoStProvingPeriod*2)
2023-09-21 15:37:02 +00:00
targetHeight = di.PeriodStart + provingPeriod*2
for {
head, err := client.ChainHead(ctx)
require.NoError(t, err)
2023-09-21 15:37:02 +00:00
if head.Height() > targetHeight {
t.Logf("Now head.Height = %d", head.Height())
break
}
build.Clock.Sleep(blocktime)
}
expectedPower := types.NewInt(uint64(ssz) * sectorsC)
2021-12-10 15:08:25 +00:00
//stm: @CHAIN_STATE_MINER_POWER_001
p, err := client.StateMinerPower(ctx, maddrC, types.EmptyTSK)
require.NoError(t, err)
// make sure it has gained power.
require.Equal(t, p.MinerPower.RawBytePower, expectedPower)
}
2022-09-21 23:39:00 +00:00
checkMiner := func(ma address.Address, power abi.StoragePower, active bool, tsk types.TipSetKey) {
2021-12-10 15:08:25 +00:00
//stm: @CHAIN_STATE_MINER_POWER_001
p, err := client.StateMinerPower(ctx, ma, tsk)
require.NoError(t, err)
// make sure it has the expected power.
require.Equal(t, p.MinerPower.RawBytePower, power)
2021-12-10 15:08:25 +00:00
//stm: @CHAIN_STATE_GET_ACTOR_001
mact, err := client.StateGetActor(ctx, ma, tsk)
require.NoError(t, err)
mst, err := miner.Load(adt.WrapStore(ctx, cbor.NewCborStore(blockstore.NewAPIBlockstore(client))), mact)
require.NoError(t, err)
act, err := mst.DeadlineCronActive()
require.NoError(t, err)
2021-06-03 15:04:45 +00:00
require.Equal(t, active, act)
}
ens.Miner(&minerD, &client, opts...).
Miner(&minerE, &client, opts...).
Start()
maddrD, err := minerD.ActorAddress(ctx)
require.NoError(t, err)
maddrE, err := minerE.ActorAddress(ctx)
require.NoError(t, err)
// first round of miner checks
2022-09-21 23:39:00 +00:00
checkMiner(maddrA, types.NewInt(uint64(ssz)*kit.DefaultPresealsPerBootstrapMiner), true, types.EmptyTSK)
checkMiner(maddrC, types.NewInt(uint64(ssz)*sectorsC), true, types.EmptyTSK)
2022-09-21 23:39:00 +00:00
checkMiner(maddrB, types.NewInt(0), false, types.EmptyTSK)
checkMiner(maddrD, types.NewInt(0), false, types.EmptyTSK)
checkMiner(maddrE, types.NewInt(0), false, types.EmptyTSK)
// pledge sectors on minerB/minerD, stop post on minerC
minerB.PledgeSectors(ctx, sectorsB, 0, nil)
2022-09-21 23:39:00 +00:00
checkMiner(maddrB, types.NewInt(0), true, types.EmptyTSK)
minerD.PledgeSectors(ctx, sectorsD, 0, nil)
2022-09-21 23:39:00 +00:00
checkMiner(maddrD, types.NewInt(0), true, types.EmptyTSK)
minerC.StorageMiner.(*impl.StorageMinerAPI).IStorageMgr.(*mock.SectorMgr).Fail()
// precommit a sector on minerE
{
head, err := client.ChainHead(ctx)
require.NoError(t, err)
cr, err := cid.Parse("bagboea4b5abcatlxechwbp7kjpjguna6r6q7ejrhe6mdp3lf34pmswn27pkkiekz")
require.NoError(t, err)
2022-04-20 21:34:28 +00:00
params := &minertypes.SectorPreCommitInfo{
Expiration: 2880 * 300,
SectorNumber: 22,
2021-06-18 18:45:29 +00:00
SealProof: kit.TestSpt,
SealedCID: cr,
SealRandEpoch: head.Height() - 200,
}
enc := new(bytes.Buffer)
require.NoError(t, params.MarshalCBOR(enc))
m, err := client.MpoolPushMessage(ctx, &types.Message{
To: maddrE,
From: defaultFrom,
Value: types.FromFil(1),
2022-04-20 21:34:28 +00:00
Method: builtin.MethodsMiner.PreCommitSector,
Params: enc.Bytes(),
}, nil)
require.NoError(t, err)
2021-12-10 15:08:25 +00:00
//stm: @CHAIN_STATE_WAIT_MSG_001
r, err := client.StateWaitMsg(ctx, m.Cid(), 2, api.LookbackNoLimit, true)
require.NoError(t, err)
require.Equal(t, exitcode.Ok, r.Receipt.ExitCode)
}
2023-09-21 15:37:02 +00:00
targetHeight = targetHeight + (provingPeriod / 2)
// go through 0.5 PP
for {
head, err := client.ChainHead(ctx)
require.NoError(t, err)
2023-09-21 15:37:02 +00:00
if head.Height() > targetHeight {
t.Logf("Now head.Height = %d", head.Height())
break
}
build.Clock.Sleep(blocktime)
}
2022-09-21 23:39:00 +00:00
checkMiner(maddrE, types.NewInt(0), true, types.EmptyTSK)
2023-09-21 15:37:02 +00:00
targetHeight = targetHeight + (provingPeriod/2)*5
// go through rest of the PP
for {
head, err := client.ChainHead(ctx)
require.NoError(t, err)
2023-09-21 15:37:02 +00:00
if head.Height() > targetHeight {
t.Logf("Now head.Height = %d", head.Height())
break
}
build.Clock.Sleep(blocktime)
}
// second round of miner checks
2022-09-21 23:39:00 +00:00
checkMiner(maddrA, types.NewInt(uint64(ssz)*kit.DefaultPresealsPerBootstrapMiner), true, types.EmptyTSK)
checkMiner(maddrC, types.NewInt(0), true, types.EmptyTSK)
checkMiner(maddrB, types.NewInt(uint64(ssz)*sectorsB), true, types.EmptyTSK)
checkMiner(maddrD, types.NewInt(uint64(ssz)*sectorsD), true, types.EmptyTSK)
2023-09-21 15:37:02 +00:00
// Note: in the older version of this test `active` would be set to false
// this is now true because the time to commit a precommit a sector has
// increased to 30 days. We could keep the original assert and increase the
// wait above to 30 days, but that makes the test take 14 minutes to run..
checkMiner(maddrE, types.NewInt(0), true, types.EmptyTSK)
// disable post on minerB
minerB.StorageMiner.(*impl.StorageMinerAPI).IStorageMgr.(*mock.SectorMgr).Fail()
// terminate sectors on minerD
{
var terminationDeclarationParams []miner2.TerminationDeclaration
secs, err := minerD.SectorsListNonGenesis(ctx)
require.NoError(t, err)
require.Len(t, secs, sectorsD)
for _, sectorNum := range secs {
sectorbit := bitfield.New()
sectorbit.Set(uint64(sectorNum))
2021-12-10 15:08:25 +00:00
//stm: @CHAIN_STATE_SECTOR_PARTITION_001
loca, err := client.StateSectorPartition(ctx, maddrD, sectorNum, types.EmptyTSK)
require.NoError(t, err)
para := miner2.TerminationDeclaration{
Deadline: loca.Deadline,
Partition: loca.Partition,
Sectors: sectorbit,
}
terminationDeclarationParams = append(terminationDeclarationParams, para)
}
terminateSectorParams := &miner2.TerminateSectorsParams{
Terminations: terminationDeclarationParams,
}
sp, aerr := actors.SerializeParams(terminateSectorParams)
require.NoError(t, aerr)
smsg, err := client.MpoolPushMessage(ctx, &types.Message{
From: defaultFrom,
To: maddrD,
2022-04-20 21:34:28 +00:00
Method: builtin.MethodsMiner.TerminateSectors,
Value: big.Zero(),
Params: sp,
}, nil)
require.NoError(t, err)
t.Log("sent termination message:", smsg.Cid())
2021-12-10 15:08:25 +00:00
//stm: @CHAIN_STATE_WAIT_MSG_001
r, err := client.StateWaitMsg(ctx, smsg.Cid(), 2, api.LookbackNoLimit, true)
require.NoError(t, err)
require.Equal(t, exitcode.Ok, r.Receipt.ExitCode)
2022-09-21 23:39:00 +00:00
// assert miner has no power
p, err := client.StateMinerPower(ctx, maddrD, r.TipSet)
require.NoError(t, err)
require.True(t, p.MinerPower.RawBytePower.IsZero())
}
2023-09-21 15:37:02 +00:00
targetHeight = targetHeight + provingPeriod*2
// go through another PP
for {
head, err := client.ChainHead(ctx)
require.NoError(t, err)
2023-09-21 15:37:02 +00:00
if head.Height() > targetHeight {
t.Logf("Now head.Height = %d", head.Height())
break
}
build.Clock.Sleep(blocktime)
}
2022-09-21 23:39:00 +00:00
checkMiner(maddrA, types.NewInt(uint64(ssz)*kit.DefaultPresealsPerBootstrapMiner), true, types.EmptyTSK)
checkMiner(maddrC, types.NewInt(0), true, types.EmptyTSK)
checkMiner(maddrB, types.NewInt(0), true, types.EmptyTSK)
checkMiner(maddrD, types.NewInt(0), false, types.EmptyTSK)
}