github.com/filecoin-project/specs-actors/v4@v4.0.2/actors/builtin/miner/miner_test.go (about)

     1  // nolint:unused // 20200716 until tests are restored from miner state refactor
     2  package miner_test
     3  
     4  import (
     5  	"bytes"
     6  	"encoding/binary"
     7  	"fmt"
     8  	"strings"
     9  	"testing"
    10  
    11  	addr "github.com/filecoin-project/go-address"
    12  	bitfield "github.com/filecoin-project/go-bitfield"
    13  	"github.com/filecoin-project/go-state-types/abi"
    14  	"github.com/filecoin-project/go-state-types/big"
    15  	"github.com/filecoin-project/go-state-types/crypto"
    16  	"github.com/filecoin-project/go-state-types/dline"
    17  	"github.com/filecoin-project/go-state-types/exitcode"
    18  	"github.com/filecoin-project/go-state-types/network"
    19  	cid "github.com/ipfs/go-cid"
    20  	"github.com/minio/blake2b-simd"
    21  	"github.com/stretchr/testify/assert"
    22  	"github.com/stretchr/testify/require"
    23  	cbg "github.com/whyrusleeping/cbor-gen"
    24  
    25  	"github.com/filecoin-project/specs-actors/v4/actors/builtin"
    26  	"github.com/filecoin-project/specs-actors/v4/actors/builtin/market"
    27  	"github.com/filecoin-project/specs-actors/v4/actors/builtin/miner"
    28  	"github.com/filecoin-project/specs-actors/v4/actors/builtin/power"
    29  	"github.com/filecoin-project/specs-actors/v4/actors/builtin/reward"
    30  	"github.com/filecoin-project/specs-actors/v4/actors/runtime"
    31  	"github.com/filecoin-project/specs-actors/v4/actors/runtime/proof"
    32  	"github.com/filecoin-project/specs-actors/v4/actors/util/adt"
    33  	"github.com/filecoin-project/specs-actors/v4/actors/util/smoothing"
    34  	"github.com/filecoin-project/specs-actors/v4/support/mock"
    35  	tutil "github.com/filecoin-project/specs-actors/v4/support/testing"
    36  )
    37  
    38  var testPid abi.PeerID
    39  var testMultiaddrs []abi.Multiaddrs
    40  
    41  // A balance for use in tests where the miner's low balance is not interesting.
    42  var bigBalance = big.Mul(big.NewInt(1_000_000), big.NewInt(1e18))
    43  
    44  // A reward amount for use in tests where the vesting amount wants to be large enough to cover penalties.
    45  var bigRewards = big.Mul(big.NewInt(1_000), big.NewInt(1e18))
    46  
    47  // an expriration 1 greater than min expiration
    48  const defaultSectorExpiration = 190
    49  
    50  func init() {
    51  	testPid = abi.PeerID("peerID")
    52  
    53  	testMultiaddrs = []abi.Multiaddrs{
    54  		[]byte("foobar"),
    55  		[]byte("imafilminer"),
    56  	}
    57  
    58  	// permit 2KiB sectors in tests
    59  	miner.PreCommitSealProofTypesV8[abi.RegisteredSealProof_StackedDrg2KiBV1_1] = struct{}{}
    60  }
    61  
    62  func TestExports(t *testing.T) {
    63  	mock.CheckActorExports(t, miner.Actor{})
    64  }
    65  
    66  func TestConstruction(t *testing.T) {
    67  	actor := miner.Actor{}
    68  	owner := tutil.NewIDAddr(t, 100)
    69  	worker := tutil.NewIDAddr(t, 101)
    70  	workerKey := tutil.NewBLSAddr(t, 0)
    71  
    72  	controlAddrs := []addr.Address{tutil.NewIDAddr(t, 999), tutil.NewIDAddr(t, 998)}
    73  
    74  	receiver := tutil.NewIDAddr(t, 1000)
    75  	builder := mock.NewBuilder(receiver).
    76  		WithActorType(owner, builtin.AccountActorCodeID).
    77  		WithActorType(worker, builtin.AccountActorCodeID).
    78  		WithActorType(controlAddrs[0], builtin.AccountActorCodeID).
    79  		WithActorType(controlAddrs[1], builtin.AccountActorCodeID).
    80  		WithHasher(blake2b.Sum256).
    81  		WithCaller(builtin.InitActorAddr, builtin.InitActorCodeID)
    82  
    83  	t.Run("simple construction", func(t *testing.T) {
    84  		rt := builder.Build(t)
    85  		params := miner.ConstructorParams{
    86  			OwnerAddr:           owner,
    87  			WorkerAddr:          worker,
    88  			ControlAddrs:        controlAddrs,
    89  			WindowPoStProofType: abi.RegisteredPoStProof_StackedDrgWindow32GiBV1,
    90  			PeerId:              testPid,
    91  			Multiaddrs:          testMultiaddrs,
    92  		}
    93  
    94  		provingPeriodStart := abi.ChainEpoch(-2222) // This is just set from running the code.
    95  		rt.ExpectValidateCallerAddr(builtin.InitActorAddr)
    96  		// Fetch worker pubkey.
    97  		rt.ExpectSend(worker, builtin.MethodsAccount.PubkeyAddress, nil, big.Zero(), &workerKey, exitcode.Ok)
    98  		// Register proving period cron.
    99  		dlIdx := (rt.Epoch() - provingPeriodStart) / miner.WPoStChallengeWindow
   100  		ret := rt.Call(actor.Constructor, &params)
   101  
   102  		assert.Nil(t, ret)
   103  		rt.Verify()
   104  
   105  		var st miner.State
   106  		rt.GetState(&st)
   107  		info, err := st.GetInfo(adt.AsStore(rt))
   108  		require.NoError(t, err)
   109  		assert.Equal(t, params.OwnerAddr, info.Owner)
   110  		assert.Equal(t, params.WorkerAddr, info.Worker)
   111  		assert.Equal(t, params.ControlAddrs, info.ControlAddresses)
   112  		assert.Equal(t, params.PeerId, info.PeerId)
   113  		assert.Equal(t, params.Multiaddrs, info.Multiaddrs)
   114  		assert.Equal(t, abi.RegisteredPoStProof_StackedDrgWindow32GiBV1, info.WindowPoStProofType)
   115  		assert.Equal(t, abi.SectorSize(1<<35), info.SectorSize)
   116  		assert.Equal(t, uint64(2349), info.WindowPoStPartitionSectors)
   117  
   118  		assert.Equal(t, big.Zero(), st.PreCommitDeposits)
   119  		assert.Equal(t, big.Zero(), st.LockedFunds)
   120  		assert.True(t, st.PreCommittedSectors.Defined())
   121  
   122  		assert.True(t, st.Sectors.Defined())
   123  		assert.Equal(t, provingPeriodStart, st.ProvingPeriodStart)
   124  		assert.Equal(t, uint64(dlIdx), st.CurrentDeadline)
   125  
   126  		var deadlines miner.Deadlines
   127  		rt.StoreGet(st.Deadlines, &deadlines)
   128  		for i := uint64(0); i < miner.WPoStPeriodDeadlines; i++ {
   129  			var deadline miner.Deadline
   130  			rt.StoreGet(deadlines.Due[i], &deadline)
   131  			assert.True(t, deadline.Partitions.Defined())
   132  			assert.True(t, deadline.ExpirationsEpochs.Defined())
   133  			assertEmptyBitfield(t, deadline.PartitionsPoSted)
   134  			assertEmptyBitfield(t, deadline.EarlyTerminations)
   135  			assert.Equal(t, uint64(0), deadline.LiveSectors)
   136  		}
   137  
   138  		assertEmptyBitfield(t, st.EarlyTerminations)
   139  
   140  		_, msgs := miner.CheckStateInvariants(&st, rt.AdtStore(), rt.Balance())
   141  		assert.True(t, msgs.IsEmpty(), strings.Join(msgs.Messages(), "\n"))
   142  	})
   143  
   144  	t.Run("control addresses are resolved during construction", func(t *testing.T) {
   145  		control1 := tutil.NewBLSAddr(t, 501)
   146  		control1Id := tutil.NewIDAddr(t, 555)
   147  
   148  		control2 := tutil.NewBLSAddr(t, 502)
   149  		control2Id := tutil.NewIDAddr(t, 655)
   150  
   151  		rt := builder.WithActorType(control1Id, builtin.AccountActorCodeID).
   152  			WithActorType(control2Id, builtin.AccountActorCodeID).Build(t)
   153  		rt.AddIDAddress(control1, control1Id)
   154  		rt.AddIDAddress(control2, control2Id)
   155  
   156  		params := miner.ConstructorParams{
   157  			OwnerAddr:           owner,
   158  			WorkerAddr:          worker,
   159  			ControlAddrs:        []addr.Address{control1, control2},
   160  			WindowPoStProofType: abi.RegisteredPoStProof_StackedDrgWindow32GiBV1,
   161  		}
   162  
   163  		rt.ExpectValidateCallerAddr(builtin.InitActorAddr)
   164  		rt.ExpectSend(worker, builtin.MethodsAccount.PubkeyAddress, nil, big.Zero(), &workerKey, exitcode.Ok)
   165  		ret := rt.Call(actor.Constructor, &params)
   166  
   167  		assert.Nil(t, ret)
   168  		rt.Verify()
   169  
   170  		var st miner.State
   171  		rt.GetState(&st)
   172  		info, err := st.GetInfo(adt.AsStore(rt))
   173  		require.NoError(t, err)
   174  		assert.Equal(t, control1Id, info.ControlAddresses[0])
   175  		assert.Equal(t, control2Id, info.ControlAddresses[1])
   176  	})
   177  
   178  	t.Run("fails if control address is not an account actor", func(t *testing.T) {
   179  		control1 := tutil.NewIDAddr(t, 501)
   180  		rt := builder.Build(t)
   181  		rt.SetAddressActorType(control1, builtin.PaymentChannelActorCodeID)
   182  
   183  		params := miner.ConstructorParams{
   184  			OwnerAddr:           owner,
   185  			WorkerAddr:          worker,
   186  			ControlAddrs:        []addr.Address{control1},
   187  			WindowPoStProofType: abi.RegisteredPoStProof_StackedDrgWindow32GiBV1,
   188  		}
   189  
   190  		rt.ExpectValidateCallerAddr(builtin.InitActorAddr)
   191  		rt.ExpectSend(worker, builtin.MethodsAccount.PubkeyAddress, nil, big.Zero(), &workerKey, exitcode.Ok)
   192  
   193  		rt.ExpectAbort(exitcode.ErrIllegalArgument, func() {
   194  			rt.Call(actor.Constructor, &params)
   195  		})
   196  		rt.Verify()
   197  	})
   198  
   199  	t.Run("test construct with invalid peer ID", func(t *testing.T) {
   200  		rt := builder.Build(t)
   201  		pid := [miner.MaxPeerIDLength + 1]byte{1, 2, 3, 4}
   202  		params := miner.ConstructorParams{
   203  			OwnerAddr:           owner,
   204  			WorkerAddr:          worker,
   205  			WindowPoStProofType: abi.RegisteredPoStProof_StackedDrgWindow32GiBV1,
   206  			PeerId:              pid[:],
   207  			Multiaddrs:          testMultiaddrs,
   208  		}
   209  
   210  		rt.ExpectValidateCallerAddr(builtin.InitActorAddr)
   211  
   212  		rt.ExpectAbortContainsMessage(exitcode.ErrIllegalArgument, "peer ID size", func() {
   213  			rt.Call(actor.Constructor, &params)
   214  		})
   215  	})
   216  
   217  	t.Run("fails if control addresses exceeds maximum length", func(t *testing.T) {
   218  		rt := builder.Build(t)
   219  
   220  		controlAddrs := make([]addr.Address, 0, miner.MaxControlAddresses+1)
   221  		for i := 0; i <= miner.MaxControlAddresses; i++ {
   222  			controlAddrs = append(controlAddrs, tutil.NewIDAddr(t, uint64(i)))
   223  		}
   224  
   225  		params := miner.ConstructorParams{
   226  			OwnerAddr:           owner,
   227  			WorkerAddr:          worker,
   228  			WindowPoStProofType: abi.RegisteredPoStProof_StackedDrgWindow32GiBV1,
   229  			PeerId:              testPid,
   230  			ControlAddrs:        controlAddrs,
   231  		}
   232  
   233  		rt.ExpectValidateCallerAddr(builtin.InitActorAddr)
   234  
   235  		rt.ExpectAbortContainsMessage(exitcode.ErrIllegalArgument, "control addresses length", func() {
   236  			rt.Call(actor.Constructor, &params)
   237  		})
   238  	})
   239  
   240  	t.Run("test construct with large multiaddr", func(t *testing.T) {
   241  		rt := builder.Build(t)
   242  		maddrs := make([]abi.Multiaddrs, 100)
   243  		for i := range maddrs {
   244  			maddrs[i] = []byte{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11}
   245  		}
   246  		params := miner.ConstructorParams{
   247  			OwnerAddr:           owner,
   248  			WorkerAddr:          worker,
   249  			WindowPoStProofType: abi.RegisteredPoStProof_StackedDrgWindow32GiBV1,
   250  			PeerId:              testPid,
   251  			Multiaddrs:          maddrs,
   252  		}
   253  
   254  		rt.ExpectValidateCallerAddr(builtin.InitActorAddr)
   255  
   256  		rt.ExpectAbortContainsMessage(exitcode.ErrIllegalArgument, "multiaddr size", func() {
   257  			rt.Call(actor.Constructor, &params)
   258  		})
   259  	})
   260  
   261  	t.Run("test construct with empty multiaddr", func(t *testing.T) {
   262  		rt := builder.Build(t)
   263  		maddrs := []abi.Multiaddrs{
   264  			{},
   265  			{1},
   266  		}
   267  		params := miner.ConstructorParams{
   268  			OwnerAddr:           owner,
   269  			WorkerAddr:          worker,
   270  			WindowPoStProofType: abi.RegisteredPoStProof_StackedDrgWindow32GiBV1,
   271  			PeerId:              testPid,
   272  			Multiaddrs:          maddrs,
   273  		}
   274  
   275  		rt.ExpectValidateCallerAddr(builtin.InitActorAddr)
   276  
   277  		rt.ExpectAbortContainsMessage(exitcode.ErrIllegalArgument, "invalid empty multiaddr", func() {
   278  			rt.Call(actor.Constructor, &params)
   279  		})
   280  	})
   281  }
   282  
   283  // Test operations related to peer info (peer ID/multiaddrs)
   284  func TestPeerInfo(t *testing.T) {
   285  	h := newHarness(t, 0)
   286  	builder := builderForHarness(h)
   287  
   288  	t.Run("can set peer id", func(t *testing.T) {
   289  		rt := builder.Build(t)
   290  		h.constructAndVerify(rt)
   291  
   292  		h.setPeerID(rt, abi.PeerID("new peer id"))
   293  		h.checkState(rt)
   294  	})
   295  
   296  	t.Run("can clear peer id", func(t *testing.T) {
   297  		rt := builder.Build(t)
   298  		h.constructAndVerify(rt)
   299  
   300  		h.setPeerID(rt, nil)
   301  		h.checkState(rt)
   302  	})
   303  
   304  	t.Run("can't set large peer id", func(t *testing.T) {
   305  		rt := builder.Build(t)
   306  		h.constructAndVerify(rt)
   307  
   308  		largePid := [miner.MaxPeerIDLength + 1]byte{1, 2, 3}
   309  		rt.ExpectAbortContainsMessage(exitcode.ErrIllegalArgument, "peer ID size", func() {
   310  			h.setPeerID(rt, largePid[:])
   311  		})
   312  		h.checkState(rt)
   313  	})
   314  
   315  	t.Run("can set multiaddrs", func(t *testing.T) {
   316  		rt := builder.Build(t)
   317  		h.constructAndVerify(rt)
   318  
   319  		h.setMultiaddrs(rt, abi.Multiaddrs("imanewminer"))
   320  		h.checkState(rt)
   321  	})
   322  
   323  	t.Run("can set multiple multiaddrs", func(t *testing.T) {
   324  		rt := builder.Build(t)
   325  		h.constructAndVerify(rt)
   326  
   327  		h.setMultiaddrs(rt, abi.Multiaddrs("imanewminer"), abi.Multiaddrs("ihavemany"))
   328  		h.checkState(rt)
   329  	})
   330  
   331  	t.Run("can set clear the multiaddr", func(t *testing.T) {
   332  		rt := builder.Build(t)
   333  		h.constructAndVerify(rt)
   334  
   335  		h.setMultiaddrs(rt)
   336  		h.checkState(rt)
   337  	})
   338  
   339  	t.Run("can't set empty multiaddrs", func(t *testing.T) {
   340  		rt := builder.Build(t)
   341  		h.constructAndVerify(rt)
   342  
   343  		rt.ExpectAbortContainsMessage(exitcode.ErrIllegalArgument, "invalid empty multiaddr", func() {
   344  			h.setMultiaddrs(rt, nil)
   345  		})
   346  		h.checkState(rt)
   347  	})
   348  
   349  	t.Run("can't set large multiaddrs", func(t *testing.T) {
   350  		rt := builder.Build(t)
   351  		h.constructAndVerify(rt)
   352  
   353  		maddrs := make([]abi.Multiaddrs, 100)
   354  		for i := range maddrs {
   355  			maddrs[i] = []byte{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11}
   356  		}
   357  
   358  		rt.ExpectAbortContainsMessage(exitcode.ErrIllegalArgument, "multiaddr size", func() {
   359  			h.setMultiaddrs(rt, maddrs...)
   360  		})
   361  		h.checkState(rt)
   362  	})
   363  }
   364  
   365  // Tests for fetching and manipulating miner addresses.
   366  func TestControlAddresses(t *testing.T) {
   367  	actor := newHarness(t, 0)
   368  	builder := builderForHarness(actor)
   369  
   370  	t.Run("get addresses", func(t *testing.T) {
   371  		rt := builder.Build(t)
   372  		actor.constructAndVerify(rt)
   373  
   374  		o, w, control := actor.controlAddresses(rt)
   375  		assert.Equal(t, actor.owner, o)
   376  		assert.Equal(t, actor.worker, w)
   377  		assert.NotEmpty(t, control)
   378  		assert.Equal(t, actor.controlAddrs, control)
   379  		actor.checkState(rt)
   380  	})
   381  
   382  }
   383  
   384  // Test for sector precommitment and proving.
   385  func TestCommitments(t *testing.T) {
   386  	periodOffset := abi.ChainEpoch(100)
   387  	t.Run("valid precommit then provecommit", func(t *testing.T) {
   388  		actor := newHarness(t, periodOffset)
   389  		rt := builderForHarness(actor).
   390  			WithBalance(bigBalance, big.Zero()).
   391  			Build(t)
   392  		precommitEpoch := periodOffset + 1
   393  		rt.SetEpoch(precommitEpoch)
   394  		actor.constructAndVerify(rt)
   395  		dlInfo := actor.deadline(rt)
   396  
   397  		// Make a good commitment for the proof to target.
   398  		// Use the max sector number to make sure everything works.
   399  		sectorNo := abi.SectorNumber(abi.MaxSectorNumber)
   400  		proveCommitEpoch := precommitEpoch + miner.PreCommitChallengeDelay + 1
   401  		expiration := dlInfo.PeriodEnd() + defaultSectorExpiration*miner.WPoStProvingPeriod // something on deadline boundary but > 180 days
   402  		// Fill the sector with verified deals
   403  		sectorWeight := big.Mul(big.NewInt(int64(actor.sectorSize)), big.NewInt(int64(expiration-proveCommitEpoch)))
   404  		dealWeight := big.Zero()
   405  		verifiedDealWeight := sectorWeight
   406  
   407  		// Pre-commit with a deal in order to exercise non-zero deal weights.
   408  		precommitParams := actor.makePreCommit(sectorNo, precommitEpoch-1, expiration, []abi.DealID{1})
   409  		precommit := actor.preCommitSector(rt, precommitParams, preCommitConf{
   410  			dealWeight:         dealWeight,
   411  			verifiedDealWeight: verifiedDealWeight,
   412  		}, true)
   413  
   414  		// assert precommit exists and meets expectations
   415  		onChainPrecommit := actor.getPreCommit(rt, sectorNo)
   416  
   417  		// deal weights must be set in precommit onchain info
   418  		assert.Equal(t, dealWeight, onChainPrecommit.DealWeight)
   419  		assert.Equal(t, verifiedDealWeight, onChainPrecommit.VerifiedDealWeight)
   420  
   421  		pwrEstimate := miner.QAPowerForWeight(actor.sectorSize, precommit.Info.Expiration-precommitEpoch, onChainPrecommit.DealWeight, onChainPrecommit.VerifiedDealWeight)
   422  		expectedDeposit := miner.PreCommitDepositForPower(actor.epochRewardSmooth, actor.epochQAPowerSmooth, pwrEstimate)
   423  		assert.Equal(t, expectedDeposit, onChainPrecommit.PreCommitDeposit)
   424  
   425  		// expect total precommit deposit to equal our new deposit
   426  		st := getState(rt)
   427  		assert.Equal(t, expectedDeposit, st.PreCommitDeposits)
   428  
   429  		// run prove commit logic
   430  		rt.SetEpoch(proveCommitEpoch)
   431  		rt.SetBalance(big.Mul(big.NewInt(1000), big.NewInt(1e18)))
   432  		actor.proveCommitSectorAndConfirm(rt, precommit, makeProveCommit(sectorNo), proveCommitConf{})
   433  
   434  		// expect precommit to have been removed
   435  		st = getState(rt)
   436  		_, found, err := st.GetPrecommittedSector(rt.AdtStore(), sectorNo)
   437  		require.NoError(t, err)
   438  		require.False(t, found)
   439  
   440  		// expect deposit to have been transferred to initial pledges
   441  		assert.Equal(t, big.Zero(), st.PreCommitDeposits)
   442  
   443  		// The sector is exactly full with verified deals, so expect fully verified power.
   444  		expectedPower := big.Mul(big.NewInt(int64(actor.sectorSize)), big.Div(builtin.VerifiedDealWeightMultiplier, builtin.QualityBaseMultiplier))
   445  		qaPower := miner.QAPowerForWeight(actor.sectorSize, precommit.Info.Expiration-rt.Epoch(), onChainPrecommit.DealWeight, onChainPrecommit.VerifiedDealWeight)
   446  		assert.Equal(t, expectedPower, qaPower)
   447  		expectedInitialPledge := miner.InitialPledgeForPower(qaPower, actor.baselinePower, actor.epochRewardSmooth,
   448  			actor.epochQAPowerSmooth, rt.TotalFilCircSupply())
   449  		assert.Equal(t, expectedInitialPledge, st.InitialPledge)
   450  
   451  		// expect new onchain sector
   452  		sector := actor.getSector(rt, sectorNo)
   453  		sectorPower := miner.NewPowerPair(big.NewIntUnsigned(uint64(actor.sectorSize)), qaPower)
   454  
   455  		// expect deal weights to be transferred to on chain info
   456  		assert.Equal(t, onChainPrecommit.DealWeight, sector.DealWeight)
   457  		assert.Equal(t, onChainPrecommit.VerifiedDealWeight, sector.VerifiedDealWeight)
   458  
   459  		// expect activation epoch to be current epoch
   460  		assert.Equal(t, rt.Epoch(), sector.Activation)
   461  
   462  		// expect initial plege of sector to be set
   463  		assert.Equal(t, expectedInitialPledge, sector.InitialPledge)
   464  
   465  		// expect locked initial pledge of sector to be the same as pledge requirement
   466  		assert.Equal(t, expectedInitialPledge, st.InitialPledge)
   467  
   468  		// expect sector to be assigned a deadline/partition
   469  		dlIdx, pIdx, err := st.FindSector(rt.AdtStore(), sectorNo)
   470  		require.NoError(t, err)
   471  		deadline, partition := actor.getDeadlineAndPartition(rt, dlIdx, pIdx)
   472  		assert.Equal(t, uint64(1), deadline.LiveSectors)
   473  		assertEmptyBitfield(t, deadline.PartitionsPoSted)
   474  		assertEmptyBitfield(t, deadline.EarlyTerminations)
   475  
   476  		quant := st.QuantSpecForDeadline(dlIdx)
   477  		quantizedExpiration := quant.QuantizeUp(precommit.Info.Expiration)
   478  
   479  		dQueue := actor.collectDeadlineExpirations(rt, deadline)
   480  		assert.Equal(t, map[abi.ChainEpoch][]uint64{
   481  			quantizedExpiration: {pIdx},
   482  		}, dQueue)
   483  
   484  		assertBitfieldEquals(t, partition.Sectors, uint64(sectorNo))
   485  		assertEmptyBitfield(t, partition.Faults)
   486  		assertEmptyBitfield(t, partition.Recoveries)
   487  		assertEmptyBitfield(t, partition.Terminated)
   488  		assert.Equal(t, sectorPower, partition.LivePower)
   489  		assert.Equal(t, miner.NewPowerPairZero(), partition.FaultyPower)
   490  		assert.Equal(t, miner.NewPowerPairZero(), partition.RecoveringPower)
   491  
   492  		pQueue := actor.collectPartitionExpirations(rt, partition)
   493  		entry, ok := pQueue[quantizedExpiration]
   494  		require.True(t, ok)
   495  		assertBitfieldEquals(t, entry.OnTimeSectors, uint64(sectorNo))
   496  		assertEmptyBitfield(t, entry.EarlySectors)
   497  		assert.Equal(t, expectedInitialPledge, entry.OnTimePledge)
   498  		assert.Equal(t, sectorPower, entry.ActivePower)
   499  		assert.Equal(t, miner.NewPowerPairZero(), entry.FaultyPower)
   500  	})
   501  
   502  	for _, test := range []struct {
   503  		name                string
   504  		version             network.Version
   505  		expectedPledgeDelta abi.TokenAmount
   506  		sealProofType       abi.RegisteredSealProof
   507  	}{{
   508  		name:                "precommit does not vest funds in version 8",
   509  		version:             network.Version8,
   510  		expectedPledgeDelta: abi.NewTokenAmount(0),
   511  		sealProofType:       abi.RegisteredSealProof_StackedDrg32GiBV1_1,
   512  	}} {
   513  		t.Run(test.name, func(t *testing.T) {
   514  			actor := newHarness(t, periodOffset)
   515  			actor.setProofType(test.sealProofType)
   516  			rt := builderForHarness(actor).
   517  				WithBalance(bigBalance, big.Zero()).
   518  				WithNetworkVersion(test.version).
   519  				Build(t)
   520  			precommitEpoch := periodOffset + 1
   521  			rt.SetEpoch(precommitEpoch)
   522  			actor.constructAndVerify(rt)
   523  			dlInfo := actor.deadline(rt)
   524  
   525  			// Make a good commitment for the proof to target.
   526  			sectorNo := abi.SectorNumber(100)
   527  			expiration := dlInfo.PeriodEnd() + defaultSectorExpiration*miner.WPoStProvingPeriod // something on deadline boundary but > 180 days
   528  
   529  			// add 1000 tokens that vest immediately
   530  			st := getState(rt)
   531  			_, err := st.AddLockedFunds(rt.AdtStore(), rt.Epoch(), abi.NewTokenAmount(1000), &miner.VestSpec{
   532  				InitialDelay: 0,
   533  				VestPeriod:   1,
   534  				StepDuration: 1,
   535  				Quantization: 1,
   536  			})
   537  			require.NoError(t, err)
   538  			rt.ReplaceState(st)
   539  
   540  			rt.SetEpoch(rt.Epoch() + 2)
   541  
   542  			// Pre-commit with a deal in order to exercise non-zero deal weights.
   543  			precommitParams := actor.makePreCommit(sectorNo, precommitEpoch-1, expiration, []abi.DealID{1})
   544  			actor.preCommitSector(rt, precommitParams, preCommitConf{
   545  				pledgeDelta: &test.expectedPledgeDelta,
   546  			}, true)
   547  		})
   548  	}
   549  
   550  	t.Run("insufficient funds for pre-commit", func(t *testing.T) {
   551  		actor := newHarness(t, periodOffset)
   552  		insufficientBalance := abi.NewTokenAmount(10) // 10 AttoFIL
   553  		rt := builderForHarness(actor).
   554  			WithBalance(insufficientBalance, big.Zero()).
   555  			Build(t)
   556  		precommitEpoch := periodOffset + 1
   557  		rt.SetEpoch(precommitEpoch)
   558  		actor.constructAndVerify(rt)
   559  		deadline := actor.deadline(rt)
   560  		challengeEpoch := precommitEpoch - 1
   561  		expiration := deadline.PeriodEnd() + defaultSectorExpiration*miner.WPoStProvingPeriod
   562  
   563  		rt.ExpectAbort(exitcode.ErrInsufficientFunds, func() {
   564  			actor.preCommitSector(rt, actor.makePreCommit(101, challengeEpoch, expiration, nil), preCommitConf{}, true)
   565  		})
   566  		actor.checkState(rt)
   567  	})
   568  
   569  	t.Run("deal space exceeds sector space", func(t *testing.T) {
   570  		actor := newHarness(t, periodOffset)
   571  		rt := builderForHarness(actor).
   572  			WithBalance(bigBalance, big.Zero()).
   573  			Build(t)
   574  
   575  		precommitEpoch := periodOffset + 1
   576  		rt.SetEpoch(precommitEpoch)
   577  		actor.constructAndVerify(rt)
   578  		deadline := actor.deadline(rt)
   579  		challengeEpoch := precommitEpoch - 1
   580  		expiration := deadline.PeriodEnd() + defaultSectorExpiration*miner.WPoStProvingPeriod
   581  
   582  		rt.ExpectAbortContainsMessage(exitcode.ErrIllegalArgument, "deals too large to fit in sector", func() {
   583  			actor.preCommitSector(rt, actor.makePreCommit(101, challengeEpoch, expiration, []abi.DealID{1}), preCommitConf{
   584  				dealSpace: actor.sectorSize + 1,
   585  			}, true)
   586  		})
   587  		actor.checkState(rt)
   588  	})
   589  
   590  	t.Run("precommit pays back fee debt", func(t *testing.T) {
   591  		actor := newHarness(t, periodOffset)
   592  		rt := builderForHarness(actor).
   593  			WithBalance(bigBalance, big.Zero()).
   594  			Build(t)
   595  
   596  		precommitEpoch := periodOffset + 1
   597  		rt.SetEpoch(precommitEpoch)
   598  		actor.constructAndVerify(rt)
   599  		deadline := actor.deadline(rt)
   600  		challengeEpoch := precommitEpoch - 1
   601  		expiration := deadline.PeriodEnd() + defaultSectorExpiration*miner.WPoStProvingPeriod
   602  
   603  		st := getState(rt)
   604  		st.FeeDebt = abi.NewTokenAmount(9999)
   605  		rt.ReplaceState(st)
   606  
   607  		actor.preCommitSector(rt, actor.makePreCommit(101, challengeEpoch, expiration, nil), preCommitConf{}, true)
   608  		st = getState(rt)
   609  		assert.Equal(t, big.Zero(), st.FeeDebt)
   610  		actor.checkState(rt)
   611  	})
   612  
   613  	t.Run("invalid pre-commit rejected", func(t *testing.T) {
   614  		actor := newHarness(t, periodOffset)
   615  		rt := builderForHarness(actor).
   616  			WithBalance(bigBalance, big.Zero()).
   617  			Build(t)
   618  		precommitEpoch := periodOffset + 1
   619  		rt.SetEpoch(precommitEpoch)
   620  		actor.constructAndVerify(rt)
   621  		deadline := actor.deadline(rt)
   622  		challengeEpoch := precommitEpoch - 1
   623  
   624  		oldSector := actor.commitAndProveSectors(rt, 1, defaultSectorExpiration, nil, true)[0]
   625  		st := getState(rt)
   626  		assert.True(t, st.DeadlineCronActive)
   627  		// Good commitment.
   628  		expiration := deadline.PeriodEnd() + defaultSectorExpiration*miner.WPoStProvingPeriod
   629  		actor.preCommitSector(rt, actor.makePreCommit(101, challengeEpoch, expiration, nil), preCommitConf{}, false)
   630  		// Duplicate pre-commit sector ID
   631  		rt.ExpectAbortContainsMessage(exitcode.ErrIllegalArgument, "already been allocated", func() {
   632  			actor.preCommitSector(rt, actor.makePreCommit(101, challengeEpoch, expiration, nil), preCommitConf{}, false)
   633  		})
   634  		rt.Reset()
   635  
   636  		// Sector ID already committed
   637  		rt.ExpectAbortContainsMessage(exitcode.ErrIllegalArgument, "already been allocated", func() {
   638  			actor.preCommitSector(rt, actor.makePreCommit(oldSector.SectorNumber, challengeEpoch, expiration, nil), preCommitConf{}, false)
   639  		})
   640  		rt.Reset()
   641  
   642  		// Bad sealed CID
   643  		rt.ExpectAbortContainsMessage(exitcode.ErrIllegalArgument, "sealed CID had wrong prefix", func() {
   644  			pc := actor.makePreCommit(102, challengeEpoch, deadline.PeriodEnd(), nil)
   645  			pc.SealedCID = tutil.MakeCID("Random Data", nil)
   646  			actor.preCommitSector(rt, pc, preCommitConf{}, false)
   647  		})
   648  		rt.Reset()
   649  
   650  		// Bad seal proof type
   651  		rt.ExpectAbortContainsMessage(exitcode.ErrIllegalArgument, "unsupported seal proof type", func() {
   652  			pc := actor.makePreCommit(102, challengeEpoch, deadline.PeriodEnd(), nil)
   653  			pc.SealProof = abi.RegisteredSealProof_StackedDrg8MiBV1_1
   654  			actor.preCommitSector(rt, pc, preCommitConf{}, false)
   655  		})
   656  		rt.Reset()
   657  
   658  		// Expires at current epoch
   659  		rt.ExpectAbortContainsMessage(exitcode.ErrIllegalArgument, "must be after activation", func() {
   660  			actor.preCommitSector(rt, actor.makePreCommit(102, challengeEpoch, rt.Epoch(), nil), preCommitConf{}, false)
   661  		})
   662  		rt.Reset()
   663  
   664  		// Expires before current epoch
   665  		rt.ExpectAbortContainsMessage(exitcode.ErrIllegalArgument, "must be after activation", func() {
   666  			actor.preCommitSector(rt, actor.makePreCommit(102, challengeEpoch, rt.Epoch()-1, nil), preCommitConf{}, false)
   667  		})
   668  		rt.Reset()
   669  
   670  		// Expires too early
   671  		rt.ExpectAbortContainsMessage(exitcode.ErrIllegalArgument, "must exceed", func() {
   672  			actor.preCommitSector(rt, actor.makePreCommit(102, challengeEpoch, expiration-20*builtin.EpochsInDay, nil), preCommitConf{}, false)
   673  		})
   674  		rt.Reset()
   675  
   676  		// Expires before min duration + max seal duration
   677  		rt.ExpectAbortContainsMessage(exitcode.ErrIllegalArgument, "must exceed", func() {
   678  			expiration := rt.Epoch() + miner.MinSectorExpiration + miner.MaxProveCommitDuration[actor.sealProofType] - 1
   679  			actor.preCommitSector(rt, actor.makePreCommit(102, challengeEpoch, expiration, nil), preCommitConf{}, false)
   680  		})
   681  		rt.Reset()
   682  
   683  		// Errors when expiry too far in the future
   684  		rt.SetEpoch(precommitEpoch)
   685  		rt.ExpectAbortContainsMessage(exitcode.ErrIllegalArgument, "invalid expiration", func() {
   686  			expiration := deadline.PeriodEnd() + miner.WPoStProvingPeriod*(miner.MaxSectorExpirationExtension/miner.WPoStProvingPeriod+1)
   687  			actor.preCommitSector(rt, actor.makePreCommit(102, challengeEpoch, expiration, nil), preCommitConf{}, false)
   688  		})
   689  		rt.Reset()
   690  
   691  		// Sector ID out of range
   692  		rt.ExpectAbortContainsMessage(exitcode.ErrIllegalArgument, "out of range", func() {
   693  			actor.preCommitSector(rt, actor.makePreCommit(abi.MaxSectorNumber+1, challengeEpoch, expiration, nil), preCommitConf{}, false)
   694  		})
   695  		rt.Reset()
   696  
   697  		// Seal randomness challenge too far in past
   698  		tooOldChallengeEpoch := precommitEpoch - miner.ChainFinality - miner.MaxProveCommitDuration[actor.sealProofType] - 1
   699  		rt.ExpectAbortContainsMessage(exitcode.ErrIllegalArgument, "too old", func() {
   700  			actor.preCommitSector(rt, actor.makePreCommit(102, tooOldChallengeEpoch, expiration, nil), preCommitConf{}, false)
   701  		})
   702  		rt.Reset()
   703  
   704  		// Try to precommit while in fee debt with insufficient balance
   705  		st = getState(rt)
   706  		st.FeeDebt = big.Add(rt.Balance(), abi.NewTokenAmount(1e18))
   707  		rt.ReplaceState(st)
   708  		rt.ExpectAbortContainsMessage(exitcode.ErrInsufficientFunds, "unlocked balance can not repay fee debt", func() {
   709  			actor.preCommitSector(rt, actor.makePreCommit(102, challengeEpoch, expiration, nil), preCommitConf{}, false)
   710  		})
   711  		// reset state back to normal
   712  		st.FeeDebt = big.Zero()
   713  		rt.ReplaceState(st)
   714  		rt.Reset()
   715  
   716  		// Try to precommit with an active consensus fault
   717  		st = getState(rt)
   718  
   719  		actor.reportConsensusFault(rt, addr.TestAddress, &runtime.ConsensusFault{
   720  			Target: actor.receiver,
   721  			Epoch:  rt.Epoch() - 1,
   722  			Type:   runtime.ConsensusFaultDoubleForkMining,
   723  		})
   724  		rt.ExpectAbortContainsMessage(exitcode.ErrForbidden, "precommit not allowed during active consensus fault", func() {
   725  			actor.preCommitSector(rt, actor.makePreCommit(102, challengeEpoch, expiration, nil), preCommitConf{}, false)
   726  		})
   727  		// reset state back to normal
   728  		rt.ReplaceState(st)
   729  		rt.Reset()
   730  		actor.checkState(rt)
   731  	})
   732  
   733  	t.Run("prove commit just after period start permits PoSt", func(t *testing.T) {
   734  		actor := newHarness(t, periodOffset)
   735  		rt := builderForHarness(actor).
   736  			WithBalance(bigBalance, big.Zero()).
   737  			Build(t)
   738  
   739  		// Epoch 101 should be at the beginning of the miner's proving period so there will be time to commit
   740  		// and PoSt a sector.
   741  		rt.SetEpoch(101)
   742  		actor.constructAndVerify(rt)
   743  
   744  		// Commit a sector the very next epoch
   745  		rt.SetEpoch(102)
   746  		sector := actor.commitAndProveSector(rt, abi.MaxSectorNumber, defaultSectorExpiration, nil)
   747  
   748  		// advance cron to activate power.
   749  		advanceAndSubmitPoSts(rt, actor, sector)
   750  		actor.checkState(rt)
   751  	})
   752  
   753  	t.Run("invalid proof rejected", func(t *testing.T) {
   754  		actor := newHarness(t, periodOffset)
   755  		rt := builderForHarness(actor).
   756  			WithBalance(bigBalance, big.Zero()).
   757  			Build(t)
   758  		precommitEpoch := periodOffset + 1
   759  		rt.SetEpoch(precommitEpoch)
   760  		actor.constructAndVerify(rt)
   761  		deadline := actor.deadline(rt)
   762  
   763  		// Make a good commitment for the proof to target.
   764  		sectorNo := abi.SectorNumber(100)
   765  		params := actor.makePreCommit(sectorNo, precommitEpoch-1, deadline.PeriodEnd()+defaultSectorExpiration*miner.WPoStProvingPeriod, []abi.DealID{1})
   766  		precommit := actor.preCommitSector(rt, params, preCommitConf{}, true)
   767  
   768  		// Sector pre-commitment missing.
   769  		rt.SetEpoch(precommitEpoch + miner.PreCommitChallengeDelay + 1)
   770  		rt.ExpectAbort(exitcode.ErrNotFound, func() {
   771  			actor.proveCommitSectorAndConfirm(rt, precommit, makeProveCommit(sectorNo+1), proveCommitConf{})
   772  		})
   773  		rt.Reset()
   774  
   775  		// Too late.
   776  		rt.SetEpoch(precommitEpoch + miner.MaxProveCommitDuration[precommit.Info.SealProof] + 1)
   777  		rt.ExpectAbort(exitcode.ErrIllegalArgument, func() {
   778  			actor.proveCommitSectorAndConfirm(rt, precommit, makeProveCommit(sectorNo), proveCommitConf{})
   779  		})
   780  		rt.Reset()
   781  
   782  		// Too early.
   783  		rt.SetEpoch(precommitEpoch + miner.PreCommitChallengeDelay - 1)
   784  		rt.ExpectAbort(exitcode.ErrForbidden, func() {
   785  			actor.proveCommitSectorAndConfirm(rt, precommit, makeProveCommit(sectorNo), proveCommitConf{})
   786  		})
   787  		rt.Reset()
   788  
   789  		// Set the right epoch for all following tests
   790  		rt.SetEpoch(precommitEpoch + miner.PreCommitChallengeDelay + 1)
   791  
   792  		// Invalid deals (market ActivateDeals aborts)
   793  		verifyDealsExit := map[abi.SectorNumber]exitcode.ExitCode{
   794  			precommit.Info.SectorNumber: exitcode.ErrIllegalArgument,
   795  		}
   796  		rt.ExpectAbort(exitcode.ErrIllegalArgument, func() {
   797  			actor.proveCommitSectorAndConfirm(rt, precommit, makeProveCommit(sectorNo), proveCommitConf{
   798  				verifyDealsExit: verifyDealsExit,
   799  			})
   800  		})
   801  		rt.Reset()
   802  
   803  		rt.SetBalance(big.Mul(big.NewInt(1000), big.NewInt(1e18)))
   804  
   805  		proveCommit := makeProveCommit(sectorNo)
   806  		actor.proveCommitSectorAndConfirm(rt, precommit, proveCommit, proveCommitConf{})
   807  		st := getState(rt)
   808  
   809  		// Verify new sectors
   810  		// TODO minerstate
   811  		//newSectors, err := st.NewSectors.All(miner.SectorsMax)
   812  		//require.NoError(t, err)
   813  		//assert.Equal(t, []uint64{uint64(sectorNo)}, newSectors)
   814  		// Verify pledge lock-up
   815  		assert.True(t, st.InitialPledge.GreaterThan(big.Zero()))
   816  		rt.Reset()
   817  
   818  		// Duplicate proof (sector no-longer pre-committed)
   819  		rt.ExpectAbort(exitcode.ErrNotFound, func() {
   820  			actor.proveCommitSectorAndConfirm(rt, precommit, makeProveCommit(sectorNo), proveCommitConf{})
   821  		})
   822  		rt.Reset()
   823  		actor.checkState(rt)
   824  	})
   825  
   826  	for _, test := range []struct {
   827  		name               string
   828  		version            network.Version
   829  		vestingPledgeDelta abi.TokenAmount
   830  		sealProofType      abi.RegisteredSealProof
   831  	}{{
   832  		name:               "verify proof does not vest at version 8",
   833  		version:            network.Version8,
   834  		vestingPledgeDelta: abi.NewTokenAmount(0),
   835  		sealProofType:      abi.RegisteredSealProof_StackedDrg32GiBV1_1,
   836  	}} {
   837  		t.Run(test.name, func(t *testing.T) {
   838  			actor := newHarness(t, periodOffset)
   839  			actor.setProofType(test.sealProofType)
   840  			rt := builderForHarness(actor).
   841  				WithNetworkVersion(test.version).
   842  				WithBalance(bigBalance, big.Zero()).
   843  				Build(t)
   844  			precommitEpoch := periodOffset + 1
   845  			rt.SetEpoch(precommitEpoch)
   846  			actor.constructAndVerify(rt)
   847  			deadline := actor.deadline(rt)
   848  
   849  			// Make a good commitment for the proof to target.
   850  			sectorNo := abi.SectorNumber(100)
   851  			params := actor.makePreCommit(sectorNo, precommitEpoch-1, deadline.PeriodEnd()+defaultSectorExpiration*miner.WPoStProvingPeriod, []abi.DealID{1})
   852  			precommit := actor.preCommitSector(rt, params, preCommitConf{}, true)
   853  
   854  			// add 1000 tokens that vest immediately
   855  			st := getState(rt)
   856  			_, err := st.AddLockedFunds(rt.AdtStore(), rt.Epoch(), abi.NewTokenAmount(1000), &miner.VestSpec{
   857  				InitialDelay: 0,
   858  				VestPeriod:   1,
   859  				StepDuration: 1,
   860  				Quantization: 1,
   861  			})
   862  			require.NoError(t, err)
   863  			rt.ReplaceState(st)
   864  
   865  			// Set the right epoch for all following tests
   866  			rt.SetEpoch(precommitEpoch + miner.PreCommitChallengeDelay + 1)
   867  			rt.SetBalance(big.Mul(big.NewInt(1000), big.NewInt(1e18)))
   868  
   869  			// Too big at version 4
   870  			proveCommit := makeProveCommit(sectorNo)
   871  			proveCommit.Proof = make([]byte, 192)
   872  			actor.proveCommitSectorAndConfirm(rt, precommit, proveCommit, proveCommitConf{
   873  				vestingPledgeDelta: &test.vestingPledgeDelta,
   874  			})
   875  		})
   876  
   877  	}
   878  
   879  	t.Run("sector with non-positive lifetime is skipped in confirmation", func(t *testing.T) {
   880  		actor := newHarness(t, periodOffset)
   881  		rt := builderForHarness(actor).
   882  			WithBalance(bigBalance, big.Zero()).
   883  			Build(t)
   884  		precommitEpoch := periodOffset + 1
   885  		rt.SetEpoch(precommitEpoch)
   886  		actor.constructAndVerify(rt)
   887  		deadline := actor.deadline(rt)
   888  
   889  		sectorNo := abi.SectorNumber(100)
   890  		params := actor.makePreCommit(sectorNo, precommitEpoch-1, deadline.PeriodEnd()+defaultSectorExpiration*miner.WPoStProvingPeriod, nil)
   891  		precommit := actor.preCommitSector(rt, params, preCommitConf{}, true)
   892  
   893  		// precommit at correct epoch
   894  		rt.SetEpoch(rt.Epoch() + miner.PreCommitChallengeDelay + 1)
   895  		actor.proveCommitSector(rt, precommit, makeProveCommit(sectorNo))
   896  
   897  		// confirm at sector expiration (this probably can't happen)
   898  		rt.SetEpoch(precommit.Info.Expiration)
   899  		// sector skipped but no failure occurs
   900  		actor.confirmSectorProofsValid(rt, proveCommitConf{}, precommit)
   901  		rt.ExpectLogsContain("less than minimum. ignoring")
   902  
   903  		// it still skips if sector lifetime is negative
   904  		rt.ClearLogs()
   905  		rt.SetEpoch(precommit.Info.Expiration + 1)
   906  		actor.confirmSectorProofsValid(rt, proveCommitConf{}, precommit)
   907  		rt.ExpectLogsContain("less than minimum. ignoring")
   908  
   909  		// it fails up to the miniumum expiration
   910  		rt.ClearLogs()
   911  		rt.SetEpoch(precommit.Info.Expiration - miner.MinSectorExpiration + 1)
   912  		actor.confirmSectorProofsValid(rt, proveCommitConf{}, precommit)
   913  		rt.ExpectLogsContain("less than minimum. ignoring")
   914  		actor.checkState(rt)
   915  	})
   916  
   917  	t.Run("fails with too many deals", func(t *testing.T) {
   918  		setup := func(proof abi.RegisteredSealProof) (*mock.Runtime, *actorHarness, *dline.Info) {
   919  			actor := newHarness(t, periodOffset)
   920  			actor.setProofType(proof)
   921  			rt := builderForHarness(actor).
   922  				WithBalance(bigBalance, big.Zero()).
   923  				Build(t)
   924  			rt.SetEpoch(periodOffset + 1)
   925  			actor.constructAndVerify(rt)
   926  			deadline := actor.deadline(rt)
   927  			return rt, actor, deadline
   928  		}
   929  
   930  		makeDealIDs := func(n int) []abi.DealID {
   931  			ids := make([]abi.DealID, n)
   932  			for i := range ids {
   933  				ids[i] = abi.DealID(i)
   934  			}
   935  			return ids
   936  		}
   937  
   938  		// Make a good commitment for the proof to target.
   939  		sectorNo := abi.SectorNumber(100)
   940  
   941  		dealLimits := map[abi.RegisteredSealProof]int{
   942  			abi.RegisteredSealProof_StackedDrg2KiBV1_1:  256,
   943  			abi.RegisteredSealProof_StackedDrg32GiBV1_1: 256,
   944  			abi.RegisteredSealProof_StackedDrg64GiBV1_1: 512,
   945  		}
   946  
   947  		for proof, limit := range dealLimits {
   948  			// attempt to pre-commmit a sector with too many sectors
   949  			rt, actor, deadline := setup(proof)
   950  			expiration := deadline.PeriodEnd() + defaultSectorExpiration*miner.WPoStProvingPeriod
   951  			precommit := actor.makePreCommit(sectorNo, rt.Epoch()-1, expiration, makeDealIDs(limit+1))
   952  			rt.ExpectAbortContainsMessage(exitcode.ErrIllegalArgument, "too many deals for sector", func() {
   953  				actor.preCommitSector(rt, precommit, preCommitConf{}, true)
   954  			})
   955  
   956  			// sector at or below limit succeeds
   957  			rt, actor, _ = setup(proof)
   958  			precommit = actor.makePreCommit(sectorNo, rt.Epoch()-1, expiration, makeDealIDs(limit))
   959  			actor.preCommitSector(rt, precommit, preCommitConf{}, true)
   960  			actor.checkState(rt)
   961  		}
   962  	})
   963  
   964  	t.Run("precommit checks seal proof version", func(t *testing.T) {
   965  		actor := newHarness(t, periodOffset)
   966  		actor.setProofType(abi.RegisteredSealProof_StackedDrg32GiBV1)
   967  		rt := builderForHarness(actor).
   968  			WithBalance(bigBalance, big.Zero()).
   969  			Build(t)
   970  
   971  		// Create miner before version 7
   972  		rt.SetNetworkVersion(network.Version6)
   973  		actor.constructAndVerify(rt)
   974  		precommitEpoch := periodOffset + 1
   975  		rt.SetEpoch(precommitEpoch)
   976  		deadline := actor.deadline(rt)
   977  		challengeEpoch := precommitEpoch - 1
   978  		expiration := deadline.PeriodEnd() + defaultSectorExpiration*miner.WPoStProvingPeriod
   979  		{
   980  			// After version 7, only V1_1 accepted
   981  			rt.SetNetworkVersion(network.Version8)
   982  			pc := actor.makePreCommit(104, challengeEpoch, expiration, nil)
   983  			pc.SealProof = abi.RegisteredSealProof_StackedDrg32GiBV1
   984  			rt.ExpectAbort(exitcode.ErrIllegalArgument, func() {
   985  				actor.preCommitSector(rt, pc, preCommitConf{}, true)
   986  			})
   987  			rt.Reset()
   988  			pc.SealProof = abi.RegisteredSealProof_StackedDrg32GiBV1_1
   989  			actor.preCommitSector(rt, pc, preCommitConf{}, true)
   990  		}
   991  
   992  		actor.checkState(rt)
   993  	})
   994  }
   995  
   996  // Test sector lifecycle when a sector is upgraded
   997  func TestCCUpgrade(t *testing.T) {
   998  	periodOffset := abi.ChainEpoch(100)
   999  	t.Run("valid committed capacity upgrade", func(t *testing.T) {
  1000  		actor := newHarness(t, periodOffset)
  1001  		rt := builderForHarness(actor).
  1002  			WithBalance(bigBalance, big.Zero()).
  1003  			Build(t)
  1004  		actor.constructAndVerify(rt)
  1005  
  1006  		// Move the current epoch forward so that the first deadline is a stable candidate for both sectors
  1007  		rt.SetEpoch(periodOffset + miner.WPoStChallengeWindow)
  1008  
  1009  		// Commit a sector to upgrade
  1010  		// Use the max sector number to make sure everything works.
  1011  		oldSector := actor.commitAndProveSector(rt, abi.MaxSectorNumber, defaultSectorExpiration, nil)
  1012  
  1013  		// advance cron to activate power.
  1014  		advanceAndSubmitPoSts(rt, actor, oldSector)
  1015  
  1016  		st := getState(rt)
  1017  		dlIdx, partIdx, err := st.FindSector(rt.AdtStore(), oldSector.SectorNumber)
  1018  		require.NoError(t, err)
  1019  
  1020  		// Reduce the epoch reward so that a new sector's initial pledge would otherwise be lesser.
  1021  		// It has to be reduced quite a lot to overcome the new sector having more power due to verified deal weight.
  1022  		actor.epochRewardSmooth = smoothing.TestingConstantEstimate(big.Div(actor.epochRewardSmooth.Estimate(), big.NewInt(20)))
  1023  
  1024  		challengeEpoch := rt.Epoch() - 1
  1025  		upgradeParams := actor.makePreCommit(200, challengeEpoch, oldSector.Expiration, []abi.DealID{1})
  1026  		upgradeParams.ReplaceCapacity = true
  1027  		upgradeParams.ReplaceSectorDeadline = dlIdx
  1028  		upgradeParams.ReplaceSectorPartition = partIdx
  1029  		upgradeParams.ReplaceSectorNumber = oldSector.SectorNumber
  1030  		upgrade := actor.preCommitSector(rt, upgradeParams, preCommitConf{}, false)
  1031  
  1032  		// Check new pre-commit in state
  1033  		assert.True(t, upgrade.Info.ReplaceCapacity)
  1034  		assert.Equal(t, upgradeParams.ReplaceSectorNumber, upgrade.Info.ReplaceSectorNumber)
  1035  
  1036  		// Old sector is unchanged
  1037  		oldSectorAgain := actor.getSector(rt, oldSector.SectorNumber)
  1038  		assert.Equal(t, oldSector, oldSectorAgain)
  1039  
  1040  		// Deposit and pledge as expected
  1041  		st = getState(rt)
  1042  		assert.Equal(t, st.PreCommitDeposits, upgrade.PreCommitDeposit)
  1043  		assert.Equal(t, st.InitialPledge, oldSector.InitialPledge)
  1044  
  1045  		// Prove new sector
  1046  		rt.SetEpoch(upgrade.PreCommitEpoch + miner.PreCommitChallengeDelay + 1)
  1047  		newSector := actor.proveCommitSectorAndConfirm(rt, upgrade, makeProveCommit(upgrade.Info.SectorNumber), proveCommitConf{})
  1048  
  1049  		// Both sectors' deposits are returned, and pledge is committed
  1050  		st = getState(rt)
  1051  		assert.Equal(t, big.Zero(), st.PreCommitDeposits)
  1052  		assert.Equal(t, st.InitialPledge, big.Add(oldSector.InitialPledge, newSector.InitialPledge))
  1053  		// new sector pledge is max of computed pledge and pledge from old sector
  1054  		assert.Equal(t, oldSector.InitialPledge, newSector.InitialPledge)
  1055  
  1056  		// Both sectors are present (in the same deadline/partition).
  1057  		deadline, partition := actor.getDeadlineAndPartition(rt, dlIdx, partIdx)
  1058  		assert.Equal(t, uint64(2), deadline.TotalSectors)
  1059  		assert.Equal(t, uint64(2), deadline.LiveSectors)
  1060  		assertEmptyBitfield(t, deadline.EarlyTerminations)
  1061  
  1062  		assertBitfieldEquals(t, partition.Sectors, uint64(newSector.SectorNumber), uint64(oldSector.SectorNumber))
  1063  		assertEmptyBitfield(t, partition.Faults)
  1064  		assertEmptyBitfield(t, partition.Recoveries)
  1065  		assertEmptyBitfield(t, partition.Terminated)
  1066  
  1067  		// The old sector's expiration has changed to the end of this proving deadline.
  1068  		// The new one expires when the old one used to.
  1069  		// The partition is registered with an expiry at both epochs.
  1070  		dQueue := actor.collectDeadlineExpirations(rt, deadline)
  1071  		dlInfo := miner.NewDeadlineInfo(st.ProvingPeriodStart, dlIdx, rt.Epoch())
  1072  		quantizedExpiration := miner.QuantSpecForDeadline(dlInfo).QuantizeUp(oldSector.Expiration)
  1073  		assert.Equal(t, map[abi.ChainEpoch][]uint64{
  1074  			dlInfo.NextNotElapsed().Last(): {uint64(0)},
  1075  			quantizedExpiration:            {uint64(0)},
  1076  		}, dQueue)
  1077  
  1078  		pQueue := actor.collectPartitionExpirations(rt, partition)
  1079  		assertBitfieldEquals(t, pQueue[dlInfo.NextNotElapsed().Last()].OnTimeSectors, uint64(oldSector.SectorNumber))
  1080  		assertBitfieldEquals(t, pQueue[quantizedExpiration].OnTimeSectors, uint64(newSector.SectorNumber))
  1081  
  1082  		// Roll forward to the beginning of the next iteration of this deadline
  1083  		advanceToEpochWithCron(rt, actor, dlInfo.NextNotElapsed().Open)
  1084  
  1085  		// Fail to submit PoSt. This means that both sectors will be detected faulty.
  1086  		// Expect the old sector to be marked as terminated.
  1087  		bothSectors := []*miner.SectorOnChainInfo{oldSector, newSector}
  1088  		lostPower := actor.powerPairForSectors(bothSectors[:1]).Neg() // new sector not active yet.
  1089  		faultExpiration := miner.QuantSpecForDeadline(dlInfo).QuantizeUp(dlInfo.NextNotElapsed().Last() + miner.FaultMaxAge)
  1090  
  1091  		advanceDeadline(rt, actor, &cronConfig{
  1092  			detectedFaultsPowerDelta:  &lostPower,
  1093  			expiredSectorsPledgeDelta: oldSector.InitialPledge.Neg(),
  1094  		})
  1095  
  1096  		// The old sector is marked as terminated
  1097  		st = getState(rt)
  1098  		deadline, partition = actor.getDeadlineAndPartition(rt, dlIdx, partIdx)
  1099  		assert.Equal(t, uint64(2), deadline.TotalSectors)
  1100  		assert.Equal(t, uint64(1), deadline.LiveSectors)
  1101  		assertBitfieldEquals(t, partition.Sectors, uint64(newSector.SectorNumber), uint64(oldSector.SectorNumber))
  1102  		assertBitfieldEquals(t, partition.Terminated, uint64(oldSector.SectorNumber))
  1103  		assertBitfieldEquals(t, partition.Faults, uint64(newSector.SectorNumber))
  1104  		newSectorPower := miner.PowerForSector(actor.sectorSize, newSector)
  1105  		assert.True(t, newSectorPower.Equals(partition.LivePower))
  1106  		assert.True(t, newSectorPower.Equals(partition.FaultyPower))
  1107  
  1108  		// we expect the partition expiration to be scheduled twice, once early
  1109  		// and once on-time (inside the partition, the sector is scheduled only once).
  1110  		dQueue = actor.collectDeadlineExpirations(rt, deadline)
  1111  		assert.Equal(t, map[abi.ChainEpoch][]uint64{
  1112  			miner.QuantSpecForDeadline(dlInfo).QuantizeUp(newSector.Expiration): {uint64(0)},
  1113  			faultExpiration: {uint64(0)},
  1114  		}, dQueue)
  1115  
  1116  		// Old sector gone from pledge requirement and deposit
  1117  		assert.Equal(t, st.InitialPledge, newSector.InitialPledge)
  1118  		actor.checkState(rt)
  1119  	})
  1120  
  1121  	t.Run("invalid committed capacity upgrade rejected", func(t *testing.T) {
  1122  		actor := newHarness(t, periodOffset)
  1123  		rt := builderForHarness(actor).
  1124  			WithBalance(bigBalance, big.Zero()).
  1125  			Build(t)
  1126  		actor.constructAndVerify(rt)
  1127  
  1128  		// Commit sectors to target upgrade. The first has no deals, the second has a deal.
  1129  		oldSectors := actor.commitAndProveSectors(rt, 2, defaultSectorExpiration, [][]abi.DealID{nil, {10}}, true)
  1130  
  1131  		st := getState(rt)
  1132  		dlIdx, partIdx, err := st.FindSector(rt.AdtStore(), oldSectors[0].SectorNumber)
  1133  		require.NoError(t, err)
  1134  
  1135  		challengeEpoch := rt.Epoch() - 1
  1136  		upgradeParams := actor.makePreCommit(200, challengeEpoch, oldSectors[0].Expiration, []abi.DealID{20})
  1137  		upgradeParams.ReplaceCapacity = true
  1138  		upgradeParams.ReplaceSectorDeadline = dlIdx
  1139  		upgradeParams.ReplaceSectorPartition = partIdx
  1140  		upgradeParams.ReplaceSectorNumber = oldSectors[0].SectorNumber
  1141  
  1142  		{ // Must have deals
  1143  			params := *upgradeParams
  1144  			params.DealIDs = nil
  1145  			rt.ExpectAbort(exitcode.ErrIllegalArgument, func() {
  1146  				actor.preCommitSector(rt, &params, preCommitConf{}, false)
  1147  			})
  1148  			rt.Reset()
  1149  		}
  1150  		{ // Old sector cannot have deals
  1151  			params := *upgradeParams
  1152  			params.ReplaceSectorNumber = oldSectors[1].SectorNumber
  1153  			rt.ExpectAbort(exitcode.ErrIllegalArgument, func() {
  1154  				actor.preCommitSector(rt, &params, preCommitConf{}, false)
  1155  			})
  1156  			rt.Reset()
  1157  		}
  1158  		{ // Target sector must exist
  1159  			params := *upgradeParams
  1160  			params.ReplaceSectorNumber = 999
  1161  			rt.ExpectAbort(exitcode.ErrNotFound, func() {
  1162  				actor.preCommitSector(rt, &params, preCommitConf{}, false)
  1163  			})
  1164  			rt.Reset()
  1165  		}
  1166  		{ // Target partition must exist
  1167  			params := *upgradeParams
  1168  			params.ReplaceSectorPartition = 999
  1169  			rt.ExpectAbortContainsMessage(exitcode.ErrNotFound, "no partition 999", func() {
  1170  				actor.preCommitSector(rt, &params, preCommitConf{}, false)
  1171  			})
  1172  			rt.Reset()
  1173  		}
  1174  		{ // Expiration must not be sooner than target
  1175  			params := *upgradeParams
  1176  			params.Expiration = params.Expiration - miner.WPoStProvingPeriod
  1177  			rt.ExpectAbort(exitcode.ErrIllegalArgument, func() {
  1178  				actor.preCommitSector(rt, &params, preCommitConf{}, false)
  1179  			})
  1180  			rt.Reset()
  1181  		}
  1182  		{ // Target must not be faulty
  1183  			params := *upgradeParams
  1184  			st := getState(rt)
  1185  			prevState := *st
  1186  			quant := st.QuantSpecForDeadline(dlIdx)
  1187  			deadlines, err := st.LoadDeadlines(rt.AdtStore())
  1188  			require.NoError(t, err)
  1189  			deadline, err := deadlines.LoadDeadline(rt.AdtStore(), dlIdx)
  1190  			require.NoError(t, err)
  1191  			partitions, err := deadline.PartitionsArray(rt.AdtStore())
  1192  			require.NoError(t, err)
  1193  			var partition miner.Partition
  1194  			found, err := partitions.Get(partIdx, &partition)
  1195  			require.True(t, found)
  1196  			require.NoError(t, err)
  1197  			sectorArr, err := miner.LoadSectors(rt.AdtStore(), st.Sectors)
  1198  			require.NoError(t, err)
  1199  			newFaults, _, _, err := partition.RecordFaults(rt.AdtStore(), sectorArr, bf(uint64(oldSectors[0].SectorNumber)), 100000,
  1200  				actor.sectorSize, quant)
  1201  			require.NoError(t, err)
  1202  			assertBitfieldEquals(t, newFaults, uint64(oldSectors[0].SectorNumber))
  1203  			require.NoError(t, partitions.Set(partIdx, &partition))
  1204  			deadline.Partitions, err = partitions.Root()
  1205  			require.NoError(t, err)
  1206  			deadlines.Due[dlIdx] = rt.StorePut(deadline)
  1207  			require.NoError(t, st.SaveDeadlines(rt.AdtStore(), deadlines))
  1208  			// Phew!
  1209  
  1210  			rt.ReplaceState(st)
  1211  			rt.ExpectAbort(exitcode.ErrForbidden, func() {
  1212  				actor.preCommitSector(rt, &params, preCommitConf{}, false)
  1213  			})
  1214  			rt.ReplaceState(&prevState)
  1215  			rt.Reset()
  1216  		}
  1217  
  1218  		{ // Target must not be terminated
  1219  			params := *upgradeParams
  1220  			st := getState(rt)
  1221  			prevState := *st
  1222  			quant := st.QuantSpecForDeadline(dlIdx)
  1223  			deadlines, err := st.LoadDeadlines(rt.AdtStore())
  1224  			require.NoError(t, err)
  1225  			deadline, err := deadlines.LoadDeadline(rt.AdtStore(), dlIdx)
  1226  			require.NoError(t, err)
  1227  			partitions, err := deadline.PartitionsArray(rt.AdtStore())
  1228  			require.NoError(t, err)
  1229  			var partition miner.Partition
  1230  			found, err := partitions.Get(partIdx, &partition)
  1231  			require.True(t, found)
  1232  			require.NoError(t, err)
  1233  			sectorArr, err := miner.LoadSectors(rt.AdtStore(), st.Sectors)
  1234  			require.NoError(t, err)
  1235  			result, err := partition.TerminateSectors(rt.AdtStore(), sectorArr, rt.Epoch(), bf(uint64(oldSectors[0].SectorNumber)),
  1236  				actor.sectorSize, quant)
  1237  			require.NoError(t, err)
  1238  			assertBitfieldEquals(t, result.OnTimeSectors, uint64(oldSectors[0].SectorNumber))
  1239  			require.NoError(t, partitions.Set(partIdx, &partition))
  1240  			deadline.Partitions, err = partitions.Root()
  1241  			require.NoError(t, err)
  1242  			deadlines.Due[dlIdx] = rt.StorePut(deadline)
  1243  			require.NoError(t, st.SaveDeadlines(rt.AdtStore(), deadlines))
  1244  			// Phew!
  1245  
  1246  			rt.ReplaceState(st)
  1247  			rt.ExpectAbort(exitcode.ErrNotFound, func() {
  1248  				actor.preCommitSector(rt, &params, preCommitConf{}, false)
  1249  			})
  1250  			rt.ReplaceState(&prevState)
  1251  			rt.Reset()
  1252  		}
  1253  
  1254  		// Demonstrate that the params are otherwise ok
  1255  		actor.preCommitSector(rt, upgradeParams, preCommitConf{}, false)
  1256  		rt.Verify()
  1257  		actor.checkState(rt)
  1258  	})
  1259  
  1260  	t.Run("upgrade sector before it is proven", func(t *testing.T) {
  1261  		actor := newHarness(t, periodOffset)
  1262  		rt := builderForHarness(actor).
  1263  			WithBalance(bigBalance, big.Zero()).
  1264  			Build(t)
  1265  		actor.constructAndVerify(rt)
  1266  
  1267  		// Move the current epoch forward so that the first deadline is a stable candidate for both sectors
  1268  		rt.SetEpoch(periodOffset + miner.WPoStChallengeWindow)
  1269  
  1270  		// Commit a sector to upgrade
  1271  		// Use the max sector number to make sure everything works.
  1272  		oldSector := actor.commitAndProveSector(rt, abi.MaxSectorNumber, defaultSectorExpiration, nil)
  1273  
  1274  		st := getState(rt)
  1275  		dlIdx, partIdx, err := st.FindSector(rt.AdtStore(), oldSector.SectorNumber)
  1276  		require.NoError(t, err)
  1277  
  1278  		// Reduce the epoch reward so that a new sector's initial pledge would otherwise be lesser.
  1279  		// It has to be reduced quite a lot to overcome the new sector having more power due to verified deal weight.
  1280  		actor.epochRewardSmooth = smoothing.TestingConstantEstimate(big.Div(actor.epochRewardSmooth.Estimate(), big.NewInt(20)))
  1281  
  1282  		challengeEpoch := rt.Epoch() - 1
  1283  		upgradeParams := actor.makePreCommit(200, challengeEpoch, oldSector.Expiration, []abi.DealID{1})
  1284  		upgradeParams.ReplaceCapacity = true
  1285  		upgradeParams.ReplaceSectorDeadline = dlIdx
  1286  		upgradeParams.ReplaceSectorPartition = partIdx
  1287  		upgradeParams.ReplaceSectorNumber = oldSector.SectorNumber
  1288  		upgrade := actor.preCommitSector(rt, upgradeParams, preCommitConf{}, false)
  1289  
  1290  		// Check new pre-commit in state
  1291  		assert.True(t, upgrade.Info.ReplaceCapacity)
  1292  		assert.Equal(t, upgradeParams.ReplaceSectorNumber, upgrade.Info.ReplaceSectorNumber)
  1293  
  1294  		// Old sector is unchanged
  1295  		oldSectorAgain := actor.getSector(rt, oldSector.SectorNumber)
  1296  		assert.Equal(t, oldSector, oldSectorAgain)
  1297  
  1298  		// Deposit and pledge as expected
  1299  		st = getState(rt)
  1300  		assert.Equal(t, st.PreCommitDeposits, upgrade.PreCommitDeposit)
  1301  		assert.Equal(t, st.InitialPledge, oldSector.InitialPledge)
  1302  
  1303  		// Prove new sector
  1304  		rt.SetEpoch(upgrade.PreCommitEpoch + miner.PreCommitChallengeDelay + 1)
  1305  		newSector := actor.proveCommitSectorAndConfirm(rt, upgrade, makeProveCommit(upgrade.Info.SectorNumber), proveCommitConf{})
  1306  
  1307  		// Both sectors' deposits are returned, and pledge is committed
  1308  		st = getState(rt)
  1309  		assert.Equal(t, big.Zero(), st.PreCommitDeposits)
  1310  		assert.Equal(t, st.InitialPledge, big.Add(oldSector.InitialPledge, newSector.InitialPledge))
  1311  		// new sector pledge is max of computed pledge and pledge from old sector
  1312  		assert.Equal(t, oldSector.InitialPledge, newSector.InitialPledge)
  1313  
  1314  		// Both sectors are present (in the same deadline/partition).
  1315  		deadline, partition := actor.getDeadlineAndPartition(rt, dlIdx, partIdx)
  1316  		assert.Equal(t, uint64(2), deadline.TotalSectors)
  1317  		assert.Equal(t, uint64(2), deadline.LiveSectors)
  1318  		assertEmptyBitfield(t, deadline.EarlyTerminations)
  1319  
  1320  		assertBitfieldEquals(t, partition.Sectors, uint64(newSector.SectorNumber), uint64(oldSector.SectorNumber))
  1321  		assertEmptyBitfield(t, partition.Faults)
  1322  		assertEmptyBitfield(t, partition.Recoveries)
  1323  		assertEmptyBitfield(t, partition.Terminated)
  1324  
  1325  		// The old sector's expiration has changed to the end of this proving deadline.
  1326  		// The new one expires when the old one used to.
  1327  		// The partition is registered with an expiry at both epochs.
  1328  		dQueue := actor.collectDeadlineExpirations(rt, deadline)
  1329  		dlInfo := miner.NewDeadlineInfo(st.ProvingPeriodStart, dlIdx, rt.Epoch())
  1330  		quantizedExpiration := miner.QuantSpecForDeadline(dlInfo).QuantizeUp(oldSector.Expiration)
  1331  		assert.Equal(t, map[abi.ChainEpoch][]uint64{
  1332  			dlInfo.NextNotElapsed().Last(): {uint64(0)},
  1333  			quantizedExpiration:            {uint64(0)},
  1334  		}, dQueue)
  1335  
  1336  		pQueue := actor.collectPartitionExpirations(rt, partition)
  1337  		assertBitfieldEquals(t, pQueue[dlInfo.NextNotElapsed().Last()].OnTimeSectors, uint64(oldSector.SectorNumber))
  1338  		assertBitfieldEquals(t, pQueue[quantizedExpiration].OnTimeSectors, uint64(newSector.SectorNumber))
  1339  
  1340  		// advance to sector proving deadline
  1341  		dlInfo = actor.deadline(rt)
  1342  		for dlIdx != dlInfo.Index {
  1343  			advanceDeadline(rt, actor, &cronConfig{})
  1344  			dlInfo = actor.deadline(rt)
  1345  		}
  1346  
  1347  		// PoSt both sectors. They both gain power and no penalties are incurred.
  1348  		rt.SetEpoch(dlInfo.Last())
  1349  		oldPower := miner.NewPowerPair(big.NewInt(int64(actor.sectorSize)), miner.QAPowerForSector(actor.sectorSize, oldSector))
  1350  		newPower := miner.NewPowerPair(big.NewInt(int64(actor.sectorSize)), miner.QAPowerForSector(actor.sectorSize, newSector))
  1351  		expectedPower := oldPower.Add(newPower)
  1352  		partitions := []miner.PoStPartition{
  1353  			{Index: partIdx, Skipped: bitfield.New()},
  1354  		}
  1355  		actor.submitWindowPoSt(rt, dlInfo, partitions, []*miner.SectorOnChainInfo{newSector, oldSector}, &poStConfig{
  1356  			expectedPowerDelta: expectedPower,
  1357  		})
  1358  
  1359  		// replaced sector expires at cron, removing its power and pledge.
  1360  		expectedPowerDelta := oldPower.Neg()
  1361  		actor.onDeadlineCron(rt, &cronConfig{
  1362  			expiredSectorsPowerDelta:  &expectedPowerDelta,
  1363  			expiredSectorsPledgeDelta: oldSector.InitialPledge.Neg(),
  1364  			expectedEnrollment:        rt.Epoch() + miner.WPoStChallengeWindow,
  1365  		})
  1366  		actor.checkState(rt)
  1367  	})
  1368  
  1369  	t.Run("declare fault for replaced cc upgrade sector doesn't double subtract power", func(t *testing.T) {
  1370  		actor := newHarness(t, periodOffset)
  1371  		rt := builderForHarness(actor).
  1372  			WithBalance(bigBalance, big.Zero()).
  1373  			Build(t)
  1374  		actor.constructAndVerify(rt)
  1375  
  1376  		oldSector, newSector := actor.commitProveAndUpgradeSector(rt, 100, 200, defaultSectorExpiration, []abi.DealID{1})
  1377  
  1378  		st := getState(rt)
  1379  		dlIdx, partIdx, err := st.FindSector(rt.AdtStore(), oldSector.SectorNumber)
  1380  		require.NoError(t, err)
  1381  
  1382  		advanceToEpochWithCron(rt, actor, rt.Epoch())
  1383  		// now declare old sector faulty
  1384  		actor.declareFaults(rt, oldSector)
  1385  
  1386  		pIdx := uint64(0)
  1387  		deadline, partition := actor.getDeadlineAndPartition(rt, dlIdx, partIdx)
  1388  		dQueue := actor.collectDeadlineExpirations(rt, deadline)
  1389  		dlInfo := miner.NewDeadlineInfo(st.ProvingPeriodStart, dlIdx, rt.Epoch())
  1390  		expectedReplacedExpiration := miner.QuantSpecForDeadline(dlInfo).QuantizeUp(rt.Epoch() + miner.FaultMaxAge)
  1391  		quantizedExpiration := miner.QuantSpecForDeadline(dlInfo).QuantizeUp(oldSector.Expiration)
  1392  
  1393  		// deadling marks expirations for partition at expiration epoch
  1394  		assert.Equal(t, map[abi.ChainEpoch][]uint64{
  1395  			dlInfo.NextNotElapsed().Last(): {pIdx},
  1396  			expectedReplacedExpiration:     {pIdx},
  1397  			quantizedExpiration:            {pIdx},
  1398  		}, dQueue)
  1399  
  1400  		// but partitions expiration set at that epoch is empty
  1401  		queue, err := miner.LoadExpirationQueue(rt.AdtStore(), partition.ExpirationsEpochs, miner.QuantSpecForDeadline(dlInfo), miner.PartitionExpirationAmtBitwidth)
  1402  		require.NoError(t, err)
  1403  		var es miner.ExpirationSet
  1404  		expirationSetNotEmpty, err := queue.Get(uint64(expectedReplacedExpiration), &es)
  1405  		require.NoError(t, err)
  1406  		assert.False(t, expirationSetNotEmpty)
  1407  
  1408  		// advance to sector proving deadline
  1409  		dlInfo = actor.deadline(rt)
  1410  		for dlIdx != dlInfo.Index {
  1411  			advanceDeadline(rt, actor, &cronConfig{})
  1412  			dlInfo = actor.deadline(rt)
  1413  		}
  1414  
  1415  		// submit post for new sector. Power is added for new sector and no penalties are paid yet
  1416  		rt.SetEpoch(dlInfo.Last())
  1417  		newPower := miner.QAPowerForSector(actor.sectorSize, newSector)
  1418  		partitions := []miner.PoStPartition{
  1419  			{Index: pIdx, Skipped: bitfield.New()},
  1420  		}
  1421  		// Old sector is faulty, so expect new sector twice in PoSt.
  1422  		actor.submitWindowPoSt(rt, dlInfo, partitions, []*miner.SectorOnChainInfo{newSector, newSector}, &poStConfig{
  1423  			expectedPowerDelta: miner.NewPowerPair(big.NewInt(int64(actor.sectorSize)), newPower),
  1424  		})
  1425  
  1426  		// At proving period cron expect to pay declared fee for old sector
  1427  		// and to have its pledge requirement deducted indicating it has expired.
  1428  		// Importantly, power is NOT removed, because it was taken when fault was declared.
  1429  		oldPower := miner.QAPowerForSector(actor.sectorSize, oldSector)
  1430  		expectedFee := miner.PledgePenaltyForContinuedFault(actor.epochRewardSmooth, actor.epochQAPowerSmooth, oldPower)
  1431  		expectedPowerDelta := miner.NewPowerPairZero()
  1432  		actor.applyRewards(rt, bigRewards, big.Zero())
  1433  		actor.onDeadlineCron(rt, &cronConfig{
  1434  			continuedFaultsPenalty:    expectedFee,
  1435  			expiredSectorsPledgeDelta: oldSector.InitialPledge.Neg(),
  1436  			expiredSectorsPowerDelta:  &expectedPowerDelta,
  1437  			expectedEnrollment:        rt.Epoch() + miner.WPoStChallengeWindow,
  1438  		})
  1439  		actor.checkState(rt)
  1440  	})
  1441  
  1442  	t.Run("skip replaced sector in its last PoSt", func(t *testing.T) {
  1443  		actor := newHarness(t, periodOffset)
  1444  		rt := builderForHarness(actor).
  1445  			WithBalance(bigBalance, big.Zero()).
  1446  			Build(t)
  1447  		actor.constructAndVerify(rt)
  1448  		actor.applyRewards(rt, bigRewards, big.Zero())
  1449  
  1450  		oldSector, newSector := actor.commitProveAndUpgradeSector(rt, 100, 200, defaultSectorExpiration, []abi.DealID{1})
  1451  
  1452  		st := getState(rt)
  1453  		dlIdx, pIdx, err := st.FindSector(rt.AdtStore(), oldSector.SectorNumber)
  1454  		require.NoError(t, err)
  1455  
  1456  		// advance to sector proving deadline
  1457  		dlInfo := actor.deadline(rt)
  1458  		for dlIdx != dlInfo.Index {
  1459  			advanceDeadline(rt, actor, &cronConfig{})
  1460  			dlInfo = actor.deadline(rt)
  1461  		}
  1462  
  1463  		// skip old sector when submitting post. Expect newSector to fill place of old sector in proof.
  1464  		// Miner should gain power for new sector, lose power for old sector (with no penalty).
  1465  		rt.SetEpoch(dlInfo.Last())
  1466  
  1467  		oldQAPower := miner.QAPowerForSector(actor.sectorSize, oldSector)
  1468  		newQAPower := miner.QAPowerForSector(actor.sectorSize, newSector)
  1469  		expectedPowerDelta := miner.NewPowerPair(big.Zero(), big.Sub(newQAPower, oldQAPower))
  1470  
  1471  		partitions := []miner.PoStPartition{
  1472  			{Index: pIdx, Skipped: bf(uint64(oldSector.SectorNumber))},
  1473  		}
  1474  		actor.submitWindowPoSt(rt, dlInfo, partitions, []*miner.SectorOnChainInfo{newSector, newSector}, &poStConfig{
  1475  			expectedPowerDelta: expectedPowerDelta,
  1476  		})
  1477  
  1478  		// At proving period cron expect to pay continued fee for old (now faulty) sector
  1479  		// and to have its pledge requirement deducted indicating it has expired.
  1480  		// Importantly, power is NOT removed, because it was taken when sector was skipped in Windowe PoSt.
  1481  		faultFee := miner.PledgePenaltyForContinuedFault(actor.epochRewardSmooth, actor.epochQAPowerSmooth, oldQAPower)
  1482  
  1483  		actor.onDeadlineCron(rt, &cronConfig{
  1484  			continuedFaultsPenalty:    faultFee,
  1485  			expiredSectorsPledgeDelta: oldSector.InitialPledge.Neg(),
  1486  			expectedEnrollment:        rt.Epoch() + miner.WPoStChallengeWindow,
  1487  		})
  1488  		actor.checkState(rt)
  1489  	})
  1490  
  1491  	t.Run("skip PoSt altogether on replaced sector expiry", func(t *testing.T) {
  1492  		actor := newHarness(t, periodOffset)
  1493  		rt := builderForHarness(actor).
  1494  			WithBalance(bigBalance, big.Zero()).
  1495  			Build(t)
  1496  		actor.constructAndVerify(rt)
  1497  
  1498  		oldSector, _ := actor.commitProveAndUpgradeSector(rt, 100, 200, defaultSectorExpiration, []abi.DealID{1})
  1499  
  1500  		st := getState(rt)
  1501  		dlIdx, _, err := st.FindSector(rt.AdtStore(), oldSector.SectorNumber)
  1502  		require.NoError(t, err)
  1503  
  1504  		// advance to sector proving deadline
  1505  		dlInfo := actor.deadline(rt)
  1506  		for dlIdx != dlInfo.Index {
  1507  			advanceDeadline(rt, actor, &cronConfig{})
  1508  			dlInfo = actor.deadline(rt)
  1509  		}
  1510  		rt.SetEpoch(dlInfo.Last())
  1511  
  1512  		// do not PoSt
  1513  		// expect old sector to lose power (new sector hasn't added any yet)
  1514  		// both sectors are detected faulty for the first time, with no penalty.
  1515  		oldQAPower := miner.QAPowerForSector(actor.sectorSize, oldSector)
  1516  		expectedPowerDelta := miner.NewPowerPair(big.NewInt(int64(actor.sectorSize)), oldQAPower).Neg()
  1517  
  1518  		// At cron, expect both sectors to be treated as undeclared faults.
  1519  		// The replaced sector will expire anyway, so its pledge will be removed.
  1520  		actor.onDeadlineCron(rt, &cronConfig{
  1521  			expiredSectorsPowerDelta:  &expectedPowerDelta,
  1522  			expiredSectorsPledgeDelta: oldSector.InitialPledge.Neg(),
  1523  			expectedEnrollment:        rt.Epoch() + miner.WPoStChallengeWindow,
  1524  		})
  1525  		actor.checkState(rt)
  1526  	})
  1527  
  1528  	t.Run("terminate replaced sector early", func(t *testing.T) {
  1529  		actor := newHarness(t, periodOffset)
  1530  		rt := builderForHarness(actor).
  1531  			WithBalance(bigBalance, big.Zero()).
  1532  			Build(t)
  1533  		actor.constructAndVerify(rt)
  1534  
  1535  		// create sector and upgrade it
  1536  		oldSector, newSector := actor.commitProveAndUpgradeSector(rt, 100, 200, defaultSectorExpiration, []abi.DealID{1})
  1537  
  1538  		st := getState(rt)
  1539  		dlIdx, partIdx, err := st.FindSector(rt.AdtStore(), oldSector.SectorNumber)
  1540  		require.NoError(t, err)
  1541  
  1542  		// now terminate replaced sector
  1543  		sectorPower := miner.QAPowerForSector(actor.sectorSize, oldSector)
  1544  		expectedFee := miner.PledgePenaltyForTermination(oldSector.ExpectedDayReward, rt.Epoch()-oldSector.Activation,
  1545  			oldSector.ExpectedStoragePledge, actor.epochQAPowerSmooth, sectorPower, actor.epochRewardSmooth,
  1546  			oldSector.ReplacedDayReward, oldSector.ReplacedSectorAge)
  1547  		actor.applyRewards(rt, bigRewards, big.Zero())
  1548  		powerDelta, pledgeDelta := actor.terminateSectors(rt, bf(uint64(oldSector.SectorNumber)), expectedFee)
  1549  
  1550  		// power and pledge should have been removed
  1551  		assert.Equal(t, miner.NewPowerPair(big.NewInt(int64(actor.sectorSize)), sectorPower).Neg(), powerDelta)
  1552  		assert.Equal(t, big.Sum(oldSector.InitialPledge.Neg(), expectedFee.Neg()), pledgeDelta)
  1553  
  1554  		// advance to sector proving deadline
  1555  		dlInfo := actor.deadline(rt)
  1556  		for dlIdx != dlInfo.Index {
  1557  			advanceDeadline(rt, actor, &cronConfig{})
  1558  			dlInfo = actor.deadline(rt)
  1559  		}
  1560  
  1561  		// oldSector is no longer active, so expect newSector twice in validation; once for its proof and once
  1562  		// to replace oldSector. Power is added for new sector and no penalties are paid.
  1563  		rt.SetEpoch(dlInfo.Last())
  1564  		newPower := miner.QAPowerForSector(actor.sectorSize, newSector)
  1565  		partitions := []miner.PoStPartition{
  1566  			{Index: partIdx, Skipped: bitfield.New()},
  1567  		}
  1568  		actor.submitWindowPoSt(rt, dlInfo, partitions, []*miner.SectorOnChainInfo{newSector, newSector}, &poStConfig{
  1569  			expectedPowerDelta: miner.NewPowerPair(big.NewInt(int64(actor.sectorSize)), newPower),
  1570  		})
  1571  
  1572  		// Nothing interesting happens at cron.
  1573  		// Importantly, power and pledge are NOT removed. This happened when sector was terminated
  1574  		actor.onDeadlineCron(rt, &cronConfig{
  1575  			expectedEnrollment: rt.Epoch() + miner.WPoStChallengeWindow,
  1576  		})
  1577  		actor.checkState(rt)
  1578  	})
  1579  
  1580  	t.Run("extend a replaced sector's expiration", func(t *testing.T) {
  1581  		actor := newHarness(t, periodOffset)
  1582  		rt := builderForHarness(actor).
  1583  			WithBalance(bigBalance, big.Zero()).
  1584  			Build(t)
  1585  		actor.constructAndVerify(rt)
  1586  
  1587  		// create sector and upgrade it
  1588  		oldSector, newSector := actor.commitProveAndUpgradeSector(rt, 100, 200, defaultSectorExpiration, []abi.DealID{1})
  1589  
  1590  		st := getState(rt)
  1591  		dlIdx, partIdx, err := st.FindSector(rt.AdtStore(), oldSector.SectorNumber)
  1592  		require.NoError(t, err)
  1593  
  1594  		params := &miner.ExtendSectorExpirationParams{
  1595  			Extensions: []miner.ExpirationExtension{{
  1596  				Deadline:      dlIdx,
  1597  				Partition:     partIdx,
  1598  				Sectors:       bf(uint64(oldSector.SectorNumber)),
  1599  				NewExpiration: rt.Epoch() + 250*builtin.EpochsInDay,
  1600  			}},
  1601  		}
  1602  		actor.extendSectors(rt, params)
  1603  
  1604  		// advance to sector proving deadline
  1605  		dlInfo := actor.deadline(rt)
  1606  		for dlIdx != dlInfo.Index {
  1607  			advanceDeadline(rt, actor, &cronConfig{})
  1608  			dlInfo = actor.deadline(rt)
  1609  		}
  1610  
  1611  		// both sectors are now active and not set to expire
  1612  		rt.SetEpoch(dlInfo.Last())
  1613  		newPower := miner.QAPowerForSector(actor.sectorSize, newSector)
  1614  		partitions := []miner.PoStPartition{
  1615  			{Index: partIdx, Skipped: bitfield.New()},
  1616  		}
  1617  		actor.submitWindowPoSt(rt, dlInfo, partitions, []*miner.SectorOnChainInfo{oldSector, newSector}, &poStConfig{
  1618  			expectedPowerDelta: miner.NewPowerPair(big.NewInt(int64(actor.sectorSize)), newPower),
  1619  		})
  1620  
  1621  		// Nothing interesting happens at cron because both sectors are active
  1622  		actor.onDeadlineCron(rt, &cronConfig{
  1623  			expectedEnrollment: rt.Epoch() + miner.WPoStChallengeWindow,
  1624  		})
  1625  
  1626  		actor.checkState(rt)
  1627  	})
  1628  
  1629  	t.Run("fault and recover a replaced sector", func(t *testing.T) {
  1630  		actor := newHarness(t, periodOffset)
  1631  		rt := builderForHarness(actor).
  1632  			WithBalance(bigBalance, big.Zero()).
  1633  			Build(t)
  1634  		actor.constructAndVerify(rt)
  1635  
  1636  		// create sector and upgrade it
  1637  		oldSector, newSector := actor.commitProveAndUpgradeSector(rt, 100, 200, defaultSectorExpiration, []abi.DealID{1})
  1638  
  1639  		advanceToEpochWithCron(rt, actor, rt.Epoch())
  1640  
  1641  		// declare replaced sector faulty
  1642  		powerDelta := actor.declareFaults(rt, oldSector)
  1643  
  1644  		// power for old sector should have been removed
  1645  		oldQAPower := miner.QAPowerForSector(actor.sectorSize, oldSector)
  1646  		oldSectorPower := miner.NewPowerPair(big.NewInt(int64(actor.sectorSize)), oldQAPower)
  1647  		assert.Equal(t, oldSectorPower.Neg(), powerDelta)
  1648  
  1649  		st := getState(rt)
  1650  		dlIdx, partIdx, err := st.FindSector(rt.AdtStore(), oldSector.SectorNumber)
  1651  		require.NoError(t, err)
  1652  
  1653  		// recover replaced sector
  1654  		actor.declareRecoveries(rt, dlIdx, partIdx, bf(uint64(oldSector.SectorNumber)), big.Zero())
  1655  
  1656  		// advance to sector proving deadline
  1657  		dlInfo := actor.deadline(rt)
  1658  		for dlIdx != dlInfo.Index {
  1659  			advanceDeadline(rt, actor, &cronConfig{})
  1660  			dlInfo = actor.deadline(rt)
  1661  		}
  1662  
  1663  		// both sectors now need to be proven.
  1664  		// Upon success, new sector will gain power and replaced sector will briefly regain power.
  1665  		rt.SetEpoch(dlInfo.Last())
  1666  		newQAPower := miner.QAPowerForSector(actor.sectorSize, newSector)
  1667  		newSectorPower := miner.NewPowerPair(big.NewInt(int64(actor.sectorSize)), newQAPower)
  1668  		expectedPowerDelta := oldSectorPower.Add(newSectorPower)
  1669  
  1670  		partitions := []miner.PoStPartition{
  1671  			{Index: partIdx, Skipped: bitfield.New()},
  1672  		}
  1673  		actor.submitWindowPoSt(rt, dlInfo, partitions, []*miner.SectorOnChainInfo{oldSector, newSector}, &poStConfig{
  1674  			expectedPowerDelta: expectedPowerDelta,
  1675  		})
  1676  
  1677  		// At cron replaced sector's power is removed because it expires, and its initial pledge is removed
  1678  		expectedPowerDelta = oldSectorPower.Neg()
  1679  		actor.onDeadlineCron(rt, &cronConfig{
  1680  			expiredSectorsPowerDelta:  &expectedPowerDelta,
  1681  			expiredSectorsPledgeDelta: oldSector.InitialPledge.Neg(),
  1682  			expectedEnrollment:        rt.Epoch() + miner.WPoStChallengeWindow,
  1683  		})
  1684  		actor.checkState(rt)
  1685  	})
  1686  
  1687  	t.Run("try to upgrade committed capacity sector twice", func(t *testing.T) {
  1688  		actor := newHarness(t, periodOffset)
  1689  		rt := builderForHarness(actor).
  1690  			WithBalance(bigBalance, big.Zero()).
  1691  			Build(t)
  1692  		actor.constructAndVerify(rt)
  1693  
  1694  		// Move the current epoch forward so that the first deadline is a stable candidate for both sectors
  1695  		rt.SetEpoch(periodOffset + miner.WPoStChallengeWindow)
  1696  
  1697  		// Commit a sector to upgrade
  1698  		// Use the max sector number to make sure everything works.
  1699  		oldSector := actor.commitAndProveSector(rt, abi.MaxSectorNumber, defaultSectorExpiration, nil)
  1700  
  1701  		// advance cron to activate power.
  1702  		advanceAndSubmitPoSts(rt, actor, oldSector)
  1703  
  1704  		st := getState(rt)
  1705  		dlIdx, partIdx, err := st.FindSector(rt.AdtStore(), oldSector.SectorNumber)
  1706  		require.NoError(t, err)
  1707  
  1708  		// Reduce the epoch reward so that a new sector's initial pledge would otherwise be lesser.
  1709  		actor.epochRewardSmooth = smoothing.TestingConstantEstimate(big.Div(actor.epochRewardSmooth.Estimate(), big.NewInt(20)))
  1710  
  1711  		challengeEpoch := rt.Epoch() - 1
  1712  
  1713  		// Upgrade 1
  1714  		upgradeParams1 := actor.makePreCommit(200, challengeEpoch, oldSector.Expiration, []abi.DealID{1})
  1715  		upgradeParams1.ReplaceCapacity = true
  1716  		upgradeParams1.ReplaceSectorDeadline = dlIdx
  1717  		upgradeParams1.ReplaceSectorPartition = partIdx
  1718  		upgradeParams1.ReplaceSectorNumber = oldSector.SectorNumber
  1719  		upgrade1 := actor.preCommitSector(rt, upgradeParams1, preCommitConf{}, false)
  1720  
  1721  		// Check new pre-commit in state
  1722  		assert.True(t, upgrade1.Info.ReplaceCapacity)
  1723  		assert.Equal(t, upgradeParams1.ReplaceSectorNumber, upgrade1.Info.ReplaceSectorNumber)
  1724  
  1725  		// Upgrade 2
  1726  		upgradeParams2 := actor.makePreCommit(201, challengeEpoch, oldSector.Expiration, []abi.DealID{1})
  1727  		upgradeParams2.ReplaceCapacity = true
  1728  		upgradeParams2.ReplaceSectorDeadline = dlIdx
  1729  		upgradeParams2.ReplaceSectorPartition = partIdx
  1730  		upgradeParams2.ReplaceSectorNumber = oldSector.SectorNumber
  1731  		upgrade2 := actor.preCommitSector(rt, upgradeParams2, preCommitConf{}, false)
  1732  
  1733  		// Check new pre-commit in state
  1734  		assert.True(t, upgrade2.Info.ReplaceCapacity)
  1735  		assert.Equal(t, upgradeParams2.ReplaceSectorNumber, upgrade2.Info.ReplaceSectorNumber)
  1736  
  1737  		// Old sector is unchanged
  1738  		oldSectorAgain := actor.getSector(rt, oldSector.SectorNumber)
  1739  		assert.Equal(t, oldSector, oldSectorAgain)
  1740  
  1741  		// Deposit and pledge as expected
  1742  		st = getState(rt)
  1743  		assert.Equal(t, st.PreCommitDeposits, big.Add(upgrade1.PreCommitDeposit, upgrade2.PreCommitDeposit))
  1744  		assert.Equal(t, st.InitialPledge, oldSector.InitialPledge)
  1745  
  1746  		// Prove new sectors
  1747  		rt.SetEpoch(upgrade1.PreCommitEpoch + miner.PreCommitChallengeDelay + 1)
  1748  		actor.proveCommitSector(rt, upgrade1, makeProveCommit(upgrade1.Info.SectorNumber))
  1749  		actor.proveCommitSector(rt, upgrade2, makeProveCommit(upgrade2.Info.SectorNumber))
  1750  
  1751  		// confirm both.
  1752  		actor.confirmSectorProofsValid(rt, proveCommitConf{}, upgrade1, upgrade2)
  1753  
  1754  		newSector1 := actor.getSector(rt, upgrade1.Info.SectorNumber)
  1755  		newSector2 := actor.getSector(rt, upgrade2.Info.SectorNumber)
  1756  
  1757  		// All three sectors pre-commit deposits are released, and have pledge committed.
  1758  		st = getState(rt)
  1759  		assert.Equal(t, big.Zero(), st.PreCommitDeposits)
  1760  		assert.Equal(t, st.InitialPledge, big.Sum(
  1761  			oldSector.InitialPledge, newSector1.InitialPledge, newSector2.InitialPledge,
  1762  		))
  1763  		// Both new sectors' pledge are at least the old sector's pledge
  1764  		assert.Equal(t, oldSector.InitialPledge, newSector1.InitialPledge)
  1765  		assert.Equal(t, oldSector.InitialPledge, newSector2.InitialPledge)
  1766  
  1767  		// All three sectors are present (in the same deadline/partition).
  1768  		deadline, partition := actor.getDeadlineAndPartition(rt, dlIdx, partIdx)
  1769  		assert.Equal(t, uint64(3), deadline.TotalSectors)
  1770  		assert.Equal(t, uint64(3), deadline.LiveSectors)
  1771  		assertEmptyBitfield(t, deadline.EarlyTerminations)
  1772  
  1773  		assertBitfieldEquals(t, partition.Sectors,
  1774  			uint64(newSector1.SectorNumber),
  1775  			uint64(newSector2.SectorNumber),
  1776  			uint64(oldSector.SectorNumber))
  1777  		assertEmptyBitfield(t, partition.Faults)
  1778  		assertEmptyBitfield(t, partition.Recoveries)
  1779  		assertEmptyBitfield(t, partition.Terminated)
  1780  
  1781  		// The old sector's expiration has changed to the end of this proving deadline.
  1782  		// The new one expires when the old one used to.
  1783  		// The partition is registered with an expiry at both epochs.
  1784  		dQueue := actor.collectDeadlineExpirations(rt, deadline)
  1785  		dlInfo := miner.NewDeadlineInfo(st.ProvingPeriodStart, dlIdx, rt.Epoch())
  1786  		quantizedExpiration := miner.QuantSpecForDeadline(dlInfo).QuantizeUp(oldSector.Expiration)
  1787  		assert.Equal(t, map[abi.ChainEpoch][]uint64{
  1788  			dlInfo.NextNotElapsed().Last(): {uint64(0)},
  1789  			quantizedExpiration:            {uint64(0)},
  1790  		}, dQueue)
  1791  
  1792  		pQueue := actor.collectPartitionExpirations(rt, partition)
  1793  		assertBitfieldEquals(t, pQueue[dlInfo.NextNotElapsed().Last()].OnTimeSectors, uint64(oldSector.SectorNumber))
  1794  		assertBitfieldEquals(t, pQueue[quantizedExpiration].OnTimeSectors,
  1795  			uint64(newSector1.SectorNumber), uint64(newSector2.SectorNumber),
  1796  		)
  1797  
  1798  		// Roll forward to the beginning of the next iteration of this deadline
  1799  		advanceToEpochWithCron(rt, actor, dlInfo.NextNotElapsed().Open)
  1800  
  1801  		// Fail to submit PoSt. This means that both sectors will be detected faulty (no penalty).
  1802  		// Expect the old sector to be marked as terminated.
  1803  		allSectors := []*miner.SectorOnChainInfo{oldSector, newSector1, newSector2}
  1804  		lostPower := actor.powerPairForSectors(allSectors[:1]).Neg() // new sectors not active yet.
  1805  		faultExpiration := miner.QuantSpecForDeadline(dlInfo).QuantizeUp(dlInfo.NextNotElapsed().Last() + miner.FaultMaxAge)
  1806  
  1807  		advanceDeadline(rt, actor, &cronConfig{
  1808  			detectedFaultsPowerDelta:  &lostPower,
  1809  			expiredSectorsPledgeDelta: oldSector.InitialPledge.Neg(),
  1810  		})
  1811  
  1812  		// The old sector is marked as terminated
  1813  		st = getState(rt)
  1814  		deadline, partition = actor.getDeadlineAndPartition(rt, dlIdx, partIdx)
  1815  		assert.Equal(t, uint64(3), deadline.TotalSectors)
  1816  		assert.Equal(t, uint64(2), deadline.LiveSectors)
  1817  		assertBitfieldEquals(t, partition.Sectors,
  1818  			uint64(newSector1.SectorNumber),
  1819  			uint64(newSector2.SectorNumber),
  1820  			uint64(oldSector.SectorNumber),
  1821  		)
  1822  		assertBitfieldEquals(t, partition.Terminated, uint64(oldSector.SectorNumber))
  1823  		assertBitfieldEquals(t, partition.Faults,
  1824  			uint64(newSector1.SectorNumber),
  1825  			uint64(newSector2.SectorNumber),
  1826  		)
  1827  		newPower := miner.PowerForSectors(actor.sectorSize, allSectors[1:])
  1828  		assert.True(t, newPower.Equals(partition.LivePower))
  1829  		assert.True(t, newPower.Equals(partition.FaultyPower))
  1830  
  1831  		// we expect the expiration to be scheduled twice, once early
  1832  		// and once on-time.
  1833  		dQueue = actor.collectDeadlineExpirations(rt, deadline)
  1834  		assert.Equal(t, map[abi.ChainEpoch][]uint64{
  1835  			miner.QuantSpecForDeadline(dlInfo).QuantizeUp(newSector1.Expiration): {uint64(0)},
  1836  			faultExpiration: {uint64(0)},
  1837  		}, dQueue)
  1838  
  1839  		// Old sector gone from pledge
  1840  		assert.Equal(t, st.InitialPledge, big.Add(newSector1.InitialPledge, newSector2.InitialPledge))
  1841  		actor.checkState(rt)
  1842  	})
  1843  }
  1844  
  1845  func TestWindowPost(t *testing.T) {
  1846  	periodOffset := abi.ChainEpoch(100)
  1847  	actor := newHarness(t, periodOffset)
  1848  	actor.setProofType(abi.RegisteredSealProof_StackedDrg2KiBV1_1)
  1849  	precommitEpoch := abi.ChainEpoch(1)
  1850  	builder := builderForHarness(actor).
  1851  		WithEpoch(precommitEpoch).
  1852  		WithBalance(bigBalance, big.Zero())
  1853  
  1854  	testBasicPoSt := func(disputeSucceed bool) {
  1855  		proofs := makePoStProofs(actor.windowPostProofType)
  1856  
  1857  		rt := builder.Build(t)
  1858  		actor.constructAndVerify(rt)
  1859  		store := rt.AdtStore()
  1860  		sector := actor.commitAndProveSectors(rt, 1, defaultSectorExpiration, nil, true)[0]
  1861  		pwr := miner.PowerForSector(actor.sectorSize, sector)
  1862  
  1863  		st := getState(rt)
  1864  		dlIdx, pIdx, err := st.FindSector(store, sector.SectorNumber)
  1865  		require.NoError(t, err)
  1866  
  1867  		// Skip over deadlines until the beginning of the one with the new sector
  1868  		dlinfo := actor.deadline(rt)
  1869  		for dlinfo.Index != dlIdx {
  1870  			dlinfo = advanceDeadline(rt, actor, &cronConfig{})
  1871  		}
  1872  
  1873  		// Submit PoSt
  1874  		partitions := []miner.PoStPartition{
  1875  			{Index: pIdx, Skipped: bitfield.New()},
  1876  		}
  1877  		actor.submitWindowPoStRaw(rt, dlinfo, partitions, []*miner.SectorOnChainInfo{sector}, proofs, &poStConfig{
  1878  			expectedPowerDelta: pwr,
  1879  		})
  1880  
  1881  		// Verify proof recorded
  1882  		deadline := actor.getDeadline(rt, dlIdx)
  1883  		assertBitfieldEquals(t, deadline.PartitionsPoSted, pIdx)
  1884  
  1885  		postsCid := deadline.OptimisticPoStSubmissions
  1886  
  1887  		posts, err := adt.AsArray(store, postsCid, miner.DeadlineOptimisticPoStSubmissionsAmtBitwidth)
  1888  		require.NoError(t, err)
  1889  		require.EqualValues(t, posts.Length(), 1)
  1890  		var post miner.WindowedPoSt
  1891  		found, err := posts.Get(0, &post)
  1892  		require.NoError(t, err)
  1893  		require.True(t, found)
  1894  		assertBitfieldEquals(t, post.Partitions, pIdx)
  1895  
  1896  		// Advance to end-of-deadline cron to verify no penalties.
  1897  		advanceDeadline(rt, actor, &cronConfig{})
  1898  		actor.checkState(rt)
  1899  
  1900  		deadline = actor.getDeadline(rt, dlIdx)
  1901  
  1902  		// Proofs should exist in snapshot.
  1903  		require.Equal(t, deadline.OptimisticPoStSubmissionsSnapshot, postsCid)
  1904  
  1905  		var result *poStDisputeResult
  1906  		if disputeSucceed {
  1907  			expectedFee := miner.PledgePenaltyForInvalidWindowPoSt(actor.epochRewardSmooth, actor.epochQAPowerSmooth, pwr.QA)
  1908  			result = &poStDisputeResult{
  1909  				expectedPowerDelta:  pwr.Neg(),
  1910  				expectedPenalty:     expectedFee,
  1911  				expectedReward:      miner.BaseRewardForDisputedWindowPoSt,
  1912  				expectedPledgeDelta: big.Zero(),
  1913  			}
  1914  		}
  1915  		actor.disputeWindowPoSt(rt, dlinfo, 0, []*miner.SectorOnChainInfo{sector}, result)
  1916  	}
  1917  
  1918  	t.Run("test proof", func(t *testing.T) {
  1919  		testBasicPoSt(true)
  1920  	})
  1921  
  1922  	t.Run("test bad proof accepted and disputed", func(t *testing.T) {
  1923  		testBasicPoSt(false)
  1924  	})
  1925  
  1926  	t.Run("test duplicate proof rejected", func(t *testing.T) {
  1927  		rt := builder.Build(t)
  1928  		actor.constructAndVerify(rt)
  1929  		store := rt.AdtStore()
  1930  		sector := actor.commitAndProveSectors(rt, 1, defaultSectorExpiration, nil, true)[0]
  1931  		pwr := miner.PowerForSector(actor.sectorSize, sector)
  1932  
  1933  		st := getState(rt)
  1934  		dlIdx, pIdx, err := st.FindSector(store, sector.SectorNumber)
  1935  		require.NoError(t, err)
  1936  
  1937  		// Skip over deadlines until the beginning of the one with the new sector
  1938  		dlinfo := actor.deadline(rt)
  1939  		for dlinfo.Index != dlIdx {
  1940  			dlinfo = advanceDeadline(rt, actor, &cronConfig{})
  1941  		}
  1942  
  1943  		// Submit PoSt
  1944  		partitions := []miner.PoStPartition{
  1945  			{Index: pIdx, Skipped: bitfield.New()},
  1946  		}
  1947  		actor.submitWindowPoSt(rt, dlinfo, partitions, []*miner.SectorOnChainInfo{sector}, &poStConfig{
  1948  			expectedPowerDelta: pwr,
  1949  		})
  1950  
  1951  		// Verify proof recorded
  1952  		deadline := actor.getDeadline(rt, dlIdx)
  1953  		assertBitfieldEquals(t, deadline.PartitionsPoSted, pIdx)
  1954  
  1955  		// Submit a duplicate proof for the same partition. This will be rejected because after ignoring the
  1956  		// already-proven partition, there are no sectors remaining.
  1957  		// The skipped fault declared here has no effect.
  1958  		commitRand := abi.Randomness("chaincommitment")
  1959  		params := miner.SubmitWindowedPoStParams{
  1960  			Deadline: dlIdx,
  1961  			Partitions: []miner.PoStPartition{{
  1962  				Index:   pIdx,
  1963  				Skipped: bf(uint64(sector.SectorNumber)),
  1964  			}},
  1965  			Proofs:           makePoStProofs(actor.windowPostProofType),
  1966  			ChainCommitEpoch: dlinfo.Challenge,
  1967  			ChainCommitRand:  commitRand,
  1968  		}
  1969  		expectQueryNetworkInfo(rt, actor)
  1970  		rt.SetCaller(actor.worker, builtin.AccountActorCodeID)
  1971  
  1972  		// From version 7, a duplicate is explicitly rejected.
  1973  		rt.ExpectValidateCallerAddr(append(actor.controlAddrs, actor.owner, actor.worker)...)
  1974  		rt.ExpectGetRandomnessTickets(crypto.DomainSeparationTag_PoStChainCommit, dlinfo.Challenge, nil, commitRand)
  1975  		rt.ExpectAbortContainsMessage(exitcode.ErrIllegalArgument, "partition already proven", func() {
  1976  			rt.Call(actor.a.SubmitWindowedPoSt, &params)
  1977  		})
  1978  		rt.Reset()
  1979  
  1980  		// Advance to end-of-deadline cron to verify no penalties.
  1981  		advanceDeadline(rt, actor, &cronConfig{})
  1982  		actor.checkState(rt)
  1983  	})
  1984  
  1985  	t.Run("test duplicate proof rejected with many partitions", func(t *testing.T) {
  1986  		rt := builder.Build(t)
  1987  		actor.constructAndVerify(rt)
  1988  		store := rt.AdtStore()
  1989  		// Commit more sectors than fit in one partition in every eligible deadline, overflowing to a second partition.
  1990  		sectorsToCommit := ((miner.WPoStPeriodDeadlines - 2) * actor.partitionSize) + 1
  1991  		sectors := actor.commitAndProveSectors(rt, int(sectorsToCommit), defaultSectorExpiration, nil, true)
  1992  		lastSector := sectors[len(sectors)-1]
  1993  
  1994  		st := getState(rt)
  1995  		dlIdx, pIdx, err := st.FindSector(store, lastSector.SectorNumber)
  1996  		require.NoError(t, err)
  1997  		require.Equal(t, uint64(2), dlIdx) // Deadlines 0 and 1 are empty (no PoSt needed) because excluded by proximity
  1998  		require.Equal(t, uint64(1), pIdx)  // Overflowed from partition 0 to partition 1
  1999  
  2000  		// Skip over deadlines until the beginning of the one with two partitions
  2001  		dlinfo := actor.deadline(rt)
  2002  		for dlinfo.Index != dlIdx {
  2003  			dlinfo = advanceDeadline(rt, actor, &cronConfig{})
  2004  		}
  2005  
  2006  		{
  2007  			// Submit PoSt for partition 0 on its own.
  2008  			partitions := []miner.PoStPartition{
  2009  				{Index: 0, Skipped: bitfield.New()},
  2010  			}
  2011  			sectorsToProve := sectors[:actor.partitionSize]
  2012  			pwr := miner.PowerForSectors(actor.sectorSize, sectorsToProve)
  2013  			actor.submitWindowPoSt(rt, dlinfo, partitions, sectorsToProve, &poStConfig{
  2014  				expectedPowerDelta: pwr,
  2015  			})
  2016  			// Verify proof recorded
  2017  			deadline := actor.getDeadline(rt, dlIdx)
  2018  			assertBitfieldEquals(t, deadline.PartitionsPoSted, 0)
  2019  		}
  2020  		{
  2021  			// Attempt PoSt for both partitions, thus duplicating proof for partition 0, so rejected
  2022  			partitions := []miner.PoStPartition{
  2023  				{Index: 0, Skipped: bitfield.New()},
  2024  				{Index: 1, Skipped: bitfield.New()},
  2025  			}
  2026  			sectorsToProve := append(sectors[:actor.partitionSize], lastSector)
  2027  			pwr := miner.PowerForSectors(actor.sectorSize, sectorsToProve)
  2028  
  2029  			// From network version 7, the miner outright rejects attempts to prove a partition twice.
  2030  			rt.ExpectAbortContainsMessage(exitcode.ErrIllegalArgument, "partition already proven", func() {
  2031  				actor.submitWindowPoSt(rt, dlinfo, partitions, sectorsToProve, &poStConfig{
  2032  					expectedPowerDelta: pwr,
  2033  				})
  2034  			})
  2035  			rt.Reset()
  2036  		}
  2037  		{
  2038  			// Submit PoSt for partition 1 on its own is ok.
  2039  			partitions := []miner.PoStPartition{
  2040  				{Index: 1, Skipped: bitfield.New()},
  2041  			}
  2042  			sectorsToProve := []*miner.SectorOnChainInfo{lastSector}
  2043  			pwr := miner.PowerForSectors(actor.sectorSize, sectorsToProve)
  2044  			actor.submitWindowPoSt(rt, dlinfo, partitions, sectorsToProve, &poStConfig{
  2045  				expectedPowerDelta: pwr,
  2046  			})
  2047  			// Verify both proofs now recorded
  2048  			deadline := actor.getDeadline(rt, dlIdx)
  2049  			assertBitfieldEquals(t, deadline.PartitionsPoSted, 0, 1)
  2050  		}
  2051  
  2052  		// Advance to end-of-deadline cron to verify no penalties.
  2053  		advanceDeadline(rt, actor, &cronConfig{})
  2054  		actor.checkState(rt)
  2055  	})
  2056  
  2057  	t.Run("successful recoveries recover power", func(t *testing.T) {
  2058  		rt := builder.Build(t)
  2059  
  2060  		actor.constructAndVerify(rt)
  2061  		infos := actor.commitAndProveSectors(rt, 1, defaultSectorExpiration, nil, true)
  2062  		pwr := miner.PowerForSectors(actor.sectorSize, infos)
  2063  
  2064  		actor.applyRewards(rt, bigRewards, big.Zero())
  2065  		initialLocked := actor.getLockedFunds(rt)
  2066  
  2067  		// Submit first PoSt to ensure we are sufficiently early to add a fault
  2068  		// advance to next proving period
  2069  		advanceAndSubmitPoSts(rt, actor, infos[0])
  2070  
  2071  		// advance deadline and declare fault
  2072  		advanceDeadline(rt, actor, &cronConfig{})
  2073  		actor.declareFaults(rt, infos...)
  2074  
  2075  		// advance a deadline and declare recovery
  2076  		advanceDeadline(rt, actor, &cronConfig{})
  2077  
  2078  		// declare recovery
  2079  		st := getState(rt)
  2080  		dlIdx, pIdx, err := st.FindSector(rt.AdtStore(), infos[0].SectorNumber)
  2081  		require.NoError(t, err)
  2082  		actor.declareRecoveries(rt, dlIdx, pIdx, bf(uint64(infos[0].SectorNumber)), big.Zero())
  2083  
  2084  		// advance to epoch when submitPoSt is due
  2085  		dlinfo := actor.deadline(rt)
  2086  		for dlinfo.Index != dlIdx {
  2087  			dlinfo = advanceDeadline(rt, actor, &cronConfig{})
  2088  		}
  2089  
  2090  		// Now submit PoSt
  2091  		// Power should return for recovered sector.
  2092  		cfg := &poStConfig{
  2093  			expectedPowerDelta: miner.NewPowerPair(pwr.Raw, pwr.QA),
  2094  		}
  2095  		partitions := []miner.PoStPartition{
  2096  			{Index: pIdx, Skipped: bitfield.New()},
  2097  		}
  2098  		actor.submitWindowPoSt(rt, dlinfo, partitions, infos, cfg)
  2099  
  2100  		// faulty power has been removed, partition no longer has faults or recoveries
  2101  		deadline, partition := actor.findSector(rt, infos[0].SectorNumber)
  2102  		assert.Equal(t, miner.NewPowerPairZero(), deadline.FaultyPower)
  2103  		assert.Equal(t, miner.NewPowerPairZero(), partition.FaultyPower)
  2104  		assertBitfieldEmpty(t, partition.Faults)
  2105  		assertBitfieldEmpty(t, partition.Recoveries)
  2106  
  2107  		// We restored power, so we should not have recorded a post.
  2108  		deadline = actor.getDeadline(rt, dlIdx)
  2109  		assertBitfieldEquals(t, deadline.PartitionsPoSted, pIdx)
  2110  		postsCid := deadline.OptimisticPoStSubmissions
  2111  		posts, err := adt.AsArray(rt.AdtStore(), postsCid,
  2112  			miner.DeadlineOptimisticPoStSubmissionsAmtBitwidth)
  2113  		require.NoError(t, err)
  2114  		require.EqualValues(t, posts.Length(), 0)
  2115  
  2116  		// Next deadline cron does not charge for the fault
  2117  		advanceDeadline(rt, actor, &cronConfig{})
  2118  
  2119  		assert.Equal(t, initialLocked, actor.getLockedFunds(rt))
  2120  		actor.checkState(rt)
  2121  	})
  2122  
  2123  	t.Run("skipped faults adjust power", func(t *testing.T) {
  2124  		rt := builder.Build(t)
  2125  
  2126  		actor.constructAndVerify(rt)
  2127  		infos := actor.commitAndProveSectors(rt, 2, defaultSectorExpiration, nil, true)
  2128  
  2129  		actor.applyRewards(rt, bigRewards, big.Zero())
  2130  
  2131  		// advance to epoch when submitPoSt is due
  2132  		st := getState(rt)
  2133  		dlIdx, pIdx, err := st.FindSector(rt.AdtStore(), infos[0].SectorNumber)
  2134  		require.NoError(t, err)
  2135  		dlIdx2, pIdx2, err := st.FindSector(rt.AdtStore(), infos[1].SectorNumber)
  2136  		require.NoError(t, err)
  2137  		assert.Equal(t, dlIdx, dlIdx2) // this test will need to change when these are not equal
  2138  
  2139  		dlinfo := actor.deadline(rt)
  2140  		for dlinfo.Index != dlIdx {
  2141  			dlinfo = advanceDeadline(rt, actor, &cronConfig{})
  2142  		}
  2143  
  2144  		// Now submit PoSt with a skipped fault for first sector
  2145  		// First sector's power should not be activated.
  2146  		powerActive := miner.PowerForSectors(actor.sectorSize, infos[1:])
  2147  		cfg := &poStConfig{
  2148  			expectedPowerDelta: powerActive,
  2149  		}
  2150  		partitions := []miner.PoStPartition{
  2151  			{Index: pIdx, Skipped: bf(uint64(infos[0].SectorNumber))},
  2152  		}
  2153  		actor.submitWindowPoSt(rt, dlinfo, partitions, infos, cfg)
  2154  
  2155  		// expect continued fault fee to be charged during cron
  2156  		faultFee := actor.continuedFaultPenalty(infos[:1])
  2157  		dlinfo = advanceDeadline(rt, actor, &cronConfig{continuedFaultsPenalty: faultFee})
  2158  
  2159  		// advance to next proving period, expect no fees
  2160  		for dlinfo.Index != dlIdx {
  2161  			dlinfo = advanceDeadline(rt, actor, &cronConfig{})
  2162  		}
  2163  
  2164  		// Attempt to skip second sector
  2165  		pwrDelta := miner.PowerForSectors(actor.sectorSize, infos[1:2])
  2166  
  2167  		cfg = &poStConfig{
  2168  			expectedPowerDelta: pwrDelta.Neg(),
  2169  		}
  2170  		partitions = []miner.PoStPartition{
  2171  			{Index: pIdx2, Skipped: bf(uint64(infos[1].SectorNumber))},
  2172  		}
  2173  		// Now all sectors are faulty so there's nothing to prove.
  2174  		rt.ExpectAbortContainsMessage(exitcode.ErrIllegalArgument, "no active sectors", func() {
  2175  			actor.submitWindowPoSt(rt, dlinfo, partitions, infos, cfg)
  2176  		})
  2177  		rt.Reset()
  2178  
  2179  		// The second sector is detected faulty but pays nothing yet.
  2180  		// Expect ongoing fault penalty for only the first, continuing-faulty sector.
  2181  		pwrDelta = miner.PowerForSectors(actor.sectorSize, infos[1:2]).Neg()
  2182  		faultFee = actor.continuedFaultPenalty(infos[:1])
  2183  		advanceDeadline(rt, actor, &cronConfig{
  2184  			detectedFaultsPowerDelta: &pwrDelta,
  2185  			continuedFaultsPenalty:   faultFee,
  2186  		})
  2187  		actor.checkState(rt)
  2188  	})
  2189  
  2190  	t.Run("skipping all sectors in a partition rejected", func(t *testing.T) {
  2191  		rt := builder.Build(t)
  2192  
  2193  		actor.constructAndVerify(rt)
  2194  		infos := actor.commitAndProveSectors(rt, 2, defaultSectorExpiration, nil, true)
  2195  
  2196  		actor.applyRewards(rt, bigRewards, big.Zero())
  2197  
  2198  		// advance to epoch when submitPoSt is due
  2199  		st := getState(rt)
  2200  		dlIdx, pIdx, err := st.FindSector(rt.AdtStore(), infos[0].SectorNumber)
  2201  		require.NoError(t, err)
  2202  		dlIdx2, pIdx2, err := st.FindSector(rt.AdtStore(), infos[1].SectorNumber)
  2203  		require.NoError(t, err)
  2204  		assert.Equal(t, dlIdx, dlIdx2) // this test will need to change when these are not equal
  2205  		assert.Equal(t, pIdx, pIdx2)   // this test will need to change when these are not equal
  2206  
  2207  		dlinfo := actor.deadline(rt)
  2208  		for dlinfo.Index != dlIdx {
  2209  			dlinfo = advanceDeadline(rt, actor, &cronConfig{})
  2210  		}
  2211  
  2212  		// PoSt with all sectors skipped fails to validate, leaving power un-activated.
  2213  		partitions := []miner.PoStPartition{
  2214  			{Index: pIdx, Skipped: bf(uint64(infos[0].SectorNumber), uint64(infos[1].SectorNumber))},
  2215  		}
  2216  		rt.ExpectAbort(exitcode.ErrIllegalArgument, func() {
  2217  			actor.submitWindowPoSt(rt, dlinfo, partitions, infos, nil)
  2218  		})
  2219  		rt.Reset()
  2220  
  2221  		// These sectors are detected faulty and pay no penalty this time.
  2222  		advanceDeadline(rt, actor, &cronConfig{continuedFaultsPenalty: big.Zero()})
  2223  		actor.checkState(rt)
  2224  	})
  2225  
  2226  	t.Run("skipped recoveries are penalized and do not recover power", func(t *testing.T) {
  2227  		rt := builder.Build(t)
  2228  
  2229  		actor.constructAndVerify(rt)
  2230  		infos := actor.commitAndProveSectors(rt, 2, defaultSectorExpiration, nil, true)
  2231  
  2232  		actor.applyRewards(rt, bigRewards, big.Zero())
  2233  
  2234  		// Submit first PoSt to ensure we are sufficiently early to add a fault
  2235  		// advance to next proving period
  2236  		advanceAndSubmitPoSts(rt, actor, infos...)
  2237  
  2238  		// advance deadline and declare fault on the first sector
  2239  		advanceDeadline(rt, actor, &cronConfig{})
  2240  		actor.declareFaults(rt, infos[0])
  2241  
  2242  		// advance a deadline and declare recovery
  2243  		advanceDeadline(rt, actor, &cronConfig{})
  2244  
  2245  		// declare recovery
  2246  		st := getState(rt)
  2247  		dlIdx, pIdx, err := st.FindSector(rt.AdtStore(), infos[0].SectorNumber)
  2248  		require.NoError(t, err)
  2249  		actor.declareRecoveries(rt, dlIdx, pIdx, bf(uint64(infos[0].SectorNumber)), big.Zero())
  2250  
  2251  		// advance to epoch when submitPoSt is due
  2252  		dlinfo := actor.deadline(rt)
  2253  		for dlinfo.Index != dlIdx {
  2254  			dlinfo = advanceDeadline(rt, actor, &cronConfig{})
  2255  		}
  2256  
  2257  		// Now submit PoSt and skip recovered sector.
  2258  		// No power should be returned
  2259  		cfg := &poStConfig{
  2260  			expectedPowerDelta: miner.NewPowerPairZero(),
  2261  		}
  2262  		partitions := []miner.PoStPartition{
  2263  			{Index: pIdx, Skipped: bf(uint64(infos[0].SectorNumber))},
  2264  		}
  2265  		actor.submitWindowPoSt(rt, dlinfo, partitions, infos, cfg)
  2266  
  2267  		// sector will be charged ongoing fee at proving period cron
  2268  		ongoingFee := actor.continuedFaultPenalty(infos[:1])
  2269  		advanceDeadline(rt, actor, &cronConfig{continuedFaultsPenalty: ongoingFee})
  2270  		actor.checkState(rt)
  2271  	})
  2272  
  2273  	t.Run("skipping a fault from the wrong partition is an error", func(t *testing.T) {
  2274  		rt := builder.Build(t)
  2275  		actor.constructAndVerify(rt)
  2276  
  2277  		// create enough sectors that one will be in a different partition
  2278  		n := 95
  2279  		infos := actor.commitAndProveSectors(rt, n, defaultSectorExpiration, nil, true)
  2280  
  2281  		// add lots of funds so we can pay penalties without going into debt
  2282  		st := getState(rt)
  2283  		dlIdx0, pIdx0, err := st.FindSector(rt.AdtStore(), infos[0].SectorNumber)
  2284  		require.NoError(t, err)
  2285  		dlIdx1, pIdx1, err := st.FindSector(rt.AdtStore(), infos[n-1].SectorNumber)
  2286  		require.NoError(t, err)
  2287  
  2288  		// if these assertions no longer hold, the test must be changed
  2289  		require.LessOrEqual(t, dlIdx0, dlIdx1)
  2290  		require.NotEqual(t, pIdx0, pIdx1)
  2291  
  2292  		// advance to deadline when sector is due
  2293  		dlinfo := actor.deadline(rt)
  2294  		for dlinfo.Index != dlIdx0 {
  2295  			dlinfo = advanceDeadline(rt, actor, &cronConfig{})
  2296  		}
  2297  
  2298  		// Now submit PoSt for partition 1 and skip sector from other partition
  2299  		cfg := &poStConfig{
  2300  			expectedPowerDelta: miner.NewPowerPairZero(),
  2301  		}
  2302  		partitions := []miner.PoStPartition{
  2303  			{Index: pIdx0, Skipped: bf(uint64(infos[n-1].SectorNumber))},
  2304  		}
  2305  		rt.ExpectAbortContainsMessage(exitcode.ErrIllegalArgument, "skipped faults contains sectors outside partition", func() {
  2306  			actor.submitWindowPoSt(rt, dlinfo, partitions, infos, cfg)
  2307  		})
  2308  		actor.checkState(rt)
  2309  	})
  2310  
  2311  	t.Run("cannot dispute posts when the challenge window is open", func(t *testing.T) {
  2312  		proofs := makePoStProofs(actor.windowPostProofType)
  2313  
  2314  		rt := builder.Build(t)
  2315  		actor.constructAndVerify(rt)
  2316  		store := rt.AdtStore()
  2317  		sector := actor.commitAndProveSectors(rt, 1, defaultSectorExpiration, nil, true)[0]
  2318  		pwr := miner.PowerForSector(actor.sectorSize, sector)
  2319  
  2320  		st := getState(rt)
  2321  		dlIdx, pIdx, err := st.FindSector(store, sector.SectorNumber)
  2322  		require.NoError(t, err)
  2323  
  2324  		// Skip over deadlines until the beginning of the one with the new sector
  2325  		dlinfo := actor.deadline(rt)
  2326  		for dlinfo.Index != dlIdx {
  2327  			dlinfo = advanceDeadline(rt, actor, &cronConfig{})
  2328  		}
  2329  
  2330  		// Submit PoSt
  2331  		partitions := []miner.PoStPartition{
  2332  			{Index: pIdx, Skipped: bitfield.New()},
  2333  		}
  2334  		actor.submitWindowPoStRaw(rt, dlinfo, partitions, []*miner.SectorOnChainInfo{sector}, proofs, &poStConfig{
  2335  			expectedPowerDelta: pwr,
  2336  		})
  2337  
  2338  		// Dispute it.
  2339  		params := miner.DisputeWindowedPoStParams{
  2340  			Deadline:  dlinfo.Index,
  2341  			PoStIndex: 0,
  2342  		}
  2343  
  2344  		rt.SetCaller(actor.worker, builtin.AccountActorCodeID)
  2345  		rt.ExpectValidateCallerType(builtin.CallerTypesSignable...)
  2346  
  2347  		expectQueryNetworkInfo(rt, actor)
  2348  
  2349  		rt.ExpectAbortContainsMessage(exitcode.ErrForbidden, "can only dispute window posts during the dispute window", func() {
  2350  			rt.Call(actor.a.DisputeWindowedPoSt, &params)
  2351  		})
  2352  		rt.Verify()
  2353  	})
  2354  	t.Run("can dispute up till window end, but not after", func(t *testing.T) {
  2355  		rt := builder.Build(t)
  2356  		actor.constructAndVerify(rt)
  2357  		store := rt.AdtStore()
  2358  		sector := actor.commitAndProveSectors(rt, 1, defaultSectorExpiration, nil, true)[0]
  2359  
  2360  		st := getState(rt)
  2361  		dlIdx, _, err := st.FindSector(store, sector.SectorNumber)
  2362  		require.NoError(t, err)
  2363  
  2364  		nextDl := miner.NewDeadlineInfo(st.ProvingPeriodStart, dlIdx, rt.Epoch()).
  2365  			NextNotElapsed()
  2366  
  2367  		advanceAndSubmitPoSts(rt, actor, sector)
  2368  
  2369  		windowEnd := nextDl.Close + miner.WPoStDisputeWindow
  2370  
  2371  		// first, try to dispute right before the window end.
  2372  		// We expect this to fail "normally" (fail to disprove).
  2373  		rt.SetEpoch(windowEnd - 1)
  2374  		actor.disputeWindowPoSt(rt, nextDl, 0, []*miner.SectorOnChainInfo{sector}, nil)
  2375  
  2376  		// Now set the epoch at the window end. We expect a different error.
  2377  		rt.SetEpoch(windowEnd)
  2378  
  2379  		// Now try to dispute.
  2380  		params := miner.DisputeWindowedPoStParams{
  2381  			Deadline:  dlIdx,
  2382  			PoStIndex: 0,
  2383  		}
  2384  
  2385  		rt.SetCaller(actor.worker, builtin.AccountActorCodeID)
  2386  		rt.ExpectValidateCallerType(builtin.CallerTypesSignable...)
  2387  
  2388  		currentReward := reward.ThisEpochRewardReturn{
  2389  			ThisEpochBaselinePower:  actor.baselinePower,
  2390  			ThisEpochRewardSmoothed: actor.epochRewardSmooth,
  2391  		}
  2392  		rt.ExpectSend(builtin.RewardActorAddr, builtin.MethodsReward.ThisEpochReward, nil, big.Zero(), &currentReward, exitcode.Ok)
  2393  
  2394  		networkPower := big.NewIntUnsigned(1 << 50)
  2395  		rt.ExpectSend(builtin.StoragePowerActorAddr, builtin.MethodsPower.CurrentTotalPower, nil, big.Zero(),
  2396  			&power.CurrentTotalPowerReturn{
  2397  				RawBytePower:            networkPower,
  2398  				QualityAdjPower:         networkPower,
  2399  				PledgeCollateral:        actor.networkPledge,
  2400  				QualityAdjPowerSmoothed: actor.epochQAPowerSmooth,
  2401  			},
  2402  			exitcode.Ok)
  2403  
  2404  		rt.ExpectAbortContainsMessage(exitcode.ErrForbidden, "can only dispute window posts during the dispute window", func() {
  2405  			rt.Call(actor.a.DisputeWindowedPoSt, &params)
  2406  		})
  2407  		rt.Verify()
  2408  	})
  2409  
  2410  	t.Run("can't dispute up with an invalid deadline", func(t *testing.T) {
  2411  		rt := builder.Build(t)
  2412  		actor.constructAndVerify(rt)
  2413  
  2414  		params := miner.DisputeWindowedPoStParams{
  2415  			Deadline:  50,
  2416  			PoStIndex: 0,
  2417  		}
  2418  
  2419  		rt.SetCaller(actor.worker, builtin.AccountActorCodeID)
  2420  		rt.ExpectValidateCallerType(builtin.CallerTypesSignable...)
  2421  
  2422  		rt.ExpectAbortContainsMessage(exitcode.ErrIllegalArgument, "invalid deadline", func() {
  2423  			rt.Call(actor.a.DisputeWindowedPoSt, &params)
  2424  		})
  2425  		rt.Verify()
  2426  	})
  2427  
  2428  	t.Run("can dispute test after proving period changes", func(t *testing.T) {
  2429  		rt := builder.Build(t)
  2430  		actor.constructAndVerify(rt)
  2431  
  2432  		periodStart := actor.deadline(rt).NextPeriodStart()
  2433  
  2434  		// go to the next deadline 0
  2435  		rt.SetEpoch(periodStart)
  2436  
  2437  		// fill one partition in each mutable deadline.
  2438  		numSectors := int(actor.partitionSize * (miner.WPoStPeriodDeadlines - 2))
  2439  
  2440  		// creates a partition in every deadline except 0 and 47
  2441  		sectors := actor.commitAndProveSectors(rt, numSectors, defaultSectorExpiration, nil, true)
  2442  		actor.t.Log("here")
  2443  
  2444  		// prove every sector once to activate power. This
  2445  		// simplifies the test a bit.
  2446  		advanceAndSubmitPoSts(rt, actor, sectors...)
  2447  
  2448  		// Make sure we're in the correct deadline. We should
  2449  		// finish at deadline 2 because precommit takes some
  2450  		// time.
  2451  		dlinfo := actor.deadline(rt)
  2452  		require.True(t, dlinfo.Index < 46,
  2453  			"we need to be before the target deadline for this test to make sense")
  2454  
  2455  		// Now challenge find the sectors in the last partition.
  2456  		_, partition := actor.getDeadlineAndPartition(rt, 46, 0)
  2457  		var targetSectors []*miner.SectorOnChainInfo
  2458  		err := partition.Sectors.ForEach(func(i uint64) error {
  2459  			for _, sector := range sectors {
  2460  				if uint64(sector.SectorNumber) == i {
  2461  					targetSectors = append(targetSectors, sector)
  2462  				}
  2463  			}
  2464  			return nil
  2465  		})
  2466  		require.NoError(t, err)
  2467  		require.NotEmpty(t, targetSectors)
  2468  
  2469  		pwr := miner.PowerForSectors(actor.sectorSize, targetSectors)
  2470  
  2471  		// And challenge the last partition.
  2472  		var result *poStDisputeResult
  2473  		expectedFee := miner.PledgePenaltyForInvalidWindowPoSt(actor.epochRewardSmooth, actor.epochQAPowerSmooth, pwr.QA)
  2474  		result = &poStDisputeResult{
  2475  			expectedPowerDelta:  pwr.Neg(),
  2476  			expectedPenalty:     expectedFee,
  2477  			expectedReward:      miner.BaseRewardForDisputedWindowPoSt,
  2478  			expectedPledgeDelta: big.Zero(),
  2479  		}
  2480  
  2481  		targetDlInfo := miner.NewDeadlineInfo(periodStart, 46, rt.Epoch())
  2482  		actor.disputeWindowPoSt(rt, targetDlInfo, 0, targetSectors, result)
  2483  	})
  2484  }
  2485  
  2486  func TestProveCommit(t *testing.T) {
  2487  	periodOffset := abi.ChainEpoch(100)
  2488  	actor := newHarness(t, periodOffset)
  2489  	builder := builderForHarness(actor).
  2490  		WithBalance(bigBalance, big.Zero())
  2491  
  2492  	t.Run("prove commit aborts if pledge requirement not met", func(t *testing.T) {
  2493  		rt := builder.Build(t)
  2494  		actor.constructAndVerify(rt)
  2495  		// Set the circulating supply high and expected reward low in order to coerce
  2496  		// pledge requirements (BR + share of money supply, but capped at 1FIL)
  2497  		// to exceed pre-commit deposit (BR only).
  2498  		rt.SetCirculatingSupply(big.Mul(big.NewInt(100_000_000), big.NewInt(1e18)))
  2499  		actor.epochRewardSmooth = smoothing.TestingConstantEstimate(big.NewInt(1e15))
  2500  
  2501  		// prove one sector to establish collateral and locked funds
  2502  		sectors := actor.commitAndProveSectors(rt, 1, defaultSectorExpiration, nil, true)
  2503  
  2504  		// preecommit another sector so we may prove it
  2505  		expiration := defaultSectorExpiration*miner.WPoStProvingPeriod + periodOffset - 1
  2506  		precommitEpoch := rt.Epoch() + 1
  2507  		rt.SetEpoch(precommitEpoch)
  2508  		params := actor.makePreCommit(actor.nextSectorNo, rt.Epoch()-1, expiration, nil)
  2509  		precommit := actor.preCommitSector(rt, params, preCommitConf{}, false)
  2510  
  2511  		// Confirm the unlocked PCD will not cover the new IP
  2512  		assert.True(t, sectors[0].InitialPledge.GreaterThan(precommit.PreCommitDeposit))
  2513  
  2514  		// Set balance to exactly cover locked funds.
  2515  		st := getState(rt)
  2516  		rt.SetBalance(big.Sum(st.PreCommitDeposits, st.InitialPledge, st.LockedFunds))
  2517  
  2518  		rt.SetEpoch(precommitEpoch + miner.MaxProveCommitDuration[actor.sealProofType] - 1)
  2519  		rt.ExpectAbort(exitcode.ErrInsufficientFunds, func() {
  2520  			actor.proveCommitSectorAndConfirm(rt, precommit, makeProveCommit(actor.nextSectorNo), proveCommitConf{})
  2521  		})
  2522  		rt.Reset()
  2523  
  2524  		// succeeds with enough free balance (enough to cover 2x IP)
  2525  		rt.SetBalance(big.Sum(st.PreCommitDeposits, st.InitialPledge, st.InitialPledge, st.LockedFunds))
  2526  		actor.proveCommitSectorAndConfirm(rt, precommit, makeProveCommit(actor.nextSectorNo), proveCommitConf{})
  2527  		actor.checkState(rt)
  2528  	})
  2529  
  2530  	t.Run("drop invalid prove commit while processing valid one", func(t *testing.T) {
  2531  		rt := builder.Build(t)
  2532  		actor.constructAndVerify(rt)
  2533  
  2534  		// make two precommits
  2535  		expiration := defaultSectorExpiration*miner.WPoStProvingPeriod + periodOffset - 1
  2536  		precommitEpoch := rt.Epoch() + 1
  2537  		rt.SetEpoch(precommitEpoch)
  2538  		paramsA := actor.makePreCommit(actor.nextSectorNo, rt.Epoch()-1, expiration, []abi.DealID{1})
  2539  		preCommitA := actor.preCommitSector(rt, paramsA, preCommitConf{}, true)
  2540  		sectorNoA := actor.nextSectorNo
  2541  		actor.nextSectorNo++
  2542  		paramsB := actor.makePreCommit(actor.nextSectorNo, rt.Epoch()-1, expiration, []abi.DealID{2})
  2543  		preCommitB := actor.preCommitSector(rt, paramsB, preCommitConf{}, false)
  2544  		sectorNoB := actor.nextSectorNo
  2545  
  2546  		// handle both prove commits in the same epoch
  2547  		rt.SetEpoch(precommitEpoch + miner.MaxProveCommitDuration[actor.sealProofType] - 1)
  2548  
  2549  		actor.proveCommitSector(rt, preCommitA, makeProveCommit(sectorNoA))
  2550  		actor.proveCommitSector(rt, preCommitB, makeProveCommit(sectorNoB))
  2551  
  2552  		conf := proveCommitConf{
  2553  			verifyDealsExit: map[abi.SectorNumber]exitcode.ExitCode{
  2554  				sectorNoA: exitcode.ErrIllegalArgument,
  2555  			},
  2556  		}
  2557  		actor.confirmSectorProofsValid(rt, conf, preCommitA, preCommitB)
  2558  		actor.checkState(rt)
  2559  	})
  2560  }
  2561  
  2562  func TestDeadlineCron(t *testing.T) {
  2563  	periodOffset := abi.ChainEpoch(100)
  2564  	actor := newHarness(t, periodOffset)
  2565  	builder := builderForHarness(actor).
  2566  		WithBalance(bigBalance, big.Zero())
  2567  
  2568  	t.Run("cron on inactive state", func(t *testing.T) {
  2569  		rt := builder.Build(t)
  2570  		actor.constructAndVerify(rt)
  2571  		st := getState(rt)
  2572  		assert.Equal(t, periodOffset-miner.WPoStProvingPeriod, st.ProvingPeriodStart)
  2573  		assert.False(t, st.ContinueDeadlineCron())
  2574  
  2575  		// cron does nothing and does not enroll another cron
  2576  		deadline := actor.deadline(rt)
  2577  		rt.SetEpoch(deadline.Last())
  2578  		actor.onDeadlineCron(rt, &cronConfig{noEnrollment: true})
  2579  
  2580  		actor.checkState(rt)
  2581  	})
  2582  
  2583  	t.Run("sector expires", func(t *testing.T) {
  2584  		rt := builder.Build(t)
  2585  		actor.constructAndVerify(rt)
  2586  
  2587  		sectors := actor.commitAndProveSectors(rt, 1, defaultSectorExpiration, nil, true)
  2588  		// advance cron to activate power.
  2589  		advanceAndSubmitPoSts(rt, actor, sectors...)
  2590  		activePower := miner.PowerForSectors(actor.sectorSize, sectors)
  2591  
  2592  		st := getState(rt)
  2593  		initialPledge := st.InitialPledge
  2594  		expirationRaw := sectors[0].Expiration
  2595  		assert.True(t, st.DeadlineCronActive)
  2596  
  2597  		// setup state to simulate moving forward all the way to expiry
  2598  
  2599  		dlIdx, _, err := st.FindSector(rt.AdtStore(), sectors[0].SectorNumber)
  2600  		require.NoError(t, err)
  2601  		expQuantSpec := st.QuantSpecForDeadline(dlIdx)
  2602  		expiration := expQuantSpec.QuantizeUp(expirationRaw)
  2603  		remainingEpochs := expiration - st.ProvingPeriodStart
  2604  		remainingPeriods := remainingEpochs/miner.WPoStProvingPeriod + 1
  2605  		st.ProvingPeriodStart += remainingPeriods * miner.WPoStProvingPeriod
  2606  		st.CurrentDeadline = dlIdx
  2607  		rt.ReplaceState(st)
  2608  
  2609  		// Advance to expiration epoch and expect expiration during cron
  2610  		rt.SetEpoch(expiration)
  2611  		powerDelta := activePower.Neg()
  2612  		// because we skip forward in state the sector is detected faulty, no penalty
  2613  		advanceDeadline(rt, actor, &cronConfig{
  2614  			noEnrollment:              true, // the last power has expired so we expect cron to go inactive
  2615  			expiredSectorsPowerDelta:  &powerDelta,
  2616  			expiredSectorsPledgeDelta: initialPledge.Neg(),
  2617  		})
  2618  		st = getState(rt)
  2619  		assert.False(t, st.DeadlineCronActive)
  2620  		actor.checkState(rt)
  2621  	})
  2622  
  2623  	t.Run("sector expires and repays fee debt", func(t *testing.T) {
  2624  		rt := builder.Build(t)
  2625  		actor.constructAndVerify(rt)
  2626  
  2627  		sectors := actor.commitAndProveSectors(rt, 1, defaultSectorExpiration, nil, true)
  2628  		// advance cron to activate power.
  2629  		advanceAndSubmitPoSts(rt, actor, sectors...)
  2630  		activePower := miner.PowerForSectors(actor.sectorSize, sectors)
  2631  
  2632  		st := getState(rt)
  2633  		initialPledge := st.InitialPledge
  2634  		expirationRaw := sectors[0].Expiration
  2635  		assert.True(t, st.DeadlineCronActive)
  2636  
  2637  		// setup state to simulate moving forward all the way to expiry
  2638  		dlIdx, _, err := st.FindSector(rt.AdtStore(), sectors[0].SectorNumber)
  2639  		require.NoError(t, err)
  2640  		expQuantSpec := st.QuantSpecForDeadline(dlIdx)
  2641  		expiration := expQuantSpec.QuantizeUp(expirationRaw)
  2642  		remainingEpochs := expiration - st.ProvingPeriodStart
  2643  		remainingPeriods := remainingEpochs/miner.WPoStProvingPeriod + 1
  2644  		st.ProvingPeriodStart += remainingPeriods * miner.WPoStProvingPeriod
  2645  		st.CurrentDeadline = dlIdx
  2646  		rt.ReplaceState(st)
  2647  
  2648  		// Advance to expiration epoch and expect expiration during cron
  2649  		rt.SetEpoch(expiration)
  2650  		powerDelta := activePower.Neg()
  2651  
  2652  		// introduce lots of fee debt
  2653  		st = getState(rt)
  2654  		feeDebt := big.Mul(big.NewInt(400), big.NewInt(1e18))
  2655  		st.FeeDebt = feeDebt
  2656  		rt.ReplaceState(st)
  2657  		// Miner balance = IP, debt repayment covered by unlocked funds
  2658  		rt.SetBalance(st.InitialPledge)
  2659  
  2660  		// because we skip forward in state and don't check post, there's no penalty.
  2661  		// this is the first time the sector is detected faulty
  2662  		advanceDeadline(rt, actor, &cronConfig{
  2663  			noEnrollment:              true,
  2664  			expiredSectorsPowerDelta:  &powerDelta,
  2665  			expiredSectorsPledgeDelta: initialPledge.Neg(),
  2666  			repaidFeeDebt:             initialPledge, // We repay unlocked IP as fees
  2667  		})
  2668  		st = getState(rt)
  2669  		assert.False(t, st.DeadlineCronActive)
  2670  		actor.checkState(rt)
  2671  	})
  2672  
  2673  	t.Run("detects and penalizes faults", func(t *testing.T) {
  2674  		rt := builder.Build(t)
  2675  		actor.constructAndVerify(rt)
  2676  
  2677  		activeSectors := actor.commitAndProveSectors(rt, 2, defaultSectorExpiration, nil, true)
  2678  		// advance cron to activate power.
  2679  		advanceAndSubmitPoSts(rt, actor, activeSectors...)
  2680  		activePower := miner.PowerForSectors(actor.sectorSize, activeSectors)
  2681  
  2682  		unprovenSectors := actor.commitAndProveSectors(rt, 1, defaultSectorExpiration, nil, false)
  2683  		unprovenPower := miner.PowerForSectors(actor.sectorSize, unprovenSectors)
  2684  
  2685  		totalPower := unprovenPower.Add(activePower)
  2686  		allSectors := append(activeSectors, unprovenSectors...)
  2687  
  2688  		// add lots of funds so penalties come from vesting funds
  2689  		actor.applyRewards(rt, bigRewards, big.Zero())
  2690  
  2691  		st := getState(rt)
  2692  		dlIdx, pIdx, err := st.FindSector(rt.AdtStore(), activeSectors[0].SectorNumber)
  2693  		require.NoError(t, err)
  2694  
  2695  		// advance to next deadline where we expect the first sectors to appear
  2696  		dlinfo := actor.deadline(rt)
  2697  		for dlinfo.Index != dlIdx {
  2698  			dlinfo = advanceDeadline(rt, actor, &cronConfig{})
  2699  		}
  2700  
  2701  		// Skip to end of the deadline, cron detects sectors as faulty
  2702  		activePowerDelta := activePower.Neg()
  2703  		advanceDeadline(rt, actor, &cronConfig{
  2704  			detectedFaultsPowerDelta: &activePowerDelta,
  2705  		})
  2706  
  2707  		// expect faulty power to be added to state
  2708  		deadline := actor.getDeadline(rt, dlIdx)
  2709  		assert.True(t, totalPower.Equals(deadline.FaultyPower))
  2710  
  2711  		// advance 3 deadlines
  2712  		advanceDeadline(rt, actor, &cronConfig{})
  2713  		advanceDeadline(rt, actor, &cronConfig{})
  2714  		dlinfo = advanceDeadline(rt, actor, &cronConfig{})
  2715  
  2716  		actor.declareRecoveries(rt, dlIdx, pIdx, sectorInfoAsBitfield(allSectors[1:]), big.Zero())
  2717  
  2718  		// Skip to end of proving period for sectors, cron detects all sectors as faulty
  2719  		for dlinfo.Index != dlIdx {
  2720  			dlinfo = advanceDeadline(rt, actor, &cronConfig{})
  2721  		}
  2722  
  2723  		// Un-recovered faults (incl failed recovery) are charged as ongoing faults
  2724  		ongoingPwr := miner.PowerForSectors(actor.sectorSize, allSectors)
  2725  		ongoingPenalty := miner.PledgePenaltyForContinuedFault(actor.epochRewardSmooth, actor.epochQAPowerSmooth, ongoingPwr.QA)
  2726  
  2727  		advanceDeadline(rt, actor, &cronConfig{
  2728  			continuedFaultsPenalty: ongoingPenalty,
  2729  		})
  2730  
  2731  		// recorded faulty power is unchanged
  2732  		deadline = actor.getDeadline(rt, dlIdx)
  2733  		assert.True(t, totalPower.Equals(deadline.FaultyPower))
  2734  		checkDeadlineInvariants(t, rt.AdtStore(), deadline, st.QuantSpecForDeadline(dlIdx), actor.sectorSize, allSectors)
  2735  		actor.checkState(rt)
  2736  	})
  2737  
  2738  	t.Run("test cron run trigger faults", func(t *testing.T) {
  2739  		rt := builder.Build(t)
  2740  		actor.constructAndVerify(rt)
  2741  
  2742  		// add lots of funds so we can pay penalties without going into debt
  2743  		actor.applyRewards(rt, bigRewards, big.Zero())
  2744  
  2745  		// create enough sectors that one will be in a different partition
  2746  		allSectors := actor.commitAndProveSectors(rt, 1, defaultSectorExpiration, nil, true)
  2747  
  2748  		// advance cron to activate power.
  2749  		advanceAndSubmitPoSts(rt, actor, allSectors...)
  2750  
  2751  		st := getState(rt)
  2752  		dlIdx, _, err := st.FindSector(rt.AdtStore(), allSectors[0].SectorNumber)
  2753  		require.NoError(t, err)
  2754  
  2755  		// advance to deadline prior to first
  2756  		dlinfo := actor.deadline(rt)
  2757  		for dlinfo.Index != dlIdx {
  2758  			dlinfo = advanceDeadline(rt, actor, &cronConfig{})
  2759  		}
  2760  
  2761  		rt.SetEpoch(dlinfo.Last())
  2762  
  2763  		// run cron and expect all sectors to be detected as faults (no penalty)
  2764  		pwr := miner.PowerForSectors(actor.sectorSize, allSectors)
  2765  
  2766  		// power for sectors is removed
  2767  		powerDeltaClaim := miner.NewPowerPair(pwr.Raw.Neg(), pwr.QA.Neg())
  2768  
  2769  		// expect next cron to be one deadline period after expected cron for this deadline
  2770  		nextCron := dlinfo.Last() + miner.WPoStChallengeWindow
  2771  
  2772  		actor.onDeadlineCron(rt, &cronConfig{
  2773  			expectedEnrollment:       nextCron,
  2774  			detectedFaultsPowerDelta: &powerDeltaClaim,
  2775  		})
  2776  		actor.checkState(rt)
  2777  	})
  2778  }
  2779  
  2780  // cronControl is a convenience harness on top of the actor harness giving the caller access to common
  2781  // sequences of miner actor actions useful for checking that cron starts, runs, stops and continues
  2782  type cronControl struct {
  2783  	rt           *mock.Runtime
  2784  	actor        *actorHarness
  2785  	preCommitNum int
  2786  }
  2787  
  2788  func newCronControl(rt *mock.Runtime, actor *actorHarness) *cronControl {
  2789  	return &cronControl{
  2790  		rt:           rt,
  2791  		actor:        actor,
  2792  		preCommitNum: 0,
  2793  	}
  2794  }
  2795  
  2796  // Start cron by precommitting at preCommitEpoch, return expiry epoch.
  2797  // Verifies that cron is not started, precommit is run and cron is enrolled.
  2798  // Returns expiration of precommit.
  2799  func (h *cronControl) preCommitToStartCron(t *testing.T, preCommitEpoch abi.ChainEpoch) abi.ChainEpoch {
  2800  	h.rt.SetEpoch(preCommitEpoch)
  2801  	st := getState(h.rt)
  2802  	h.requireCronInactive(t)
  2803  
  2804  	dlinfo := miner.NewDeadlineInfoFromOffsetAndEpoch(st.ProvingPeriodStart, preCommitEpoch) // actor.deadline might be out of date
  2805  	sectorNo := abi.SectorNumber(h.preCommitNum)
  2806  	h.preCommitNum++
  2807  	expiration := dlinfo.PeriodEnd() + defaultSectorExpiration*miner.WPoStProvingPeriod // something on deadline boundary but > 180 days
  2808  	precommitParams := h.actor.makePreCommit(sectorNo, preCommitEpoch-1, expiration, nil)
  2809  	h.actor.preCommitSector(h.rt, precommitParams, preCommitConf{}, true)
  2810  
  2811  	// PCD != 0 so cron must be active
  2812  	h.requireCronActive(t)
  2813  	expiryEpoch := preCommitEpoch + builtin.EpochsInDay + miner.PreCommitChallengeDelay + abi.ChainEpoch(1)
  2814  	return expiryEpoch
  2815  }
  2816  
  2817  // Stop cron by advancing to the preCommit expiry epoch.
  2818  // Assumes no proved sectors, no vesting funds.
  2819  // Verifies cron runs until expiry, PCD burnt and cron discontinued during last deadline
  2820  // Return open of first deadline after expiration.
  2821  func (h *cronControl) expirePreCommitStopCron(t *testing.T, startEpoch, expiryEpoch abi.ChainEpoch) abi.ChainEpoch {
  2822  	h.requireCronActive(t)
  2823  	st := getState(h.rt)
  2824  	dlinfo := miner.NewDeadlineInfoFromOffsetAndEpoch(st.ProvingPeriodStart, startEpoch) // actor.deadline might be out of date
  2825  
  2826  	for dlinfo.Open <= expiryEpoch { // PCDs are quantized to expire on the *next* new deadline after the one they expire in
  2827  		// asserts cron is rescheduled
  2828  		dlinfo = advanceDeadline(h.rt, h.actor, &cronConfig{})
  2829  	}
  2830  	// We expect PCD burnt and cron not rescheduled here.
  2831  	h.rt.SetEpoch(dlinfo.Last())
  2832  	h.actor.onDeadlineCron(h.rt, &cronConfig{
  2833  		noEnrollment:            true,
  2834  		expiredPrecommitPenalty: st.PreCommitDeposits,
  2835  	})
  2836  	h.rt.SetEpoch(dlinfo.NextOpen())
  2837  
  2838  	h.requireCronInactive(t)
  2839  	return h.rt.Epoch()
  2840  }
  2841  
  2842  func (h *cronControl) requireCronInactive(t *testing.T) {
  2843  	st := getState(h.rt)
  2844  	assert.False(t, st.DeadlineCronActive)     // No cron running now
  2845  	assert.False(t, st.ContinueDeadlineCron()) // No reason to cron now, state inactive
  2846  }
  2847  
  2848  func (h *cronControl) requireCronActive(t *testing.T) {
  2849  	st := getState(h.rt)
  2850  	require.True(t, st.DeadlineCronActive)
  2851  	require.True(t, st.ContinueDeadlineCron())
  2852  }
  2853  
  2854  func (h *cronControl) preCommitStartCronExpireStopCron(t *testing.T, startEpoch abi.ChainEpoch) abi.ChainEpoch {
  2855  	expiryEpoch := h.preCommitToStartCron(t, startEpoch)
  2856  	return h.expirePreCommitStopCron(t, startEpoch, expiryEpoch)
  2857  }
  2858  
  2859  func TestDeadlineCronDefersStopsRestarts(t *testing.T) {
  2860  	periodOffset := abi.ChainEpoch(100)
  2861  	actor := newHarness(t, periodOffset)
  2862  	builder := builderForHarness(actor).
  2863  		WithBalance(bigBalance, big.Zero())
  2864  
  2865  	t.Run("cron enrolls on precommit, prove commits and continues enrolling", func(t *testing.T) {
  2866  		rt := builder.Build(t)
  2867  		actor.constructAndVerify(rt)
  2868  		cronCtrl := newCronControl(rt, actor)
  2869  		longExpiration := uint64(500)
  2870  
  2871  		cronCtrl.requireCronInactive(t)
  2872  		sectors := actor.commitAndProveSectors(rt, 1, longExpiration, nil, true)
  2873  		cronCtrl.requireCronActive(t)
  2874  
  2875  		// advance cron to activate power.
  2876  		advanceAndSubmitPoSts(rt, actor, sectors...)
  2877  		// advance 499 days of deadline (1 before expiration occurrs)
  2878  		// this asserts that cron continues to enroll within advanceAndSubmitPoSt
  2879  		for i := 0; i < 499; i++ {
  2880  			advanceAndSubmitPoSts(rt, actor, sectors...)
  2881  		}
  2882  		actor.checkState(rt)
  2883  		st := getState(rt)
  2884  		assert.True(t, st.DeadlineCronActive)
  2885  	})
  2886  
  2887  	t.Run("cron enrolls on precommit, expires on pcd expiration, re-enrolls on new precommit immediately", func(t *testing.T) {
  2888  		rt := builder.Build(t)
  2889  		epoch := periodOffset + 1
  2890  		rt.SetEpoch(epoch)
  2891  		actor.constructAndVerify(rt)
  2892  		cronCtrl := newCronControl(rt, actor)
  2893  
  2894  		epoch = cronCtrl.preCommitStartCronExpireStopCron(t, epoch)
  2895  		cronCtrl.preCommitToStartCron(t, epoch)
  2896  	})
  2897  
  2898  	t.Run("cron enrolls on precommit, expires on pcd expiration, re-enrolls on new precommit after falling out of date", func(t *testing.T) {
  2899  		rt := builder.Build(t)
  2900  		epoch := periodOffset + 1
  2901  		rt.SetEpoch(epoch)
  2902  		actor.constructAndVerify(rt)
  2903  		cronCtrl := newCronControl(rt, actor)
  2904  
  2905  		epoch = cronCtrl.preCommitStartCronExpireStopCron(t, epoch)
  2906  		// Advance some epochs to fall several pp out of date, then precommit again reenrolling cron
  2907  		epoch = epoch + 200*miner.WPoStProvingPeriod
  2908  		epoch = cronCtrl.preCommitStartCronExpireStopCron(t, epoch)
  2909  		// Stay within the same deadline but advance an epoch
  2910  		epoch = epoch + 1
  2911  		cronCtrl.preCommitToStartCron(t, epoch)
  2912  	})
  2913  
  2914  	t.Run("enroll, pcd expire, re-enroll x 1000", func(t *testing.T) {
  2915  		rt := builder.Build(t)
  2916  		epoch := periodOffset + 1
  2917  		rt.SetEpoch(epoch)
  2918  		actor.constructAndVerify(rt)
  2919  		cronCtrl := newCronControl(rt, actor)
  2920  		for i := 0; i < 1000; i++ {
  2921  			epoch = cronCtrl.preCommitStartCronExpireStopCron(t, epoch) + 42
  2922  		}
  2923  	})
  2924  }
  2925  
  2926  func TestDeclareFaults(t *testing.T) {
  2927  	periodOffset := abi.ChainEpoch(100)
  2928  	actor := newHarness(t, periodOffset)
  2929  	builder := builderForHarness(actor).
  2930  		WithBalance(bigBalance, big.Zero())
  2931  
  2932  	t.Run("declare fault pays fee at window post", func(t *testing.T) {
  2933  		// Get sector into proving state
  2934  		rt := builder.Build(t)
  2935  		actor.constructAndVerify(rt)
  2936  		allSectors := actor.commitAndProveSectors(rt, 1, defaultSectorExpiration, nil, true)
  2937  		pwr := miner.PowerForSectors(actor.sectorSize, allSectors)
  2938  
  2939  		// add lots of funds so penalties come from vesting funds
  2940  		actor.applyRewards(rt, bigRewards, big.Zero())
  2941  
  2942  		// find deadline for sector
  2943  		st := getState(rt)
  2944  		dlIdx, _, err := st.FindSector(rt.AdtStore(), allSectors[0].SectorNumber)
  2945  		require.NoError(t, err)
  2946  
  2947  		// advance to first proving period and submit so we'll have time to declare the fault next cycle
  2948  		advanceAndSubmitPoSts(rt, actor, allSectors...)
  2949  
  2950  		// Declare the sector as faulted
  2951  		actor.declareFaults(rt, allSectors...)
  2952  
  2953  		// faults are recorded in state
  2954  		dl := actor.getDeadline(rt, dlIdx)
  2955  		assert.True(t, pwr.Equals(dl.FaultyPower))
  2956  
  2957  		// Skip to end of proving period.
  2958  		dlinfo := actor.deadline(rt)
  2959  		for dlinfo.Index != dlIdx {
  2960  			dlinfo = advanceDeadline(rt, actor, &cronConfig{})
  2961  		}
  2962  
  2963  		// faults are charged at ongoing rate and no additional power is removed
  2964  		ongoingPwr := miner.PowerForSectors(actor.sectorSize, allSectors)
  2965  		ongoingPenalty := miner.PledgePenaltyForContinuedFault(actor.epochRewardSmooth, actor.epochQAPowerSmooth, ongoingPwr.QA)
  2966  
  2967  		advanceDeadline(rt, actor, &cronConfig{
  2968  			continuedFaultsPenalty: ongoingPenalty,
  2969  		})
  2970  		actor.checkState(rt)
  2971  	})
  2972  }
  2973  
  2974  func TestDeclareRecoveries(t *testing.T) {
  2975  	periodOffset := abi.ChainEpoch(100)
  2976  	actor := newHarness(t, periodOffset)
  2977  	builder := builderForHarness(actor).
  2978  		WithBalance(bigBalance, big.Zero())
  2979  
  2980  	t.Run("recovery happy path", func(t *testing.T) {
  2981  		rt := builder.Build(t)
  2982  		actor.constructAndVerify(rt)
  2983  		oneSector := actor.commitAndProveSectors(rt, 1, defaultSectorExpiration, nil, true)
  2984  
  2985  		// advance to first proving period and submit so we'll have time to declare the fault next cycle
  2986  		advanceAndSubmitPoSts(rt, actor, oneSector...)
  2987  
  2988  		// Declare the sector as faulted
  2989  		actor.declareFaults(rt, oneSector...)
  2990  
  2991  		// Declare recoveries updates state
  2992  		st := getState(rt)
  2993  		dlIdx, pIdx, err := st.FindSector(rt.AdtStore(), oneSector[0].SectorNumber)
  2994  		require.NoError(t, err)
  2995  		actor.declareRecoveries(rt, dlIdx, pIdx, bf(uint64(oneSector[0].SectorNumber)), big.Zero())
  2996  
  2997  		dl := actor.getDeadline(rt, dlIdx)
  2998  		p, err := dl.LoadPartition(rt.AdtStore(), pIdx)
  2999  		require.NoError(t, err)
  3000  		assert.Equal(t, p.Faults, p.Recoveries)
  3001  		actor.checkState(rt)
  3002  	})
  3003  
  3004  	t.Run("recovery must pay back fee debt", func(t *testing.T) {
  3005  		rt := builder.Build(t)
  3006  		actor.constructAndVerify(rt)
  3007  		oneSector := actor.commitAndProveSectors(rt, 1, defaultSectorExpiration, nil, true)
  3008  		// advance to first proving period and submit so we'll have time to declare the fault next cycle
  3009  		advanceAndSubmitPoSts(rt, actor, oneSector...)
  3010  
  3011  		// Fault will take miner into fee debt
  3012  		st := getState(rt)
  3013  		rt.SetBalance(big.Sum(st.PreCommitDeposits, st.InitialPledge, st.LockedFunds))
  3014  
  3015  		actor.declareFaults(rt, oneSector...)
  3016  
  3017  		st = getState(rt)
  3018  		dlIdx, pIdx, err := st.FindSector(rt.AdtStore(), oneSector[0].SectorNumber)
  3019  		require.NoError(t, err)
  3020  
  3021  		// Skip to end of proving period.
  3022  		dlinfo := actor.deadline(rt)
  3023  		for dlinfo.Index != dlIdx {
  3024  			dlinfo = advanceDeadline(rt, actor, &cronConfig{})
  3025  		}
  3026  
  3027  		// Can't pay during this deadline so miner goes into fee debt
  3028  		ongoingPwr := miner.PowerForSectors(actor.sectorSize, oneSector)
  3029  		ff := miner.PledgePenaltyForContinuedFault(actor.epochRewardSmooth, actor.epochQAPowerSmooth, ongoingPwr.QA)
  3030  		advanceDeadline(rt, actor, &cronConfig{
  3031  			continuedFaultsPenalty: big.Zero(), // fee is instead added to debt
  3032  		})
  3033  
  3034  		st = getState(rt)
  3035  		assert.Equal(t, ff, st.FeeDebt)
  3036  
  3037  		// Recovery fails when it can't pay back fee debt
  3038  		rt.ExpectAbortContainsMessage(exitcode.ErrInsufficientFunds, "unlocked balance can not repay fee debt", func() {
  3039  			actor.declareRecoveries(rt, dlIdx, pIdx, bf(uint64(oneSector[0].SectorNumber)), big.Zero())
  3040  		})
  3041  
  3042  		// Recovery pays back fee debt and IP requirements and succeeds
  3043  		funds := big.Add(ff, st.InitialPledge)
  3044  		rt.SetBalance(funds) // this is how we send funds along with recovery message using mock rt
  3045  		actor.declareRecoveries(rt, dlIdx, pIdx, bf(uint64(oneSector[0].SectorNumber)), ff)
  3046  
  3047  		dl := actor.getDeadline(rt, dlIdx)
  3048  		p, err := dl.LoadPartition(rt.AdtStore(), pIdx)
  3049  		require.NoError(t, err)
  3050  		assert.Equal(t, p.Faults, p.Recoveries)
  3051  		st = getState(rt)
  3052  		assert.Equal(t, big.Zero(), st.FeeDebt)
  3053  		actor.checkState(rt)
  3054  	})
  3055  
  3056  	t.Run("recovery fails during active consensus fault", func(t *testing.T) {
  3057  		rt := builder.Build(t)
  3058  		actor.constructAndVerify(rt)
  3059  		oneSector := actor.commitAndProveSectors(rt, 1, defaultSectorExpiration, nil, true)
  3060  
  3061  		// consensus fault
  3062  		actor.reportConsensusFault(rt, addr.TestAddress, &runtime.ConsensusFault{
  3063  			Target: actor.receiver,
  3064  			Epoch:  rt.Epoch() - 1,
  3065  			Type:   runtime.ConsensusFaultDoubleForkMining,
  3066  		})
  3067  
  3068  		// advance to first proving period and submit so we'll have time to declare the fault next cycle
  3069  		advanceAndSubmitPoSts(rt, actor, oneSector...)
  3070  
  3071  		// Declare the sector as faulted
  3072  		actor.declareFaults(rt, oneSector...)
  3073  
  3074  		st := getState(rt)
  3075  		dlIdx, pIdx, err := st.FindSector(rt.AdtStore(), oneSector[0].SectorNumber)
  3076  		require.NoError(t, err)
  3077  		rt.ExpectAbortContainsMessage(exitcode.ErrForbidden, "recovery not allowed during active consensus fault", func() {
  3078  			actor.declareRecoveries(rt, dlIdx, pIdx, bf(uint64(oneSector[0].SectorNumber)), big.Zero())
  3079  		})
  3080  		actor.checkState(rt)
  3081  	})
  3082  }
  3083  
  3084  func TestExtendSectorExpiration(t *testing.T) {
  3085  	periodOffset := abi.ChainEpoch(100)
  3086  	actor := newHarness(t, periodOffset)
  3087  	precommitEpoch := abi.ChainEpoch(1)
  3088  	builder := builderForHarness(actor).
  3089  		WithEpoch(precommitEpoch).
  3090  		WithBalance(bigBalance, big.Zero())
  3091  
  3092  	commitSector := func(t *testing.T, rt *mock.Runtime) *miner.SectorOnChainInfo {
  3093  		actor.constructAndVerify(rt)
  3094  		sectorInfo := actor.commitAndProveSectors(rt, 1, defaultSectorExpiration, nil, true)
  3095  		return sectorInfo[0]
  3096  	}
  3097  
  3098  	t.Run("rejects negative extension", func(t *testing.T) {
  3099  		rt := builder.Build(t)
  3100  		sector := commitSector(t, rt)
  3101  
  3102  		// attempt to shorten epoch
  3103  		newExpiration := sector.Expiration - abi.ChainEpoch(miner.WPoStProvingPeriod)
  3104  
  3105  		// find deadline and partition
  3106  		st := getState(rt)
  3107  		dlIdx, pIdx, err := st.FindSector(rt.AdtStore(), sector.SectorNumber)
  3108  		require.NoError(t, err)
  3109  
  3110  		params := &miner.ExtendSectorExpirationParams{
  3111  			Extensions: []miner.ExpirationExtension{{
  3112  				Deadline:      dlIdx,
  3113  				Partition:     pIdx,
  3114  				Sectors:       bf(uint64(sector.SectorNumber)),
  3115  				NewExpiration: newExpiration,
  3116  			}},
  3117  		}
  3118  
  3119  		rt.ExpectAbortContainsMessage(exitcode.ErrIllegalArgument, fmt.Sprintf("cannot reduce sector %d's expiration", sector.SectorNumber), func() {
  3120  			actor.extendSectors(rt, params)
  3121  		})
  3122  		actor.checkState(rt)
  3123  	})
  3124  
  3125  	t.Run("rejects extension too far in future", func(t *testing.T) {
  3126  		rt := builder.Build(t)
  3127  		sector := commitSector(t, rt)
  3128  
  3129  		// extend by even proving period after max
  3130  		rt.SetEpoch(sector.Expiration)
  3131  		extension := miner.WPoStProvingPeriod * (miner.MaxSectorExpirationExtension/miner.WPoStProvingPeriod + 1)
  3132  		newExpiration := rt.Epoch() + extension
  3133  
  3134  		// find deadline and partition
  3135  		st := getState(rt)
  3136  		dlIdx, pIdx, err := st.FindSector(rt.AdtStore(), sector.SectorNumber)
  3137  		require.NoError(t, err)
  3138  
  3139  		params := &miner.ExtendSectorExpirationParams{
  3140  			Extensions: []miner.ExpirationExtension{{
  3141  				Deadline:      dlIdx,
  3142  				Partition:     pIdx,
  3143  				Sectors:       bf(uint64(sector.SectorNumber)),
  3144  				NewExpiration: newExpiration,
  3145  			}},
  3146  		}
  3147  
  3148  		expectedMessage := fmt.Sprintf("cannot be more than %d past current epoch", miner.MaxSectorExpirationExtension)
  3149  		rt.ExpectAbortContainsMessage(exitcode.ErrIllegalArgument, expectedMessage, func() {
  3150  			actor.extendSectors(rt, params)
  3151  		})
  3152  		actor.checkState(rt)
  3153  	})
  3154  
  3155  	t.Run("rejects extension past max for seal proof", func(t *testing.T) {
  3156  		rt := builder.Build(t)
  3157  		sector := commitSector(t, rt)
  3158  		// and prove it once to activate it.
  3159  		advanceAndSubmitPoSts(rt, actor, sector)
  3160  
  3161  		maxLifetime, err := builtin.SealProofSectorMaximumLifetime(sector.SealProof, network.VersionMax)
  3162  		require.NoError(t, err)
  3163  
  3164  		st := getState(rt)
  3165  		dlIdx, pIdx, err := st.FindSector(rt.AdtStore(), sector.SectorNumber)
  3166  		require.NoError(t, err)
  3167  
  3168  		// extend sector until just below threshold
  3169  		rt.SetEpoch(sector.Expiration)
  3170  		extension := abi.ChainEpoch(miner.MinSectorExpiration)
  3171  		expiration := sector.Expiration + extension
  3172  		for ; expiration-sector.Activation < maxLifetime; expiration += extension {
  3173  			params := &miner.ExtendSectorExpirationParams{
  3174  				Extensions: []miner.ExpirationExtension{{
  3175  					Deadline:      dlIdx,
  3176  					Partition:     pIdx,
  3177  					Sectors:       bf(uint64(sector.SectorNumber)),
  3178  					NewExpiration: expiration,
  3179  				}},
  3180  			}
  3181  
  3182  			actor.extendSectors(rt, params)
  3183  			sector.Expiration = expiration
  3184  			rt.SetEpoch(expiration)
  3185  		}
  3186  
  3187  		// next extension fails because it extends sector past max lifetime
  3188  		params := &miner.ExtendSectorExpirationParams{
  3189  			Extensions: []miner.ExpirationExtension{{
  3190  				Deadline:      dlIdx,
  3191  				Partition:     pIdx,
  3192  				Sectors:       bf(uint64(sector.SectorNumber)),
  3193  				NewExpiration: expiration,
  3194  			}},
  3195  		}
  3196  
  3197  		rt.ExpectAbortContainsMessage(exitcode.ErrIllegalArgument, "total sector lifetime", func() {
  3198  			actor.extendSectors(rt, params)
  3199  		})
  3200  
  3201  		actor.checkState(rt)
  3202  	})
  3203  
  3204  	t.Run("updates expiration with valid params", func(t *testing.T) {
  3205  		rt := builder.Build(t)
  3206  		oldSector := commitSector(t, rt)
  3207  		advanceAndSubmitPoSts(rt, actor, oldSector)
  3208  
  3209  		st := getState(rt)
  3210  		dlIdx, pIdx, err := st.FindSector(rt.AdtStore(), oldSector.SectorNumber)
  3211  		require.NoError(t, err)
  3212  
  3213  		extension := 42 * miner.WPoStProvingPeriod
  3214  		newExpiration := oldSector.Expiration + extension
  3215  		params := &miner.ExtendSectorExpirationParams{
  3216  			Extensions: []miner.ExpirationExtension{{
  3217  				Deadline:      dlIdx,
  3218  				Partition:     pIdx,
  3219  				Sectors:       bf(uint64(oldSector.SectorNumber)),
  3220  				NewExpiration: newExpiration,
  3221  			}},
  3222  		}
  3223  
  3224  		actor.extendSectors(rt, params)
  3225  
  3226  		// assert sector expiration is set to the new value
  3227  		newSector := actor.getSector(rt, oldSector.SectorNumber)
  3228  		assert.Equal(t, newExpiration, newSector.Expiration)
  3229  
  3230  		quant := st.QuantSpecForDeadline(dlIdx)
  3231  
  3232  		// assert that new expiration exists
  3233  		_, partition := actor.getDeadlineAndPartition(rt, dlIdx, pIdx)
  3234  		expirationSet, err := partition.PopExpiredSectors(rt.AdtStore(), newExpiration-1, quant)
  3235  		require.NoError(t, err)
  3236  		empty, err := expirationSet.IsEmpty()
  3237  		require.NoError(t, err)
  3238  		assert.True(t, empty)
  3239  
  3240  		expirationSet, err = partition.PopExpiredSectors(rt.AdtStore(), quant.QuantizeUp(newExpiration), quant)
  3241  		require.NoError(t, err)
  3242  		empty, err = expirationSet.IsEmpty()
  3243  		require.NoError(t, err)
  3244  		assert.False(t, empty)
  3245  
  3246  		actor.checkState(rt)
  3247  	})
  3248  
  3249  	t.Run("updates many sectors", func(t *testing.T) {
  3250  		rt := builder.Build(t)
  3251  		actor.constructAndVerify(rt)
  3252  
  3253  		const sectorCount = 4000
  3254  
  3255  		// commit a bunch of sectors to ensure that we get multiple partitions.
  3256  		sectorInfos := actor.commitAndProveSectors(rt, sectorCount, defaultSectorExpiration, nil, true)
  3257  		advanceAndSubmitPoSts(rt, actor, sectorInfos...)
  3258  
  3259  		newExpiration := sectorInfos[0].Expiration + 42*miner.WPoStProvingPeriod
  3260  
  3261  		var params miner.ExtendSectorExpirationParams
  3262  
  3263  		// extend all odd-numbered sectors.
  3264  		{
  3265  			st := getState(rt)
  3266  			deadlines, err := st.LoadDeadlines(rt.AdtStore())
  3267  			require.NoError(t, err)
  3268  			require.NoError(t, deadlines.ForEach(rt.AdtStore(), func(dlIdx uint64, dl *miner.Deadline) error {
  3269  				partitions, err := dl.PartitionsArray(rt.AdtStore())
  3270  				require.NoError(t, err)
  3271  				var partition miner.Partition
  3272  				require.NoError(t, partitions.ForEach(&partition, func(partIdx int64) error {
  3273  					oldSectorNos, err := partition.Sectors.All(miner.AddressedSectorsMax)
  3274  					require.NoError(t, err)
  3275  
  3276  					// filter out even-numbered sectors.
  3277  					newSectorNos := make([]uint64, 0, len(oldSectorNos)/2)
  3278  					for _, sno := range oldSectorNos {
  3279  						if sno%2 == 0 {
  3280  							continue
  3281  						}
  3282  						newSectorNos = append(newSectorNos, sno)
  3283  					}
  3284  					params.Extensions = append(params.Extensions, miner.ExpirationExtension{
  3285  						Deadline:      dlIdx,
  3286  						Partition:     uint64(partIdx),
  3287  						Sectors:       bf(newSectorNos...),
  3288  						NewExpiration: newExpiration,
  3289  					})
  3290  					return nil
  3291  				}))
  3292  				return nil
  3293  			}))
  3294  		}
  3295  
  3296  		// Make sure we're touching at least two sectors.
  3297  		require.GreaterOrEqual(t, len(params.Extensions), 2,
  3298  			"test error: this test should touch more than one partition",
  3299  		)
  3300  
  3301  		actor.extendSectors(rt, &params)
  3302  
  3303  		{
  3304  			st := getState(rt)
  3305  			deadlines, err := st.LoadDeadlines(rt.AdtStore())
  3306  			require.NoError(t, err)
  3307  
  3308  			// Half the sectors should expire on-time.
  3309  			var onTimeTotal uint64
  3310  			require.NoError(t, deadlines.ForEach(rt.AdtStore(), func(dlIdx uint64, dl *miner.Deadline) error {
  3311  				expirationSet, err := dl.PopExpiredSectors(rt.AdtStore(), newExpiration-1, st.QuantSpecForDeadline(dlIdx))
  3312  				require.NoError(t, err)
  3313  
  3314  				count, err := expirationSet.Count()
  3315  				require.NoError(t, err)
  3316  				onTimeTotal += count
  3317  				return nil
  3318  			}))
  3319  			assert.EqualValues(t, sectorCount/2, onTimeTotal)
  3320  
  3321  			// Half the sectors should expire late.
  3322  			var extendedTotal uint64
  3323  			require.NoError(t, deadlines.ForEach(rt.AdtStore(), func(dlIdx uint64, dl *miner.Deadline) error {
  3324  				expirationSet, err := dl.PopExpiredSectors(rt.AdtStore(), newExpiration-1, st.QuantSpecForDeadline(dlIdx))
  3325  				require.NoError(t, err)
  3326  
  3327  				count, err := expirationSet.Count()
  3328  				require.NoError(t, err)
  3329  				extendedTotal += count
  3330  				return nil
  3331  			}))
  3332  			assert.EqualValues(t, sectorCount/2, extendedTotal)
  3333  		}
  3334  
  3335  		actor.checkState(rt)
  3336  	})
  3337  
  3338  	t.Run("supports extensions off deadline boundary", func(t *testing.T) {
  3339  		rt := builder.Build(t)
  3340  		oldSector := commitSector(t, rt)
  3341  		advanceAndSubmitPoSts(rt, actor, oldSector)
  3342  
  3343  		st := getState(rt)
  3344  		dlIdx, pIdx, err := st.FindSector(rt.AdtStore(), oldSector.SectorNumber)
  3345  		require.NoError(t, err)
  3346  
  3347  		extension := 42*miner.WPoStProvingPeriod + miner.WPoStProvingPeriod/3
  3348  		newExpiration := oldSector.Expiration + extension
  3349  		params := &miner.ExtendSectorExpirationParams{
  3350  			Extensions: []miner.ExpirationExtension{{
  3351  				Deadline:      dlIdx,
  3352  				Partition:     pIdx,
  3353  				Sectors:       bf(uint64(oldSector.SectorNumber)),
  3354  				NewExpiration: newExpiration,
  3355  			}},
  3356  		}
  3357  
  3358  		actor.extendSectors(rt, params)
  3359  
  3360  		// assert sector expiration is set to the new value
  3361  		st = getState(rt)
  3362  		newSector := actor.getSector(rt, oldSector.SectorNumber)
  3363  		assert.Equal(t, newExpiration, newSector.Expiration)
  3364  
  3365  		// advance clock to expiration
  3366  		rt.SetEpoch(newSector.Expiration)
  3367  		st.ProvingPeriodStart += miner.WPoStProvingPeriod * ((rt.Epoch()-st.ProvingPeriodStart)/miner.WPoStProvingPeriod + 1)
  3368  		rt.ReplaceState(st)
  3369  
  3370  		// confirm it is not in sector's deadline
  3371  		dlinfo := actor.deadline(rt)
  3372  		assert.NotEqual(t, dlIdx, dlinfo.Index)
  3373  
  3374  		// advance to deadline and submit one last PoSt
  3375  		for dlinfo.Index != dlIdx {
  3376  			dlinfo = advanceDeadline(rt, actor, &cronConfig{})
  3377  		}
  3378  		partitions := []miner.PoStPartition{
  3379  			{Index: pIdx, Skipped: bitfield.New()},
  3380  		}
  3381  		actor.submitWindowPoSt(rt, dlinfo, partitions, []*miner.SectorOnChainInfo{newSector}, nil)
  3382  
  3383  		// advance one more time. No missed PoSt fees are charged. Total Power and pledge are lowered.
  3384  		pwr := miner.PowerForSectors(actor.sectorSize, []*miner.SectorOnChainInfo{newSector}).Neg()
  3385  		advanceDeadline(rt, actor, &cronConfig{
  3386  			noEnrollment:              true,
  3387  			expiredSectorsPowerDelta:  &pwr,
  3388  			expiredSectorsPledgeDelta: newSector.InitialPledge.Neg(),
  3389  		})
  3390  		st = getState(rt)
  3391  		assert.False(t, st.DeadlineCronActive)
  3392  		actor.checkState(rt)
  3393  	})
  3394  
  3395  	t.Run("prevents extending old seal proof types", func(t *testing.T) {
  3396  		actor := newHarness(t, periodOffset)
  3397  		actor.setProofType(abi.RegisteredSealProof_StackedDrg32GiBV1)
  3398  		rt := builderForHarness(actor).
  3399  			WithBalance(bigBalance, big.Zero()).
  3400  			Build(t)
  3401  		rt.SetNetworkVersion(network.Version7)
  3402  		actor.constructAndVerify(rt)
  3403  
  3404  		// Commit and prove first sector with V1
  3405  		rt.SetEpoch(periodOffset + miner.WPoStChallengeWindow)
  3406  		sector := actor.commitAndProveSector(rt, 101, defaultSectorExpiration, nil)
  3407  		assert.Equal(t, abi.RegisteredSealProof_StackedDrg32GiBV1, sector.SealProof)
  3408  
  3409  		st := getState(rt)
  3410  		dlIdx, pIdx, err := st.FindSector(rt.AdtStore(), sector.SectorNumber)
  3411  		require.NoError(t, err)
  3412  
  3413  		newExpiration := sector.Expiration + abi.ChainEpoch(miner.MinSectorExpiration)
  3414  		params := &miner.ExtendSectorExpirationParams{
  3415  			Extensions: []miner.ExpirationExtension{{
  3416  				Deadline:      dlIdx,
  3417  				Partition:     pIdx,
  3418  				Sectors:       bf(uint64(sector.SectorNumber)),
  3419  				NewExpiration: newExpiration,
  3420  			}},
  3421  		}
  3422  
  3423  		rt.ExpectAbortContainsMessage(exitcode.ErrForbidden, "unsupported seal type", func() {
  3424  			actor.extendSectors(rt, params)
  3425  		})
  3426  		actor.checkState(rt)
  3427  	})
  3428  }
  3429  
  3430  func TestTerminateSectors(t *testing.T) {
  3431  	periodOffset := abi.ChainEpoch(100)
  3432  	actor := newHarness(t, periodOffset)
  3433  	builder := builderForHarness(actor).
  3434  		WithBalance(big.Mul(big.NewInt(1e18), big.NewInt(200000)), big.Zero())
  3435  
  3436  	t.Run("removes sector with correct accounting", func(t *testing.T) {
  3437  		rt := builder.Build(t)
  3438  		actor.constructAndVerify(rt)
  3439  		rt.SetEpoch(abi.ChainEpoch(1))
  3440  		sectorInfo := actor.commitAndProveSectors(rt, 1, defaultSectorExpiration, nil, true)
  3441  		sector := sectorInfo[0]
  3442  		advanceAndSubmitPoSts(rt, actor, sector)
  3443  
  3444  		// A miner will pay the minimum of termination fee and locked funds. Add some locked funds to ensure
  3445  		// correct fee calculation is used.
  3446  		actor.applyRewards(rt, bigRewards, big.Zero())
  3447  		st := getState(rt)
  3448  		initialLockedFunds := st.LockedFunds
  3449  
  3450  		sectorSize, err := sector.SealProof.SectorSize()
  3451  		require.NoError(t, err)
  3452  		sectorPower := miner.QAPowerForSector(sectorSize, sector)
  3453  		dayReward := miner.ExpectedRewardForPower(actor.epochRewardSmooth, actor.epochQAPowerSmooth, sectorPower, builtin.EpochsInDay)
  3454  		twentyDayReward := miner.ExpectedRewardForPower(actor.epochRewardSmooth, actor.epochQAPowerSmooth, sectorPower, miner.InitialPledgeProjectionPeriod)
  3455  		sectorAge := rt.Epoch() - sector.Activation
  3456  		expectedFee := miner.PledgePenaltyForTermination(dayReward, sectorAge, twentyDayReward, actor.epochQAPowerSmooth, sectorPower, actor.epochRewardSmooth, big.Zero(), 0)
  3457  
  3458  		sectors := bf(uint64(sector.SectorNumber))
  3459  		actor.terminateSectors(rt, sectors, expectedFee)
  3460  
  3461  		{
  3462  			st := getState(rt)
  3463  
  3464  			// expect sector to be marked as terminated and the early termination queue to be empty (having been fully processed)
  3465  			_, partition := actor.findSector(rt, sector.SectorNumber)
  3466  			terminated, err := partition.Terminated.IsSet(uint64(sector.SectorNumber))
  3467  			require.NoError(t, err)
  3468  			assert.True(t, terminated)
  3469  			result, _, err := partition.PopEarlyTerminations(rt.AdtStore(), 1000)
  3470  			require.NoError(t, err)
  3471  			assert.True(t, result.IsEmpty())
  3472  
  3473  			// expect fee to have been unlocked and burnt
  3474  			assert.Equal(t, big.Sub(initialLockedFunds, expectedFee), st.LockedFunds)
  3475  
  3476  			// expect pledge requirement to have been decremented
  3477  			assert.Equal(t, big.Zero(), st.InitialPledge)
  3478  		}
  3479  		actor.checkState(rt)
  3480  	})
  3481  
  3482  	t.Run("charges correct fee for young termination of committed capacity upgrade", func(t *testing.T) {
  3483  		actor := newHarness(t, periodOffset)
  3484  		rt := builderForHarness(actor).
  3485  			WithBalance(bigBalance, big.Zero()).
  3486  			Build(t)
  3487  		actor.constructAndVerify(rt)
  3488  
  3489  		// Move the current epoch forward so that the first deadline is a stable candidate for both sectors
  3490  		rt.SetEpoch(periodOffset + miner.WPoStChallengeWindow)
  3491  
  3492  		// Commit a sector to upgrade
  3493  		oldSector := actor.commitAndProveSector(rt, 1, defaultSectorExpiration, nil)
  3494  		advanceAndSubmitPoSts(rt, actor, oldSector) // activate power
  3495  		st := getState(rt)
  3496  		dlIdx, partIdx, err := st.FindSector(rt.AdtStore(), oldSector.SectorNumber)
  3497  		require.NoError(t, err)
  3498  
  3499  		// advance clock so upgrade happens later
  3500  		for i := 0; i < 4; i++ { // 4 * 2880 = 11,520
  3501  			advanceAndSubmitPoSts(rt, actor, oldSector)
  3502  		}
  3503  
  3504  		challengeEpoch := rt.Epoch() - 1
  3505  		upgradeParams := actor.makePreCommit(200, challengeEpoch, oldSector.Expiration, []abi.DealID{1})
  3506  		upgradeParams.ReplaceCapacity = true
  3507  		upgradeParams.ReplaceSectorDeadline = dlIdx
  3508  		upgradeParams.ReplaceSectorPartition = partIdx
  3509  		upgradeParams.ReplaceSectorNumber = oldSector.SectorNumber
  3510  		upgrade := actor.preCommitSector(rt, upgradeParams, preCommitConf{}, false)
  3511  
  3512  		// Prove new sector
  3513  		rt.SetEpoch(upgrade.PreCommitEpoch + miner.PreCommitChallengeDelay + 1)
  3514  		newSector := actor.proveCommitSectorAndConfirm(rt, upgrade, makeProveCommit(upgrade.Info.SectorNumber), proveCommitConf{})
  3515  
  3516  		// Expect replace parameters have been set
  3517  		assert.Equal(t, oldSector.ExpectedDayReward, newSector.ReplacedDayReward)
  3518  		assert.Equal(t, rt.Epoch()-oldSector.Activation, newSector.ReplacedSectorAge)
  3519  
  3520  		// advance to deadline of new and old sectors
  3521  		dlInfo := actor.currentDeadline(rt)
  3522  		for dlInfo.Index != dlIdx {
  3523  			dlInfo = advanceDeadline(rt, actor, &cronConfig{})
  3524  		}
  3525  		/**/
  3526  		// PoSt both sectors. They both gain power and no penalties are incurred.
  3527  		rt.SetEpoch(dlInfo.Last())
  3528  		oldPower := miner.NewPowerPair(big.NewInt(int64(actor.sectorSize)), miner.QAPowerForSector(actor.sectorSize, oldSector))
  3529  		newPower := miner.NewPowerPair(big.NewInt(int64(actor.sectorSize)), miner.QAPowerForSector(actor.sectorSize, newSector))
  3530  		partitions := []miner.PoStPartition{
  3531  			{Index: partIdx, Skipped: bitfield.New()},
  3532  		}
  3533  		actor.submitWindowPoSt(rt, dlInfo, partitions, []*miner.SectorOnChainInfo{newSector, oldSector}, &poStConfig{
  3534  			expectedPowerDelta: newPower,
  3535  		})
  3536  
  3537  		// replaced sector expires at cron, removing its power and pledge.
  3538  		expectedPowerDelta := oldPower.Neg()
  3539  		actor.onDeadlineCron(rt, &cronConfig{
  3540  			expiredSectorsPowerDelta:  &expectedPowerDelta,
  3541  			expiredSectorsPledgeDelta: oldSector.InitialPledge.Neg(),
  3542  			expectedEnrollment:        rt.Epoch() + miner.WPoStChallengeWindow,
  3543  		})
  3544  		actor.checkState(rt)
  3545  
  3546  		// advance clock a little and terminate new sector
  3547  		rt.SetEpoch(rt.Epoch() + 5_000)
  3548  
  3549  		// Add some locked funds to ensure full termination fee appears as pledge change.
  3550  		actor.applyRewards(rt, bigRewards, big.Zero())
  3551  
  3552  		sectorPower := miner.QAPowerForSector(actor.sectorSize, newSector)
  3553  		twentyDayReward := miner.ExpectedRewardForPower(actor.epochRewardSmooth, actor.epochQAPowerSmooth, sectorPower, miner.InitialPledgeProjectionPeriod)
  3554  		newSectorAge := rt.Epoch() - newSector.Activation
  3555  		oldSectorAge := newSector.Activation - oldSector.Activation
  3556  		expectedFee := miner.PledgePenaltyForTermination(newSector.ExpectedDayReward, newSectorAge, twentyDayReward,
  3557  			actor.epochQAPowerSmooth, sectorPower, actor.epochRewardSmooth, oldSector.ExpectedDayReward, oldSectorAge)
  3558  
  3559  		sectors := bf(uint64(newSector.SectorNumber))
  3560  		actor.terminateSectors(rt, sectors, expectedFee)
  3561  		actor.checkState(rt)
  3562  	})
  3563  
  3564  	t.Run("cannot terminate a sector when the challenge window is open", func(t *testing.T) {
  3565  		rt := builder.Build(t)
  3566  		actor.constructAndVerify(rt)
  3567  		rt.SetEpoch(abi.ChainEpoch(1))
  3568  		sectorInfo := actor.commitAndProveSectors(rt, 1, defaultSectorExpiration, nil, true)
  3569  		sector := sectorInfo[0]
  3570  
  3571  		st := getState(rt)
  3572  		dlIdx, pIdx, err := st.FindSector(rt.AdtStore(), sector.SectorNumber)
  3573  		require.NoError(t, err)
  3574  
  3575  		// advance into the deadline, but not past it.
  3576  		dlinfo := actor.deadline(rt)
  3577  		for dlinfo.Index != dlIdx {
  3578  			dlinfo = advanceDeadline(rt, actor, &cronConfig{})
  3579  		}
  3580  
  3581  		params := &miner.TerminateSectorsParams{Terminations: []miner.TerminationDeclaration{{
  3582  			Deadline:  dlIdx,
  3583  			Partition: pIdx,
  3584  			Sectors:   bf(uint64(sector.SectorNumber)),
  3585  		}}}
  3586  		rt.SetCaller(actor.worker, builtin.AccountActorCodeID)
  3587  		rt.ExpectValidateCallerAddr(append(actor.controlAddrs, actor.owner, actor.worker)...)
  3588  		rt.ExpectAbortContainsMessage(exitcode.ErrIllegalArgument, "cannot terminate sectors in immutable deadline", func() {
  3589  			rt.Call(actor.a.TerminateSectors, params)
  3590  		})
  3591  
  3592  		actor.checkState(rt)
  3593  	})
  3594  
  3595  }
  3596  
  3597  func TestWithdrawBalance(t *testing.T) {
  3598  	periodOffset := abi.ChainEpoch(100)
  3599  	actor := newHarness(t, periodOffset)
  3600  	builder := builderForHarness(actor).
  3601  		WithBalance(bigBalance, big.Zero())
  3602  
  3603  	onePercentBalance := big.Div(bigBalance, big.NewInt(100))
  3604  
  3605  	t.Run("happy path withdraws funds", func(t *testing.T) {
  3606  		rt := builder.Build(t)
  3607  		actor.constructAndVerify(rt)
  3608  
  3609  		// withdraw 1% of balance
  3610  		actor.withdrawFunds(rt, onePercentBalance, onePercentBalance, big.Zero())
  3611  		actor.checkState(rt)
  3612  	})
  3613  
  3614  	t.Run("fails if miner can't repay fee debt", func(t *testing.T) {
  3615  		rt := builder.Build(t)
  3616  		actor.constructAndVerify(rt)
  3617  
  3618  		st := getState(rt)
  3619  		st.FeeDebt = big.Add(rt.Balance(), abi.NewTokenAmount(1e18))
  3620  		rt.ReplaceState(st)
  3621  		rt.ExpectAbortContainsMessage(exitcode.ErrInsufficientFunds, "unlocked balance can not repay fee debt", func() {
  3622  			actor.withdrawFunds(rt, onePercentBalance, onePercentBalance, big.Zero())
  3623  		})
  3624  		actor.checkState(rt)
  3625  	})
  3626  
  3627  	t.Run("withdraw only what we can after fee debt", func(t *testing.T) {
  3628  		rt := builder.Build(t)
  3629  		actor.constructAndVerify(rt)
  3630  
  3631  		st := getState(rt)
  3632  		feeDebt := big.Sub(bigBalance, onePercentBalance)
  3633  		st.FeeDebt = feeDebt
  3634  		rt.ReplaceState(st)
  3635  
  3636  		requested := rt.Balance()
  3637  		expectedWithdraw := big.Sub(requested, feeDebt)
  3638  		actor.withdrawFunds(rt, requested, expectedWithdraw, feeDebt)
  3639  		actor.checkState(rt)
  3640  	})
  3641  }
  3642  
  3643  func TestRepayDebts(t *testing.T) {
  3644  	actor := newHarness(t, abi.ChainEpoch(100))
  3645  	builder := builderForHarness(actor).
  3646  		WithBalance(big.Zero(), big.Zero())
  3647  
  3648  	t.Run("repay with no avaialable funds does nothing", func(t *testing.T) {
  3649  		rt := builder.Build(t)
  3650  		actor.constructAndVerify(rt)
  3651  
  3652  		// introduce fee debt
  3653  		st := getState(rt)
  3654  		feeDebt := big.Mul(big.NewInt(4), big.NewInt(1e18))
  3655  		st.FeeDebt = feeDebt
  3656  		rt.ReplaceState(st)
  3657  
  3658  		actor.repayDebt(rt, big.Zero(), big.Zero(), big.Zero())
  3659  
  3660  		st = getState(rt)
  3661  		assert.Equal(t, feeDebt, st.FeeDebt)
  3662  		actor.checkState(rt)
  3663  	})
  3664  
  3665  	t.Run("pay debt entirely from balance", func(t *testing.T) {
  3666  		rt := builder.Build(t)
  3667  		actor.constructAndVerify(rt)
  3668  
  3669  		// introduce fee debt
  3670  		st := getState(rt)
  3671  		feeDebt := big.Mul(big.NewInt(4), big.NewInt(1e18))
  3672  		st.FeeDebt = feeDebt
  3673  		rt.ReplaceState(st)
  3674  
  3675  		debtToRepay := big.Mul(big.NewInt(2), feeDebt)
  3676  		actor.repayDebt(rt, debtToRepay, big.Zero(), feeDebt)
  3677  
  3678  		st = getState(rt)
  3679  		assert.Equal(t, big.Zero(), st.FeeDebt)
  3680  		actor.checkState(rt)
  3681  	})
  3682  
  3683  	t.Run("partially repay debt", func(t *testing.T) {
  3684  		rt := builder.Build(t)
  3685  		actor.constructAndVerify(rt)
  3686  
  3687  		// introduce fee debt
  3688  		st := getState(rt)
  3689  		feeDebt := big.Mul(big.NewInt(4), big.NewInt(1e18))
  3690  		st.FeeDebt = feeDebt
  3691  		rt.ReplaceState(st)
  3692  
  3693  		debtToRepay := big.Mul(big.NewInt(3), big.Div(feeDebt, big.NewInt(4)))
  3694  		actor.repayDebt(rt, debtToRepay, big.Zero(), debtToRepay)
  3695  
  3696  		st = getState(rt)
  3697  		assert.Equal(t, big.Div(feeDebt, big.NewInt(4)), st.FeeDebt)
  3698  		actor.checkState(rt)
  3699  	})
  3700  
  3701  	t.Run("pay debt partially from vested funds", func(t *testing.T) {
  3702  		rt := builder.Build(t)
  3703  		actor.constructAndVerify(rt)
  3704  
  3705  		rewardAmount := big.Mul(big.NewInt(4), big.NewInt(1e18))
  3706  		amountLocked, _ := miner.LockedRewardFromReward(rewardAmount)
  3707  		rt.SetBalance(amountLocked)
  3708  		actor.applyRewards(rt, rewardAmount, big.Zero())
  3709  		require.Equal(t, amountLocked, actor.getLockedFunds(rt))
  3710  
  3711  		// introduce fee debt
  3712  		st := getState(rt)
  3713  		feeDebt := big.Mul(big.NewInt(4), big.NewInt(1e18))
  3714  		st.FeeDebt = feeDebt
  3715  		rt.ReplaceState(st)
  3716  
  3717  		// send 1 FIL and repay all debt from vesting funds and balance
  3718  		actor.repayDebt(rt,
  3719  			big.NewInt(1e18), // send 1 FIL
  3720  			amountLocked,     // 3 FIL comes from vesting funds
  3721  			big.NewInt(1e18)) // 1 FIL sent from balance
  3722  
  3723  		st = getState(rt)
  3724  		assert.Equal(t, big.Zero(), st.FeeDebt)
  3725  		actor.checkState(rt)
  3726  	})
  3727  }
  3728  
  3729  func TestChangePeerID(t *testing.T) {
  3730  	periodOffset := abi.ChainEpoch(100)
  3731  	actor := newHarness(t, periodOffset)
  3732  	builder := builderForHarness(actor).
  3733  		WithBalance(bigBalance, big.Zero())
  3734  
  3735  	t.Run("successfully change peer id", func(t *testing.T) {
  3736  		rt := builder.Build(t)
  3737  		actor.constructAndVerify(rt)
  3738  
  3739  		newPID := tutil.MakePID("test-change-peer-id")
  3740  		actor.changePeerID(rt, newPID)
  3741  		actor.checkState(rt)
  3742  	})
  3743  }
  3744  
  3745  func TestCompactPartitions(t *testing.T) {
  3746  	periodOffset := abi.ChainEpoch(100)
  3747  	actor := newHarness(t, periodOffset)
  3748  	builder := builderForHarness(actor).
  3749  		WithBalance(bigBalance, big.Zero())
  3750  
  3751  	assertSectorExists := func(store adt.Store, st *miner.State, sectorNum abi.SectorNumber, expectPart uint64, expectDeadline uint64) {
  3752  		_, found, err := st.GetSector(store, sectorNum)
  3753  		require.NoError(t, err)
  3754  		require.True(t, found)
  3755  
  3756  		deadline, pid, err := st.FindSector(store, sectorNum)
  3757  		require.NoError(t, err)
  3758  		require.EqualValues(t, expectPart, pid)
  3759  		require.EqualValues(t, expectDeadline, deadline)
  3760  	}
  3761  
  3762  	assertSectorNotFound := func(store adt.Store, st *miner.State, sectorNum abi.SectorNumber) {
  3763  		_, found, err := st.GetSector(store, sectorNum)
  3764  		require.NoError(t, err)
  3765  		require.False(t, found)
  3766  
  3767  		_, _, err = st.FindSector(store, sectorNum)
  3768  		require.Error(t, err)
  3769  		require.Contains(t, err.Error(), "not due at any deadline")
  3770  	}
  3771  
  3772  	t.Run("compacting a partition with both live and dead sectors removes the dead sectors but retains the live sectors", func(t *testing.T) {
  3773  		rt := builder.Build(t)
  3774  		actor.constructAndVerify(rt)
  3775  
  3776  		rt.SetEpoch(200)
  3777  		// create 4 sectors in partition 0
  3778  		info := actor.commitAndProveSectors(rt, 4, defaultSectorExpiration, [][]abi.DealID{{10}, {20}, {30}, {40}}, true)
  3779  
  3780  		advanceAndSubmitPoSts(rt, actor, info...) // prove and activate power.
  3781  
  3782  		sector1 := info[0].SectorNumber
  3783  		sector2 := info[1].SectorNumber
  3784  		sector3 := info[2].SectorNumber
  3785  		sector4 := info[3].SectorNumber
  3786  
  3787  		// terminate sector1
  3788  		rt.SetEpoch(rt.Epoch() + 100)
  3789  		actor.applyRewards(rt, bigRewards, big.Zero())
  3790  		tsector := info[0]
  3791  		sectorSize, err := tsector.SealProof.SectorSize()
  3792  		require.NoError(t, err)
  3793  		sectorPower := miner.QAPowerForSector(sectorSize, tsector)
  3794  		dayReward := miner.ExpectedRewardForPower(actor.epochRewardSmooth, actor.epochQAPowerSmooth, sectorPower, builtin.EpochsInDay)
  3795  		twentyDayReward := miner.ExpectedRewardForPower(actor.epochRewardSmooth, actor.epochQAPowerSmooth, sectorPower, miner.InitialPledgeProjectionPeriod)
  3796  		sectorAge := rt.Epoch() - tsector.Activation
  3797  		expectedFee := miner.PledgePenaltyForTermination(dayReward, sectorAge, twentyDayReward, actor.epochQAPowerSmooth,
  3798  			sectorPower, actor.epochRewardSmooth, big.Zero(), 0)
  3799  
  3800  		sectors := bitfield.NewFromSet([]uint64{uint64(sector1)})
  3801  		actor.terminateSectors(rt, sectors, expectedFee)
  3802  
  3803  		// Wait WPoStProofChallengePeriod epochs so we can compact the sector.
  3804  		advanceToEpochWithCron(rt, actor, rt.Epoch()+miner.WPoStDisputeWindow)
  3805  
  3806  		// compacting partition will remove sector1 but retain sector 2, 3 and 4.
  3807  		partId := uint64(0)
  3808  		deadlineId := uint64(0)
  3809  		partitions := bitfield.NewFromSet([]uint64{partId})
  3810  		actor.compactPartitions(rt, deadlineId, partitions)
  3811  
  3812  		st := getState(rt)
  3813  		assertSectorExists(rt.AdtStore(), st, sector2, partId, deadlineId)
  3814  		assertSectorExists(rt.AdtStore(), st, sector3, partId, deadlineId)
  3815  		assertSectorExists(rt.AdtStore(), st, sector4, partId, deadlineId)
  3816  
  3817  		assertSectorNotFound(rt.AdtStore(), st, sector1)
  3818  		actor.checkState(rt)
  3819  	})
  3820  
  3821  	t.Run("fail to compact partitions with faults", func(T *testing.T) {
  3822  		rt := builder.Build(t)
  3823  		actor.constructAndVerify(rt)
  3824  
  3825  		rt.SetEpoch(200)
  3826  		// create 2 sectors in partition 0
  3827  		info := actor.commitAndProveSectors(rt, 2, defaultSectorExpiration, [][]abi.DealID{{10}, {20}}, true)
  3828  		advanceAndSubmitPoSts(rt, actor, info...) // prove and activate power.
  3829  
  3830  		// fault sector1
  3831  		actor.declareFaults(rt, info[0])
  3832  
  3833  		// Wait WPoStProofChallengePeriod epochs so we can compact the sector.
  3834  		advanceToEpochWithCron(rt, actor, rt.Epoch()+miner.WPoStDisputeWindow)
  3835  
  3836  		partId := uint64(0)
  3837  		deadlineId := uint64(0)
  3838  		rt.ExpectAbortContainsMessage(exitcode.ErrIllegalArgument, "failed to remove partitions from deadline 0: while removing partitions: cannot remove partition 0: has faults", func() {
  3839  			partitions := bitfield.NewFromSet([]uint64{partId})
  3840  			actor.compactPartitions(rt, deadlineId, partitions)
  3841  		})
  3842  		actor.checkState(rt)
  3843  	})
  3844  
  3845  	t.Run("fails to compact partitions with unproven sectors", func(T *testing.T) {
  3846  		rt := builder.Build(t)
  3847  		actor.constructAndVerify(rt)
  3848  
  3849  		// Wait until deadline 0 (the one to which we'll assign the
  3850  		// sector) has elapsed. That'll let us commit, prove, then wait
  3851  		// finality epochs.
  3852  		st := getState(rt)
  3853  		deadlineEpoch := miner.NewDeadlineInfo(st.ProvingPeriodStart, 0, rt.Epoch()).NextNotElapsed().NextOpen()
  3854  		rt.SetEpoch(deadlineEpoch)
  3855  
  3856  		// create 2 sectors in partition 0
  3857  		actor.commitAndProveSectors(rt, 2, defaultSectorExpiration, [][]abi.DealID{{10}, {20}}, true)
  3858  
  3859  		// Wait WPoStProofChallengePeriod epochs so we can compact the sector.
  3860  		advanceToEpochWithCron(rt, actor, rt.Epoch()+miner.WPoStDisputeWindow)
  3861  
  3862  		partId := uint64(0)
  3863  		deadlineId := uint64(0)
  3864  		rt.ExpectAbortContainsMessage(exitcode.ErrIllegalArgument, "failed to remove partitions from deadline 0: while removing partitions: cannot remove partition 0: has unproven sectors", func() {
  3865  			partitions := bitfield.NewFromSet([]uint64{partId})
  3866  			actor.compactPartitions(rt, deadlineId, partitions)
  3867  		})
  3868  		actor.checkState(rt)
  3869  	})
  3870  
  3871  	t.Run("fails if deadline is equal to WPoStPeriodDeadlines", func(t *testing.T) {
  3872  		rt := builder.Build(t)
  3873  		actor.constructAndVerify(rt)
  3874  
  3875  		rt.ExpectAbortContainsMessage(exitcode.ErrIllegalArgument, "invalid deadline 48", func() {
  3876  			actor.compactPartitions(rt, miner.WPoStPeriodDeadlines, bitfield.New())
  3877  		})
  3878  		actor.checkState(rt)
  3879  	})
  3880  
  3881  	t.Run("fails if deadline is open for challenging", func(t *testing.T) {
  3882  		rt := builder.Build(t)
  3883  		actor.constructAndVerify(rt)
  3884  
  3885  		rt.SetEpoch(periodOffset)
  3886  		rt.ExpectAbort(exitcode.ErrForbidden, func() {
  3887  			actor.compactPartitions(rt, 0, bitfield.New())
  3888  		})
  3889  		actor.checkState(rt)
  3890  	})
  3891  
  3892  	t.Run("fails if deadline is next up to be challenged", func(t *testing.T) {
  3893  		rt := builder.Build(t)
  3894  		actor.constructAndVerify(rt)
  3895  
  3896  		rt.SetEpoch(periodOffset)
  3897  		rt.ExpectAbort(exitcode.ErrForbidden, func() {
  3898  			actor.compactPartitions(rt, 1, bitfield.New())
  3899  		})
  3900  		actor.checkState(rt)
  3901  	})
  3902  
  3903  	t.Run("the deadline after the next deadline should still be open for compaction", func(t *testing.T) {
  3904  		rt := builder.Build(t)
  3905  		actor.constructAndVerify(rt)
  3906  
  3907  		rt.SetEpoch(periodOffset)
  3908  		actor.compactPartitions(rt, 3, bitfield.New())
  3909  		actor.checkState(rt)
  3910  	})
  3911  
  3912  	t.Run("deadlines challenged last proving period should still be in the dispute window", func(t *testing.T) {
  3913  		rt := builder.Build(t)
  3914  		actor.constructAndVerify(rt)
  3915  
  3916  		rt.SetEpoch(periodOffset)
  3917  		rt.ExpectAbort(exitcode.ErrForbidden, func() {
  3918  			actor.compactPartitions(rt, 47, bitfield.New())
  3919  		})
  3920  		actor.checkState(rt)
  3921  	})
  3922  
  3923  	disputeEnd := periodOffset + miner.WPoStChallengeWindow + miner.WPoStDisputeWindow - 1
  3924  	t.Run("compaction should be forbidden during the dispute window", func(t *testing.T) {
  3925  		rt := builder.Build(t)
  3926  		actor.constructAndVerify(rt)
  3927  
  3928  		rt.SetEpoch(disputeEnd)
  3929  		rt.ExpectAbort(exitcode.ErrForbidden, func() {
  3930  			actor.compactPartitions(rt, 0, bitfield.New())
  3931  		})
  3932  		actor.checkState(rt)
  3933  	})
  3934  
  3935  	t.Run("compaction should be allowed following the dispute window", func(t *testing.T) {
  3936  		rt := builder.Build(t)
  3937  		actor.constructAndVerify(rt)
  3938  
  3939  		rt.SetEpoch(disputeEnd + 1)
  3940  		actor.compactPartitions(rt, 0, bitfield.New())
  3941  		actor.checkState(rt)
  3942  	})
  3943  
  3944  	t.Run("fails if partition count is above limit", func(t *testing.T) {
  3945  		rt := builder.Build(t)
  3946  		actor.constructAndVerify(rt)
  3947  
  3948  		// partition limit is 4 for the default construction
  3949  		bf := bitfield.NewFromSet([]uint64{1, 2, 3, 4, 5})
  3950  
  3951  		rt.ExpectAbort(exitcode.ErrIllegalArgument, func() {
  3952  			actor.compactPartitions(rt, 1, bf)
  3953  		})
  3954  		actor.checkState(rt)
  3955  	})
  3956  }
  3957  
  3958  func TestCheckSectorProven(t *testing.T) {
  3959  	periodOffset := abi.ChainEpoch(100)
  3960  
  3961  	t.Run("successfully check sector is proven", func(t *testing.T) {
  3962  		actor := newHarness(t, periodOffset)
  3963  		rt := builderForHarness(actor).
  3964  			WithBalance(bigBalance, big.Zero()).
  3965  			Build(t)
  3966  		actor.constructAndVerify(rt)
  3967  
  3968  		sectors := actor.commitAndProveSectors(rt, 1, defaultSectorExpiration, [][]abi.DealID{{10}}, true)
  3969  
  3970  		actor.checkSectorProven(rt, sectors[0].SectorNumber)
  3971  		actor.checkState(rt)
  3972  	})
  3973  
  3974  	t.Run("fails is sector is not found", func(t *testing.T) {
  3975  		actor := newHarness(t, periodOffset)
  3976  		rt := builderForHarness(actor).
  3977  			WithBalance(bigBalance, big.Zero()).
  3978  			Build(t)
  3979  		actor.constructAndVerify(rt)
  3980  
  3981  		rt.ExpectAbort(exitcode.ErrNotFound, func() {
  3982  			actor.checkSectorProven(rt, abi.SectorNumber(1))
  3983  		})
  3984  		actor.checkState(rt)
  3985  	})
  3986  }
  3987  
  3988  func TestChangeMultiAddrs(t *testing.T) {
  3989  	periodOffset := abi.ChainEpoch(100)
  3990  
  3991  	t.Run("successfully change multiaddrs", func(t *testing.T) {
  3992  		actor := newHarness(t, periodOffset)
  3993  		builder := builderForHarness(actor).
  3994  			WithBalance(bigBalance, big.Zero())
  3995  		rt := builder.Build(t)
  3996  		actor.constructAndVerify(rt)
  3997  
  3998  		addr1 := abi.Multiaddrs([]byte("addr1"))
  3999  		addr2 := abi.Multiaddrs([]byte("addr2"))
  4000  
  4001  		actor.changeMultiAddrs(rt, []abi.Multiaddrs{addr1, addr2})
  4002  		actor.checkState(rt)
  4003  	})
  4004  
  4005  	t.Run("clear multiaddrs by passing in empty slice", func(t *testing.T) {
  4006  		actor := newHarness(t, periodOffset)
  4007  		builder := builderForHarness(actor).
  4008  			WithBalance(bigBalance, big.Zero())
  4009  		rt := builder.Build(t)
  4010  		actor.constructAndVerify(rt)
  4011  
  4012  		actor.changeMultiAddrs(rt, nil)
  4013  		actor.checkState(rt)
  4014  	})
  4015  }
  4016  
  4017  func TestChangeWorkerAddress(t *testing.T) {
  4018  	periodOffset := abi.ChainEpoch(100)
  4019  
  4020  	setupFunc := func() (*mock.Runtime, *actorHarness) {
  4021  		actor := newHarness(t, periodOffset)
  4022  		builder := builderForHarness(actor).
  4023  			WithBalance(bigBalance, big.Zero())
  4024  		rt := builder.Build(t)
  4025  
  4026  		return rt, actor
  4027  	}
  4028  
  4029  	t.Run("successfully change ONLY the worker address", func(t *testing.T) {
  4030  		rt, actor := setupFunc()
  4031  		actor.constructAndVerify(rt)
  4032  		originalControlAddrs := actor.controlAddrs
  4033  
  4034  		newWorker := tutil.NewIDAddr(t, 999)
  4035  
  4036  		// set epoch to something close to next deadline so first cron will be before effective date
  4037  		currentEpoch := abi.ChainEpoch(2970)
  4038  		rt.SetEpoch(currentEpoch)
  4039  
  4040  		effectiveEpoch := currentEpoch + miner.WorkerKeyChangeDelay
  4041  		actor.changeWorkerAddress(rt, newWorker, effectiveEpoch, originalControlAddrs)
  4042  
  4043  		// assert change has been made in state
  4044  		info := actor.getInfo(rt)
  4045  		assert.Equal(t, info.PendingWorkerKey.NewWorker, newWorker)
  4046  		assert.Equal(t, info.PendingWorkerKey.EffectiveAt, effectiveEpoch)
  4047  
  4048  		// no change if current epoch is less than effective epoch
  4049  		st := getState(rt)
  4050  		deadline := st.DeadlineInfo(rt.Epoch())
  4051  		rt.SetEpoch(deadline.PeriodEnd())
  4052  
  4053  		info = actor.getInfo(rt)
  4054  		require.NotNil(t, info.PendingWorkerKey)
  4055  		require.EqualValues(t, actor.worker, info.Worker)
  4056  
  4057  		// move to deadline containing effectiveEpoch
  4058  		rt.SetEpoch(effectiveEpoch)
  4059  
  4060  		// enact worker change
  4061  		actor.confirmUpdateWorkerKey(rt)
  4062  
  4063  		// assert address has changed
  4064  		info = actor.getInfo(rt)
  4065  		assert.Equal(t, newWorker, info.Worker)
  4066  
  4067  		// assert control addresses are unchanged
  4068  		require.NotEmpty(t, info.ControlAddresses)
  4069  		require.Equal(t, originalControlAddrs, info.ControlAddresses)
  4070  		actor.checkState(rt)
  4071  	})
  4072  
  4073  	t.Run("change cannot be overridden", func(t *testing.T) {
  4074  		rt, actor := setupFunc()
  4075  		actor.constructAndVerify(rt)
  4076  		originalControlAddrs := actor.controlAddrs
  4077  
  4078  		newWorker1 := tutil.NewIDAddr(t, 999)
  4079  		newWorker2 := tutil.NewIDAddr(t, 1023)
  4080  
  4081  		// set epoch to something close to next deadline so first cron will be before effective date
  4082  		currentEpoch := abi.ChainEpoch(2970)
  4083  		rt.SetEpoch(currentEpoch)
  4084  
  4085  		effectiveEpoch := currentEpoch + miner.WorkerKeyChangeDelay
  4086  		actor.changeWorkerAddress(rt, newWorker1, effectiveEpoch, originalControlAddrs)
  4087  
  4088  		// no change if current epoch is less than effective epoch
  4089  		st := getState(rt)
  4090  		deadline := st.DeadlineInfo(rt.Epoch())
  4091  		rt.SetEpoch(deadline.PeriodEnd())
  4092  
  4093  		// attempt to change address again
  4094  		actor.changeWorkerAddress(rt, newWorker2, rt.Epoch()+miner.WorkerKeyChangeDelay, originalControlAddrs)
  4095  
  4096  		// assert change has not been modified
  4097  		info := actor.getInfo(rt)
  4098  		assert.Equal(t, info.PendingWorkerKey.NewWorker, newWorker1)
  4099  		assert.Equal(t, info.PendingWorkerKey.EffectiveAt, effectiveEpoch)
  4100  
  4101  		rt.SetEpoch(effectiveEpoch)
  4102  		actor.confirmUpdateWorkerKey(rt)
  4103  
  4104  		// assert original change is effected
  4105  		info = actor.getInfo(rt)
  4106  		assert.Equal(t, newWorker1, info.Worker)
  4107  		actor.checkState(rt)
  4108  	})
  4109  
  4110  	t.Run("successfully resolve AND change ONLY control addresses", func(t *testing.T) {
  4111  		rt, actor := setupFunc()
  4112  		actor.constructAndVerify(rt)
  4113  
  4114  		c1Id := tutil.NewIDAddr(t, 555)
  4115  
  4116  		c2Id := tutil.NewIDAddr(t, 556)
  4117  		c2NonId := tutil.NewBLSAddr(t, 999)
  4118  		rt.AddIDAddress(c2NonId, c2Id)
  4119  
  4120  		rt.SetAddressActorType(c1Id, builtin.AccountActorCodeID)
  4121  		rt.SetAddressActorType(c2Id, builtin.AccountActorCodeID)
  4122  
  4123  		actor.changeWorkerAddress(rt, actor.worker, abi.ChainEpoch(-1), []addr.Address{c1Id, c2NonId})
  4124  
  4125  		// assert there is no worker change request and worker key is unchanged
  4126  		st := getState(rt)
  4127  		info, err := st.GetInfo(adt.AsStore(rt))
  4128  		require.NoError(t, err)
  4129  		require.Equal(t, actor.worker, info.Worker)
  4130  		require.Nil(t, info.PendingWorkerKey)
  4131  		actor.checkState(rt)
  4132  	})
  4133  
  4134  	t.Run("successfully change both worker AND control addresses", func(t *testing.T) {
  4135  		rt, actor := setupFunc()
  4136  		actor.constructAndVerify(rt)
  4137  
  4138  		newWorker := tutil.NewIDAddr(t, 999)
  4139  
  4140  		c1 := tutil.NewIDAddr(t, 5001)
  4141  		c2 := tutil.NewIDAddr(t, 5002)
  4142  		rt.SetAddressActorType(c1, builtin.AccountActorCodeID)
  4143  		rt.SetAddressActorType(c2, builtin.AccountActorCodeID)
  4144  
  4145  		currentEpoch := abi.ChainEpoch(5)
  4146  		rt.SetEpoch(currentEpoch)
  4147  		effectiveEpoch := currentEpoch + miner.WorkerKeyChangeDelay
  4148  		actor.changeWorkerAddress(rt, newWorker, effectiveEpoch, []addr.Address{c1, c2})
  4149  
  4150  		// set current epoch and update worker key
  4151  		rt.SetEpoch(effectiveEpoch)
  4152  		actor.confirmUpdateWorkerKey(rt)
  4153  
  4154  		// assert both worker and control addresses have changed
  4155  		st := getState(rt)
  4156  		info, err := st.GetInfo(adt.AsStore(rt))
  4157  		require.NoError(t, err)
  4158  		require.NotEmpty(t, info.ControlAddresses)
  4159  		require.Equal(t, []addr.Address{c1, c2}, info.ControlAddresses)
  4160  		require.Equal(t, newWorker, info.Worker)
  4161  		actor.checkState(rt)
  4162  	})
  4163  
  4164  	t.Run("successfully clear all control addresses", func(t *testing.T) {
  4165  		rt, actor := setupFunc()
  4166  		actor.constructAndVerify(rt)
  4167  
  4168  		actor.changeWorkerAddress(rt, actor.worker, abi.ChainEpoch(-1), nil)
  4169  
  4170  		// assert control addresses are cleared
  4171  		st := getState(rt)
  4172  		info, err := st.GetInfo(adt.AsStore(rt))
  4173  		require.NoError(t, err)
  4174  		require.Empty(t, info.ControlAddresses)
  4175  		actor.checkState(rt)
  4176  	})
  4177  
  4178  	t.Run("fails if control addresses length exceeds maximum limit", func(t *testing.T) {
  4179  		rt, actor := setupFunc()
  4180  		actor.constructAndVerify(rt)
  4181  
  4182  		controlAddrs := make([]addr.Address, 0, miner.MaxControlAddresses+1)
  4183  		for i := 0; i <= miner.MaxControlAddresses; i++ {
  4184  			controlAddrs = append(controlAddrs, tutil.NewIDAddr(t, uint64(i)))
  4185  		}
  4186  
  4187  		rt.ExpectAbortContainsMessage(exitcode.ErrIllegalArgument, "control addresses length", func() {
  4188  			actor.changeWorkerAddress(rt, actor.worker, abi.ChainEpoch(-1), controlAddrs)
  4189  		})
  4190  		actor.checkState(rt)
  4191  	})
  4192  
  4193  	t.Run("fails if unable to resolve control address", func(t *testing.T) {
  4194  		rt, actor := setupFunc()
  4195  		actor.constructAndVerify(rt)
  4196  		c1 := tutil.NewBLSAddr(t, 501)
  4197  
  4198  		rt.SetCaller(actor.owner, builtin.AccountActorCodeID)
  4199  		param := &miner.ChangeWorkerAddressParams{NewControlAddrs: []addr.Address{c1}}
  4200  		rt.ExpectAbort(exitcode.ErrIllegalArgument, func() {
  4201  			rt.Call(actor.a.ChangeWorkerAddress, param)
  4202  		})
  4203  		rt.Verify()
  4204  		actor.checkState(rt)
  4205  	})
  4206  
  4207  	t.Run("fails if unable to resolve worker address", func(t *testing.T) {
  4208  		rt, actor := setupFunc()
  4209  		actor.constructAndVerify(rt)
  4210  		newWorker := tutil.NewBLSAddr(t, 999)
  4211  		rt.SetAddressActorType(newWorker, builtin.AccountActorCodeID)
  4212  
  4213  		rt.SetCaller(actor.owner, builtin.AccountActorCodeID)
  4214  		param := &miner.ChangeWorkerAddressParams{NewWorker: newWorker}
  4215  		rt.ExpectAbort(exitcode.ErrIllegalArgument, func() {
  4216  			rt.Call(actor.a.ChangeWorkerAddress, param)
  4217  		})
  4218  		rt.Verify()
  4219  		actor.checkState(rt)
  4220  	})
  4221  
  4222  	t.Run("fails if worker public key is not BLS", func(t *testing.T) {
  4223  		rt, actor := setupFunc()
  4224  		actor.constructAndVerify(rt)
  4225  		newWorker := tutil.NewIDAddr(t, 999)
  4226  		rt.SetAddressActorType(newWorker, builtin.AccountActorCodeID)
  4227  		key := tutil.NewIDAddr(t, 505)
  4228  
  4229  		rt.ExpectSend(newWorker, builtin.MethodsAccount.PubkeyAddress, nil, big.Zero(), &key, exitcode.Ok)
  4230  
  4231  		rt.SetCaller(actor.owner, builtin.AccountActorCodeID)
  4232  		param := &miner.ChangeWorkerAddressParams{NewWorker: newWorker}
  4233  		rt.ExpectAbort(exitcode.ErrIllegalArgument, func() {
  4234  			rt.Call(actor.a.ChangeWorkerAddress, param)
  4235  		})
  4236  		rt.Verify()
  4237  		actor.checkState(rt)
  4238  	})
  4239  
  4240  	t.Run("fails if new worker address does not have a code", func(t *testing.T) {
  4241  		rt, actor := setupFunc()
  4242  		actor.constructAndVerify(rt)
  4243  		newWorker := tutil.NewIDAddr(t, 5001)
  4244  
  4245  		rt.SetCaller(actor.owner, builtin.AccountActorCodeID)
  4246  		param := &miner.ChangeWorkerAddressParams{NewWorker: newWorker}
  4247  		rt.ExpectAbort(exitcode.ErrIllegalArgument, func() {
  4248  			rt.Call(actor.a.ChangeWorkerAddress, param)
  4249  		})
  4250  		rt.Verify()
  4251  		actor.checkState(rt)
  4252  	})
  4253  
  4254  	t.Run("fails if new worker is not an account actor", func(t *testing.T) {
  4255  		rt, actor := setupFunc()
  4256  		actor.constructAndVerify(rt)
  4257  		newWorker := tutil.NewIDAddr(t, 999)
  4258  		rt.SetAddressActorType(newWorker, builtin.StorageMinerActorCodeID)
  4259  
  4260  		rt.SetCaller(actor.owner, builtin.AccountActorCodeID)
  4261  		param := &miner.ChangeWorkerAddressParams{NewWorker: newWorker}
  4262  		rt.ExpectAbort(exitcode.ErrIllegalArgument, func() {
  4263  			rt.Call(actor.a.ChangeWorkerAddress, param)
  4264  		})
  4265  		rt.Verify()
  4266  		actor.checkState(rt)
  4267  	})
  4268  
  4269  	t.Run("fails when caller is not the owner", func(t *testing.T) {
  4270  		rt, actor := setupFunc()
  4271  		actor.constructAndVerify(rt)
  4272  		newWorker := tutil.NewIDAddr(t, 999)
  4273  		rt.SetAddressActorType(newWorker, builtin.AccountActorCodeID)
  4274  
  4275  		rt.ExpectValidateCallerAddr(actor.owner)
  4276  		rt.ExpectSend(newWorker, builtin.MethodsAccount.PubkeyAddress, nil, big.Zero(), &actor.key, exitcode.Ok)
  4277  
  4278  		rt.SetCaller(actor.worker, builtin.AccountActorCodeID)
  4279  		param := &miner.ChangeWorkerAddressParams{NewWorker: newWorker}
  4280  		rt.ExpectAbort(exitcode.SysErrForbidden, func() {
  4281  			rt.Call(actor.a.ChangeWorkerAddress, param)
  4282  		})
  4283  		rt.Verify()
  4284  		actor.checkState(rt)
  4285  	})
  4286  }
  4287  
  4288  func TestConfirmUpdateWorkerKey(t *testing.T) {
  4289  	periodOffset := abi.ChainEpoch(100)
  4290  	newWorker := tutil.NewIDAddr(t, 999)
  4291  	currentEpoch := abi.ChainEpoch(5)
  4292  	actor := newHarness(t, periodOffset)
  4293  	builder := builderForHarness(actor).
  4294  		WithBalance(bigBalance, big.Zero())
  4295  
  4296  	t.Run("successfully changes the worker address", func(t *testing.T) {
  4297  		rt := builder.Build(t)
  4298  		rt.SetEpoch(currentEpoch)
  4299  		actor.constructAndVerify(rt)
  4300  
  4301  		effectiveEpoch := currentEpoch + miner.WorkerKeyChangeDelay
  4302  		actor.changeWorkerAddress(rt, newWorker, effectiveEpoch, actor.controlAddrs)
  4303  
  4304  		// confirm at effective epoch
  4305  		rt.SetEpoch(effectiveEpoch)
  4306  		actor.confirmUpdateWorkerKey(rt)
  4307  
  4308  		st := getState(rt)
  4309  		info, err := st.GetInfo(adt.AsStore(rt))
  4310  		require.NoError(t, err)
  4311  		require.Equal(t, info.Worker, newWorker)
  4312  		require.Nil(t, info.PendingWorkerKey)
  4313  		actor.checkState(rt)
  4314  	})
  4315  
  4316  	t.Run("does nothing before the effective date", func(t *testing.T) {
  4317  		rt := builder.Build(t)
  4318  		rt.SetEpoch(currentEpoch)
  4319  		actor.constructAndVerify(rt)
  4320  
  4321  		effectiveEpoch := currentEpoch + miner.WorkerKeyChangeDelay
  4322  		actor.changeWorkerAddress(rt, newWorker, effectiveEpoch, actor.controlAddrs)
  4323  
  4324  		// confirm right before the effective epoch
  4325  		rt.SetEpoch(effectiveEpoch - 1)
  4326  		actor.confirmUpdateWorkerKey(rt)
  4327  
  4328  		st := getState(rt)
  4329  		info, err := st.GetInfo(adt.AsStore(rt))
  4330  		require.NoError(t, err)
  4331  		require.Equal(t, actor.worker, info.Worker)
  4332  		require.NotNil(t, info.PendingWorkerKey)
  4333  		actor.checkState(rt)
  4334  	})
  4335  
  4336  	t.Run("does nothing when no update is set", func(t *testing.T) {
  4337  		rt := builder.Build(t)
  4338  		rt.SetEpoch(currentEpoch)
  4339  		actor.constructAndVerify(rt)
  4340  
  4341  		actor.confirmUpdateWorkerKey(rt)
  4342  
  4343  		st := getState(rt)
  4344  		info, err := st.GetInfo(adt.AsStore(rt))
  4345  		require.NoError(t, err)
  4346  		require.Equal(t, actor.worker, info.Worker)
  4347  		require.Nil(t, info.PendingWorkerKey)
  4348  		actor.checkState(rt)
  4349  	})
  4350  }
  4351  
  4352  func TestChangeOwnerAddress(t *testing.T) {
  4353  	actor := newHarness(t, 0)
  4354  	builder := builderForHarness(actor).
  4355  		WithBalance(bigBalance, big.Zero())
  4356  	newAddr := tutil.NewIDAddr(t, 1001)
  4357  	otherAddr := tutil.NewIDAddr(t, 1002)
  4358  
  4359  	t.Run("successful change", func(t *testing.T) {
  4360  		rt := builder.Build(t)
  4361  		actor.constructAndVerify(rt)
  4362  
  4363  		rt.SetCaller(actor.owner, builtin.MultisigActorCodeID)
  4364  		actor.changeOwnerAddress(rt, newAddr)
  4365  
  4366  		info := actor.getInfo(rt)
  4367  		assert.Equal(t, actor.owner, info.Owner)
  4368  		assert.Equal(t, newAddr, *info.PendingOwnerAddress)
  4369  
  4370  		rt.SetCaller(newAddr, builtin.MultisigActorCodeID)
  4371  		actor.changeOwnerAddress(rt, newAddr)
  4372  
  4373  		info = actor.getInfo(rt)
  4374  		assert.Equal(t, newAddr, info.Owner)
  4375  		assert.Nil(t, info.PendingOwnerAddress)
  4376  	})
  4377  
  4378  	t.Run("proposed must be valid", func(t *testing.T) {
  4379  		rt := builder.Build(t)
  4380  		actor.constructAndVerify(rt)
  4381  
  4382  		nominees := []addr.Address{
  4383  			addr.Undef,
  4384  			tutil.NewSECP256K1Addr(t, "asd"),
  4385  			tutil.NewBLSAddr(t, 1234),
  4386  			tutil.NewActorAddr(t, "asd"),
  4387  		}
  4388  		rt.SetCaller(actor.owner, builtin.MultisigActorCodeID)
  4389  		for _, a := range nominees {
  4390  			rt.ExpectAbort(exitcode.ErrIllegalArgument, func() {
  4391  				actor.changeOwnerAddress(rt, a)
  4392  			})
  4393  		}
  4394  	})
  4395  
  4396  	t.Run("withdraw proposal", func(t *testing.T) {
  4397  		rt := builder.Build(t)
  4398  		actor.constructAndVerify(rt)
  4399  
  4400  		rt.SetCaller(actor.owner, builtin.MultisigActorCodeID)
  4401  		actor.changeOwnerAddress(rt, newAddr)
  4402  
  4403  		// Revert it
  4404  		actor.changeOwnerAddress(rt, actor.owner)
  4405  
  4406  		info := actor.getInfo(rt)
  4407  		assert.Equal(t, actor.owner, info.Owner)
  4408  		assert.Nil(t, info.PendingOwnerAddress)
  4409  
  4410  		// New address cannot confirm.
  4411  		rt.SetCaller(newAddr, builtin.MultisigActorCodeID)
  4412  		rt.ExpectAbort(exitcode.SysErrForbidden, func() {
  4413  			actor.changeOwnerAddress(rt, newAddr)
  4414  		})
  4415  	})
  4416  
  4417  	t.Run("only owner can propose", func(t *testing.T) {
  4418  		rt := builder.Build(t)
  4419  		actor.constructAndVerify(rt)
  4420  
  4421  		rt.SetCaller(actor.worker, builtin.AccountActorCodeID)
  4422  		rt.ExpectAbort(exitcode.SysErrForbidden, func() {
  4423  			actor.changeOwnerAddress(rt, newAddr)
  4424  		})
  4425  		rt.SetCaller(otherAddr, builtin.MultisigActorCodeID)
  4426  		rt.ExpectAbort(exitcode.SysErrForbidden, func() {
  4427  			actor.changeOwnerAddress(rt, newAddr)
  4428  		})
  4429  	})
  4430  
  4431  	t.Run("only owner can change proposal", func(t *testing.T) {
  4432  		rt := builder.Build(t)
  4433  		actor.constructAndVerify(rt)
  4434  
  4435  		// Make a proposal
  4436  		rt.SetCaller(actor.owner, builtin.MultisigActorCodeID)
  4437  		actor.changeOwnerAddress(rt, newAddr)
  4438  
  4439  		rt.SetCaller(actor.worker, builtin.AccountActorCodeID)
  4440  		rt.ExpectAbort(exitcode.SysErrForbidden, func() {
  4441  			actor.changeOwnerAddress(rt, otherAddr)
  4442  		})
  4443  		rt.SetCaller(otherAddr, builtin.MultisigActorCodeID)
  4444  		rt.ExpectAbort(exitcode.SysErrForbidden, func() {
  4445  			actor.changeOwnerAddress(rt, otherAddr)
  4446  		})
  4447  
  4448  		// Owner can change it
  4449  		rt.SetCaller(actor.owner, builtin.MultisigActorCodeID)
  4450  		actor.changeOwnerAddress(rt, otherAddr)
  4451  		info := actor.getInfo(rt)
  4452  		assert.Equal(t, actor.owner, info.Owner)
  4453  		assert.Equal(t, otherAddr, *info.PendingOwnerAddress)
  4454  
  4455  	})
  4456  
  4457  	t.Run("only nominee can confirm", func(t *testing.T) {
  4458  		rt := builder.Build(t)
  4459  		actor.constructAndVerify(rt)
  4460  
  4461  		// Make a proposal
  4462  		rt.SetCaller(actor.owner, builtin.MultisigActorCodeID)
  4463  		actor.changeOwnerAddress(rt, newAddr)
  4464  
  4465  		// Owner re-proposing same address doesn't confirm it.
  4466  		actor.changeOwnerAddress(rt, newAddr)
  4467  		info := actor.getInfo(rt)
  4468  		assert.Equal(t, actor.owner, info.Owner)
  4469  		assert.Equal(t, newAddr, *info.PendingOwnerAddress) // Still staged
  4470  
  4471  		rt.SetCaller(actor.worker, builtin.AccountActorCodeID)
  4472  		rt.ExpectAbort(exitcode.SysErrForbidden, func() {
  4473  			actor.changeOwnerAddress(rt, otherAddr)
  4474  		})
  4475  		rt.SetCaller(otherAddr, builtin.MultisigActorCodeID)
  4476  		rt.ExpectAbort(exitcode.SysErrForbidden, func() {
  4477  			actor.changeOwnerAddress(rt, otherAddr)
  4478  		})
  4479  
  4480  		// New addr can confirm itself
  4481  		rt.SetCaller(newAddr, builtin.MultisigActorCodeID)
  4482  		actor.changeOwnerAddress(rt, newAddr)
  4483  		info = actor.getInfo(rt)
  4484  		assert.Equal(t, newAddr, info.Owner)
  4485  		assert.Nil(t, info.PendingOwnerAddress)
  4486  	})
  4487  
  4488  	t.Run("nominee must confirm self explicitly", func(t *testing.T) {
  4489  		rt := builder.Build(t)
  4490  		actor.constructAndVerify(rt)
  4491  
  4492  		// Make a proposal
  4493  		rt.SetCaller(actor.owner, builtin.MultisigActorCodeID)
  4494  		actor.changeOwnerAddress(rt, newAddr)
  4495  
  4496  		rt.SetCaller(newAddr, builtin.MultisigActorCodeID)
  4497  		rt.ExpectAbort(exitcode.ErrIllegalArgument, func() {
  4498  			actor.changeOwnerAddress(rt, actor.owner) // Not own address
  4499  		})
  4500  		rt.ExpectAbort(exitcode.ErrIllegalArgument, func() {
  4501  			actor.changeOwnerAddress(rt, otherAddr) // Not own address
  4502  		})
  4503  	})
  4504  }
  4505  
  4506  func TestReportConsensusFault(t *testing.T) {
  4507  	periodOffset := abi.ChainEpoch(100)
  4508  	actor := newHarness(t, periodOffset)
  4509  	builder := builderForHarness(actor).
  4510  		WithBalance(bigBalance, big.Zero())
  4511  
  4512  	t.Run("invalid report rejected", func(t *testing.T) {
  4513  		rt := builder.Build(t)
  4514  		actor.constructAndVerify(rt)
  4515  		rt.SetEpoch(abi.ChainEpoch(1))
  4516  
  4517  		rt.ExpectAbort(exitcode.ErrIllegalArgument, func() {
  4518  			actor.reportConsensusFault(rt, addr.TestAddress, nil)
  4519  		})
  4520  		actor.checkState(rt)
  4521  	})
  4522  
  4523  	t.Run("mis-targeted report rejected", func(t *testing.T) {
  4524  		rt := builder.Build(t)
  4525  		actor.constructAndVerify(rt)
  4526  		rt.SetEpoch(abi.ChainEpoch(1))
  4527  
  4528  		rt.ExpectAbort(exitcode.ErrIllegalArgument, func() {
  4529  			actor.reportConsensusFault(rt, addr.TestAddress, &runtime.ConsensusFault{
  4530  				Target: tutil.NewIDAddr(t, 1234), // Not receiver
  4531  				Epoch:  rt.Epoch() - 1,
  4532  				Type:   runtime.ConsensusFaultDoubleForkMining,
  4533  			})
  4534  		})
  4535  		actor.checkState(rt)
  4536  	})
  4537  
  4538  	t.Run("Report consensus fault pays reward and charges fee", func(t *testing.T) {
  4539  		rt := builder.Build(t)
  4540  		actor.constructAndVerify(rt)
  4541  		precommitEpoch := abi.ChainEpoch(1)
  4542  		rt.SetEpoch(precommitEpoch)
  4543  
  4544  		actor.reportConsensusFault(rt, addr.TestAddress, &runtime.ConsensusFault{
  4545  			Target: actor.receiver,
  4546  			Epoch:  rt.Epoch() - 1,
  4547  			Type:   runtime.ConsensusFaultDoubleForkMining,
  4548  		})
  4549  		actor.checkState(rt)
  4550  	})
  4551  
  4552  	t.Run("Report consensus fault updates consensus fault reported field", func(t *testing.T) {
  4553  		rt := builder.Build(t)
  4554  		actor.constructAndVerify(rt)
  4555  		precommitEpoch := abi.ChainEpoch(1)
  4556  		rt.SetEpoch(precommitEpoch)
  4557  
  4558  		startInfo := actor.getInfo(rt)
  4559  		assert.Equal(t, abi.ChainEpoch(-1), startInfo.ConsensusFaultElapsed)
  4560  
  4561  		reportEpoch := abi.ChainEpoch(333)
  4562  		rt.SetEpoch(reportEpoch)
  4563  
  4564  		actor.reportConsensusFault(rt, addr.TestAddress, &runtime.ConsensusFault{
  4565  			Target: actor.receiver,
  4566  			Epoch:  rt.Epoch() - 1,
  4567  			Type:   runtime.ConsensusFaultDoubleForkMining,
  4568  		})
  4569  		endInfo := actor.getInfo(rt)
  4570  		assert.Equal(t, reportEpoch+miner.ConsensusFaultIneligibilityDuration, endInfo.ConsensusFaultElapsed)
  4571  		actor.checkState(rt)
  4572  	})
  4573  
  4574  	t.Run("Double report of consensus fault fails", func(t *testing.T) {
  4575  		rt := builder.Build(t)
  4576  		actor.constructAndVerify(rt)
  4577  		precommitEpoch := abi.ChainEpoch(1)
  4578  		rt.SetEpoch(precommitEpoch)
  4579  
  4580  		startInfo := actor.getInfo(rt)
  4581  		assert.Equal(t, abi.ChainEpoch(-1), startInfo.ConsensusFaultElapsed)
  4582  
  4583  		reportEpoch := abi.ChainEpoch(333)
  4584  		rt.SetEpoch(reportEpoch)
  4585  
  4586  		fault1 := rt.Epoch() - 1
  4587  		actor.reportConsensusFault(rt, addr.TestAddress, &runtime.ConsensusFault{
  4588  			Target: actor.receiver,
  4589  			Epoch:  fault1,
  4590  			Type:   runtime.ConsensusFaultDoubleForkMining,
  4591  		})
  4592  		endInfo := actor.getInfo(rt)
  4593  		assert.Equal(t, reportEpoch+miner.ConsensusFaultIneligibilityDuration, endInfo.ConsensusFaultElapsed)
  4594  
  4595  		// same fault can't be reported twice
  4596  		rt.ExpectAbortContainsMessage(exitcode.ErrForbidden, "too old", func() {
  4597  			actor.reportConsensusFault(rt, addr.TestAddress, &runtime.ConsensusFault{
  4598  				Target: actor.receiver,
  4599  				Epoch:  fault1,
  4600  				Type:   runtime.ConsensusFaultDoubleForkMining,
  4601  			})
  4602  		})
  4603  		rt.Reset()
  4604  
  4605  		// new consensus faults are forbidden until original has elapsed
  4606  		rt.SetEpoch(endInfo.ConsensusFaultElapsed)
  4607  		fault2 := endInfo.ConsensusFaultElapsed - 1
  4608  		rt.ExpectAbortContainsMessage(exitcode.ErrForbidden, "too old", func() {
  4609  			actor.reportConsensusFault(rt, addr.TestAddress, &runtime.ConsensusFault{
  4610  				Target: actor.receiver,
  4611  				Epoch:  fault2,
  4612  				Type:   runtime.ConsensusFaultDoubleForkMining,
  4613  			})
  4614  		})
  4615  		rt.Reset()
  4616  
  4617  		// a new consensus fault can be reported for blocks once original has expired
  4618  		rt.SetEpoch(endInfo.ConsensusFaultElapsed + 1)
  4619  		fault3 := endInfo.ConsensusFaultElapsed
  4620  		actor.reportConsensusFault(rt, addr.TestAddress, &runtime.ConsensusFault{
  4621  			Target: actor.receiver,
  4622  			Epoch:  fault3,
  4623  			Type:   runtime.ConsensusFaultDoubleForkMining,
  4624  		})
  4625  		endInfo = actor.getInfo(rt)
  4626  		assert.Equal(t, rt.Epoch()+miner.ConsensusFaultIneligibilityDuration, endInfo.ConsensusFaultElapsed)
  4627  
  4628  		// old fault still cannot be reported after fault interval has elapsed
  4629  		fault4 := fault1 + 1
  4630  		rt.ExpectAbortContainsMessage(exitcode.ErrForbidden, "too old", func() {
  4631  			actor.reportConsensusFault(rt, addr.TestAddress, &runtime.ConsensusFault{
  4632  				Target: actor.receiver,
  4633  				Epoch:  fault4,
  4634  				Type:   runtime.ConsensusFaultDoubleForkMining,
  4635  			})
  4636  		})
  4637  		actor.checkState(rt)
  4638  	})
  4639  }
  4640  
  4641  func TestApplyRewards(t *testing.T) {
  4642  	periodOffset := abi.ChainEpoch(1808)
  4643  	actor := newHarness(t, periodOffset)
  4644  
  4645  	builder := builderForHarness(actor).
  4646  		WithBalance(bigBalance, big.Zero())
  4647  
  4648  	t.Run("funds are locked", func(t *testing.T) {
  4649  		rt := builder.Build(t)
  4650  		actor.constructAndVerify(rt)
  4651  
  4652  		rwd := abi.NewTokenAmount(1_000_000)
  4653  		actor.applyRewards(rt, rwd, big.Zero())
  4654  
  4655  		expected := abi.NewTokenAmount(750_000)
  4656  		assert.Equal(t, expected, actor.getLockedFunds(rt))
  4657  	})
  4658  
  4659  	t.Run("funds vest", func(t *testing.T) {
  4660  		rt := builder.Build(t)
  4661  		actor.constructAndVerify(rt)
  4662  		st := getState(rt)
  4663  
  4664  		vestingFunds, err := st.LoadVestingFunds(adt.AsStore(rt))
  4665  		require.NoError(t, err)
  4666  
  4667  		// Nothing vesting to start
  4668  		assert.Empty(t, vestingFunds.Funds)
  4669  		assert.Equal(t, big.Zero(), st.LockedFunds)
  4670  
  4671  		// Lock some funds with AddLockedFund
  4672  		amt := abi.NewTokenAmount(600_000)
  4673  		actor.applyRewards(rt, amt, big.Zero())
  4674  		st = getState(rt)
  4675  		vestingFunds, err = st.LoadVestingFunds(adt.AsStore(rt))
  4676  		require.NoError(t, err)
  4677  
  4678  		require.Len(t, vestingFunds.Funds, 180)
  4679  
  4680  		// Vested FIL pays out on epochs with expected offset
  4681  		quantSpec := miner.NewQuantSpec(miner.RewardVestingSpec.Quantization, periodOffset)
  4682  
  4683  		currEpoch := rt.Epoch()
  4684  		for i := range vestingFunds.Funds {
  4685  			step := miner.RewardVestingSpec.InitialDelay + abi.ChainEpoch(i+1)*miner.RewardVestingSpec.StepDuration
  4686  			expectedEpoch := quantSpec.QuantizeUp(currEpoch + step)
  4687  			vf := vestingFunds.Funds[i]
  4688  			assert.Equal(t, expectedEpoch, vf.Epoch)
  4689  		}
  4690  
  4691  		expectedOffset := periodOffset % miner.RewardVestingSpec.Quantization
  4692  		for i := range vestingFunds.Funds {
  4693  			vf := vestingFunds.Funds[i]
  4694  			require.EqualValues(t, expectedOffset, int64(vf.Epoch)%int64(miner.RewardVestingSpec.Quantization))
  4695  		}
  4696  
  4697  		st = getState(rt)
  4698  		lockedAmt, _ := miner.LockedRewardFromReward(amt)
  4699  		assert.Equal(t, lockedAmt, st.LockedFunds)
  4700  		// technically applying rewards without first activating cron is an impossible state but convenient for testing
  4701  		_, msgs := miner.CheckStateInvariants(st, rt.AdtStore(), rt.Balance())
  4702  		assert.Equal(t, 1, len(msgs.Messages()))
  4703  		assert.Contains(t, msgs.Messages()[0], "DeadlineCronActive == false")
  4704  	})
  4705  
  4706  	t.Run("penalty is burnt", func(t *testing.T) {
  4707  		rt := builder.Build(t)
  4708  		actor.constructAndVerify(rt)
  4709  
  4710  		rwd := abi.NewTokenAmount(600_000)
  4711  		penalty := abi.NewTokenAmount(300_000)
  4712  		rt.SetBalance(big.Add(rt.Balance(), rwd))
  4713  		actor.applyRewards(rt, rwd, penalty)
  4714  
  4715  		expectedLockAmt, _ := miner.LockedRewardFromReward(rwd)
  4716  		expectedLockAmt = big.Sub(expectedLockAmt, penalty)
  4717  		assert.Equal(t, expectedLockAmt, actor.getLockedFunds(rt))
  4718  
  4719  		// technically applying rewards without first activating cron is an impossible state but convenient for testing
  4720  		st := getState(rt)
  4721  		_, msgs := miner.CheckStateInvariants(st, rt.AdtStore(), rt.Balance())
  4722  		assert.Equal(t, 1, len(msgs.Messages()))
  4723  		assert.Contains(t, msgs.Messages()[0], "DeadlineCronActive == false")
  4724  	})
  4725  
  4726  	t.Run("penalty is partially burnt and stored as fee debt", func(t *testing.T) {
  4727  		rt := builder.Build(t)
  4728  		actor.constructAndVerify(rt)
  4729  		st := getState(rt)
  4730  		assert.Equal(t, big.Zero(), st.FeeDebt)
  4731  
  4732  		amt := rt.Balance()
  4733  		penalty := big.Mul(big.NewInt(3), amt)
  4734  		reward := amt
  4735  
  4736  		// manually update actor balance to include the added funds on reward message
  4737  		newBalance := big.Add(reward, amt)
  4738  		rt.SetBalance(newBalance)
  4739  
  4740  		rt.SetCaller(builtin.RewardActorAddr, builtin.RewardActorCodeID)
  4741  		rt.ExpectValidateCallerAddr(builtin.RewardActorAddr)
  4742  
  4743  		// pledge change is new reward - reward taken for fee debt
  4744  		// zero here since all reward goes to debt
  4745  		// so do not expect pledge update
  4746  
  4747  		// burn initial balance + reward = 2*amt
  4748  		expectBurnt := big.Mul(big.NewInt(2), amt)
  4749  		rt.ExpectSend(builtin.BurntFundsActorAddr, builtin.MethodSend, nil, expectBurnt, nil, exitcode.Ok)
  4750  
  4751  		rt.Call(actor.a.ApplyRewards, &builtin.ApplyRewardParams{Reward: reward, Penalty: penalty})
  4752  		rt.Verify()
  4753  
  4754  		st = getState(rt)
  4755  		// fee debt =  penalty - reward - initial balance = 3*amt - 2*amt = amt
  4756  		assert.Equal(t, amt, st.FeeDebt)
  4757  		// technically applying rewards without first activating cron is an impossible state but convenient for testing
  4758  		actor.checkState(rt)
  4759  	})
  4760  
  4761  	// The system should not reach this state since fee debt removes mining eligibility
  4762  	// But if invariants are violated this should work.
  4763  	t.Run("rewards pay back fee debt ", func(t *testing.T) {
  4764  		rt := builder.Build(t)
  4765  		actor.constructAndVerify(rt)
  4766  		st := getState(rt)
  4767  
  4768  		assert.Equal(t, big.Zero(), st.LockedFunds)
  4769  
  4770  		amt := rt.Balance()
  4771  		availableBefore, err := st.GetAvailableBalance(amt)
  4772  		require.NoError(t, err)
  4773  		assert.True(t, availableBefore.GreaterThan(big.Zero()))
  4774  		initFeeDebt := big.Mul(big.NewInt(2), amt) // FeeDebt twice total balance
  4775  		st.FeeDebt = initFeeDebt
  4776  		availableAfter, err := st.GetAvailableBalance(amt)
  4777  		require.NoError(t, err)
  4778  		assert.True(t, availableAfter.LessThan(big.Zero()))
  4779  
  4780  		rt.ReplaceState(st)
  4781  
  4782  		reward := big.Mul(big.NewInt(3), amt)
  4783  		penalty := big.Zero()
  4784  		// manually update actor balance to include the added funds from outside
  4785  		newBalance := big.Add(amt, reward)
  4786  		rt.SetBalance(newBalance)
  4787  
  4788  		// pledge change is new reward - reward taken for fee debt
  4789  		// 3*LockedRewardFactor*amt - 2*amt = remainingLocked
  4790  		lockedReward, _ := miner.LockedRewardFromReward(reward)
  4791  		remainingLocked := big.Sub(lockedReward, st.FeeDebt) // note that this would be clamped at 0 if difference above is < 0
  4792  		pledgeDelta := remainingLocked
  4793  		rt.SetCaller(builtin.RewardActorAddr, builtin.RewardActorCodeID)
  4794  		rt.ExpectValidateCallerAddr(builtin.RewardActorAddr)
  4795  		// expect pledge update
  4796  		rt.ExpectSend(
  4797  			builtin.StoragePowerActorAddr,
  4798  			builtin.MethodsPower.UpdatePledgeTotal,
  4799  			&pledgeDelta,
  4800  			abi.NewTokenAmount(0),
  4801  			nil,
  4802  			exitcode.Ok,
  4803  		)
  4804  
  4805  		expectBurnt := st.FeeDebt
  4806  		rt.ExpectSend(builtin.BurntFundsActorAddr, builtin.MethodSend, nil, expectBurnt, nil, exitcode.Ok)
  4807  
  4808  		rt.Call(actor.a.ApplyRewards, &builtin.ApplyRewardParams{Reward: reward, Penalty: penalty})
  4809  		rt.Verify()
  4810  
  4811  		// Set balance to deduct fee
  4812  		finalBalance := big.Sub(newBalance, expectBurnt)
  4813  
  4814  		st = getState(rt)
  4815  		// balance funds used to pay off fee debt
  4816  		// available balance should be 2
  4817  		availableBalance, err := st.GetAvailableBalance(finalBalance)
  4818  		require.NoError(t, err)
  4819  		assert.Equal(t, big.Sum(availableBefore, reward, initFeeDebt.Neg(), remainingLocked.Neg()), availableBalance)
  4820  		assert.True(t, st.IsDebtFree())
  4821  		// remaining funds locked in vesting table
  4822  		assert.Equal(t, remainingLocked, st.LockedFunds)
  4823  		// technically applying rewards without first activating cron is an impossible state but convenient for testing
  4824  		_, msgs := miner.CheckStateInvariants(st, rt.AdtStore(), rt.Balance())
  4825  		assert.Equal(t, 1, len(msgs.Messages()))
  4826  		assert.Contains(t, msgs.Messages()[0], "DeadlineCronActive == false")
  4827  	})
  4828  }
  4829  
  4830  func TestCompactSectorNumbers(t *testing.T) {
  4831  	periodOffset := abi.ChainEpoch(100)
  4832  	actor := newHarness(t, periodOffset)
  4833  	builder := builderForHarness(actor).
  4834  		WithBalance(bigBalance, big.Zero())
  4835  
  4836  	t.Run("compact sector numbers then pre-commit", func(t *testing.T) {
  4837  		// Create a sector.
  4838  		rt := builder.Build(t)
  4839  		actor.constructAndVerify(rt)
  4840  		allSectors := actor.commitAndProveSectors(rt, 1, defaultSectorExpiration, nil, true)
  4841  
  4842  		targetSno := allSectors[0].SectorNumber
  4843  		actor.compactSectorNumbers(rt, bf(uint64(targetSno), uint64(targetSno)+1))
  4844  
  4845  		precommitEpoch := rt.Epoch()
  4846  		deadline := actor.deadline(rt)
  4847  		expiration := deadline.PeriodEnd() + abi.ChainEpoch(defaultSectorExpiration)*miner.WPoStProvingPeriod
  4848  
  4849  		// Allocating masked sector number should fail.
  4850  		{
  4851  			precommit := actor.makePreCommit(targetSno+1, precommitEpoch-1, expiration, nil)
  4852  			rt.ExpectAbort(exitcode.ErrIllegalArgument, func() {
  4853  				actor.preCommitSector(rt, precommit, preCommitConf{}, false)
  4854  			})
  4855  		}
  4856  
  4857  		{
  4858  			precommit := actor.makePreCommit(targetSno+2, precommitEpoch-1, expiration, nil)
  4859  			actor.preCommitSector(rt, precommit, preCommitConf{}, false)
  4860  		}
  4861  		actor.checkState(rt)
  4862  	})
  4863  
  4864  	t.Run("owner can also compact sectors", func(t *testing.T) {
  4865  		// Create a sector.
  4866  		rt := builder.Build(t)
  4867  		actor.constructAndVerify(rt)
  4868  		allSectors := actor.commitAndProveSectors(rt, 1, defaultSectorExpiration, nil, true)
  4869  
  4870  		targetSno := allSectors[0].SectorNumber
  4871  		rt.SetCaller(actor.owner, builtin.AccountActorCodeID)
  4872  		rt.ExpectValidateCallerAddr(append(actor.controlAddrs, actor.owner, actor.worker)...)
  4873  
  4874  		rt.Call(actor.a.CompactSectorNumbers, &miner.CompactSectorNumbersParams{
  4875  			MaskSectorNumbers: bf(uint64(targetSno), uint64(targetSno)+1),
  4876  		})
  4877  		rt.Verify()
  4878  		actor.checkState(rt)
  4879  	})
  4880  
  4881  	t.Run("one of the control addresses can also compact sectors", func(t *testing.T) {
  4882  		// Create a sector.
  4883  		rt := builder.Build(t)
  4884  		actor.constructAndVerify(rt)
  4885  		allSectors := actor.commitAndProveSectors(rt, 1, defaultSectorExpiration, nil, true)
  4886  
  4887  		targetSno := allSectors[0].SectorNumber
  4888  		rt.SetCaller(actor.controlAddrs[0], builtin.AccountActorCodeID)
  4889  		rt.ExpectValidateCallerAddr(append(actor.controlAddrs, actor.owner, actor.worker)...)
  4890  
  4891  		rt.Call(actor.a.CompactSectorNumbers, &miner.CompactSectorNumbersParams{
  4892  			MaskSectorNumbers: bf(uint64(targetSno), uint64(targetSno)+1),
  4893  		})
  4894  		rt.Verify()
  4895  		actor.checkState(rt)
  4896  	})
  4897  
  4898  	t.Run("fail if caller is not among caller worker or control addresses", func(t *testing.T) {
  4899  		// Create a sector.
  4900  		rt := builder.Build(t)
  4901  		actor.constructAndVerify(rt)
  4902  		allSectors := actor.commitAndProveSectors(rt, 1, defaultSectorExpiration, nil, true)
  4903  
  4904  		targetSno := allSectors[0].SectorNumber
  4905  		rAddr := tutil.NewIDAddr(t, 1005)
  4906  		rt.SetCaller(rAddr, builtin.AccountActorCodeID)
  4907  		rt.ExpectValidateCallerAddr(append(actor.controlAddrs, actor.owner, actor.worker)...)
  4908  
  4909  		rt.ExpectAbort(exitcode.SysErrForbidden, func() {
  4910  			rt.Call(actor.a.CompactSectorNumbers, &miner.CompactSectorNumbersParams{
  4911  				MaskSectorNumbers: bf(uint64(targetSno), uint64(targetSno)+1),
  4912  			})
  4913  		})
  4914  
  4915  		rt.Verify()
  4916  		actor.checkState(rt)
  4917  	})
  4918  
  4919  	t.Run("compacting no sector numbers aborts", func(t *testing.T) {
  4920  		rt := builder.Build(t)
  4921  		actor.constructAndVerify(rt)
  4922  
  4923  		rt.ExpectAbort(exitcode.ErrIllegalArgument, func() {
  4924  			// compact nothing
  4925  			actor.compactSectorNumbers(rt, bf())
  4926  		})
  4927  		actor.checkState(rt)
  4928  	})
  4929  }
  4930  
  4931  type actorHarness struct {
  4932  	a miner.Actor
  4933  	t testing.TB
  4934  
  4935  	receiver addr.Address // The miner actor's own address
  4936  	owner    addr.Address
  4937  	worker   addr.Address
  4938  	key      addr.Address
  4939  
  4940  	controlAddrs []addr.Address
  4941  
  4942  	sealProofType       abi.RegisteredSealProof
  4943  	windowPostProofType abi.RegisteredPoStProof
  4944  	sectorSize          abi.SectorSize
  4945  	partitionSize       uint64
  4946  	periodOffset        abi.ChainEpoch
  4947  	nextSectorNo        abi.SectorNumber
  4948  
  4949  	networkPledge   abi.TokenAmount
  4950  	networkRawPower abi.StoragePower
  4951  	networkQAPower  abi.StoragePower
  4952  	baselinePower   abi.StoragePower
  4953  
  4954  	epochRewardSmooth  smoothing.FilterEstimate
  4955  	epochQAPowerSmooth smoothing.FilterEstimate
  4956  }
  4957  
  4958  func newHarness(t testing.TB, provingPeriodOffset abi.ChainEpoch) *actorHarness {
  4959  	owner := tutil.NewIDAddr(t, 100)
  4960  	worker := tutil.NewIDAddr(t, 101)
  4961  
  4962  	controlAddrs := []addr.Address{tutil.NewIDAddr(t, 999), tutil.NewIDAddr(t, 998), tutil.NewIDAddr(t, 997)}
  4963  
  4964  	workerKey := tutil.NewBLSAddr(t, 0)
  4965  	receiver := tutil.NewIDAddr(t, 1000)
  4966  	rwd := big.Mul(big.NewIntUnsigned(10), big.NewIntUnsigned(1e18))
  4967  	pwr := abi.NewStoragePower(1 << 50)
  4968  	h := &actorHarness{
  4969  		t:        t,
  4970  		receiver: receiver,
  4971  		owner:    owner,
  4972  		worker:   worker,
  4973  		key:      workerKey,
  4974  
  4975  		controlAddrs: controlAddrs,
  4976  
  4977  		// Proof types and metadata initialized in setProofType
  4978  		periodOffset: provingPeriodOffset,
  4979  		nextSectorNo: 100,
  4980  
  4981  		networkPledge:   big.Mul(rwd, big.NewIntUnsigned(1000)),
  4982  		networkRawPower: pwr,
  4983  		networkQAPower:  pwr,
  4984  		baselinePower:   pwr,
  4985  
  4986  		epochRewardSmooth:  smoothing.TestingConstantEstimate(rwd),
  4987  		epochQAPowerSmooth: smoothing.TestingConstantEstimate(pwr),
  4988  	}
  4989  	h.setProofType(abi.RegisteredSealProof_StackedDrg32GiBV1_1)
  4990  	return h
  4991  }
  4992  
  4993  func (h *actorHarness) setProofType(proof abi.RegisteredSealProof) {
  4994  	var err error
  4995  	h.sealProofType = proof
  4996  	h.windowPostProofType, err = proof.RegisteredWindowPoStProof()
  4997  	require.NoError(h.t, err)
  4998  	h.sectorSize, err = proof.SectorSize()
  4999  	require.NoError(h.t, err)
  5000  	h.partitionSize, err = builtin.PoStProofWindowPoStPartitionSectors(h.windowPostProofType)
  5001  	require.NoError(h.t, err)
  5002  }
  5003  
  5004  func (h *actorHarness) constructAndVerify(rt *mock.Runtime) {
  5005  	params := miner.ConstructorParams{
  5006  		OwnerAddr:           h.owner,
  5007  		WorkerAddr:          h.worker,
  5008  		ControlAddrs:        h.controlAddrs,
  5009  		WindowPoStProofType: h.windowPostProofType,
  5010  		PeerId:              testPid,
  5011  	}
  5012  
  5013  	rt.ExpectValidateCallerAddr(builtin.InitActorAddr)
  5014  	// Fetch worker pubkey.
  5015  	rt.ExpectSend(h.worker, builtin.MethodsAccount.PubkeyAddress, nil, big.Zero(), &h.key, exitcode.Ok)
  5016  	// Register proving period cron.
  5017  	rt.SetCaller(builtin.InitActorAddr, builtin.InitActorCodeID)
  5018  	ret := rt.Call(h.a.Constructor, &params)
  5019  	assert.Nil(h.t, ret)
  5020  	rt.Verify()
  5021  }
  5022  
  5023  //
  5024  // State access helpers
  5025  //
  5026  
  5027  func (h *actorHarness) deadline(rt *mock.Runtime) *dline.Info {
  5028  	st := getState(rt)
  5029  	return st.RecordedDeadlineInfo(rt.Epoch())
  5030  }
  5031  
  5032  func (h *actorHarness) currentDeadline(rt *mock.Runtime) *dline.Info {
  5033  	st := getState(rt)
  5034  	return st.DeadlineInfo(rt.Epoch())
  5035  }
  5036  
  5037  func (h *actorHarness) getPreCommit(rt *mock.Runtime, sno abi.SectorNumber) *miner.SectorPreCommitOnChainInfo {
  5038  	st := getState(rt)
  5039  	pc, found, err := st.GetPrecommittedSector(rt.AdtStore(), sno)
  5040  	require.NoError(h.t, err)
  5041  	require.True(h.t, found)
  5042  	return pc
  5043  }
  5044  
  5045  func (h *actorHarness) getSector(rt *mock.Runtime, sno abi.SectorNumber) *miner.SectorOnChainInfo {
  5046  	st := getState(rt)
  5047  	sector, found, err := st.GetSector(rt.AdtStore(), sno)
  5048  	require.NoError(h.t, err)
  5049  	require.True(h.t, found)
  5050  	return sector
  5051  }
  5052  
  5053  func (h *actorHarness) getInfo(rt *mock.Runtime) *miner.MinerInfo {
  5054  	var st miner.State
  5055  	rt.GetState(&st)
  5056  	info, err := st.GetInfo(rt.AdtStore())
  5057  	require.NoError(h.t, err)
  5058  	return info
  5059  }
  5060  
  5061  func (h *actorHarness) getDeadlines(rt *mock.Runtime) *miner.Deadlines {
  5062  	st := getState(rt)
  5063  	deadlines, err := st.LoadDeadlines(rt.AdtStore())
  5064  	require.NoError(h.t, err)
  5065  	return deadlines
  5066  }
  5067  
  5068  func (h *actorHarness) getDeadline(rt *mock.Runtime, idx uint64) *miner.Deadline {
  5069  	dls := h.getDeadlines(rt)
  5070  	deadline, err := dls.LoadDeadline(rt.AdtStore(), idx)
  5071  	require.NoError(h.t, err)
  5072  	return deadline
  5073  }
  5074  
  5075  func (h *actorHarness) getPartition(rt *mock.Runtime, deadline *miner.Deadline, idx uint64) *miner.Partition {
  5076  	partition, err := deadline.LoadPartition(rt.AdtStore(), idx)
  5077  	require.NoError(h.t, err)
  5078  	return partition
  5079  }
  5080  
  5081  func (h *actorHarness) getPartitionSnapshot(rt *mock.Runtime, deadline *miner.Deadline, idx uint64) *miner.Partition {
  5082  	partition, err := deadline.LoadPartitionSnapshot(rt.AdtStore(), idx)
  5083  	require.NoError(h.t, err)
  5084  	return partition
  5085  }
  5086  
  5087  func (h *actorHarness) getSubmittedProof(rt *mock.Runtime, deadline *miner.Deadline, idx uint64) *miner.WindowedPoSt {
  5088  	proofs, err := adt.AsArray(rt.AdtStore(), deadline.OptimisticPoStSubmissionsSnapshot, miner.DeadlineOptimisticPoStSubmissionsAmtBitwidth)
  5089  	require.NoError(h.t, err)
  5090  	var post miner.WindowedPoSt
  5091  	found, err := proofs.Get(idx, &post)
  5092  	require.NoError(h.t, err)
  5093  	require.True(h.t, found)
  5094  	return &post
  5095  }
  5096  
  5097  func (h *actorHarness) getDeadlineAndPartition(rt *mock.Runtime, dlIdx, pIdx uint64) (*miner.Deadline, *miner.Partition) {
  5098  	deadline := h.getDeadline(rt, dlIdx)
  5099  	partition := h.getPartition(rt, deadline, pIdx)
  5100  	return deadline, partition
  5101  }
  5102  
  5103  func (h *actorHarness) findSector(rt *mock.Runtime, sno abi.SectorNumber) (*miner.Deadline, *miner.Partition) {
  5104  	var st miner.State
  5105  	rt.GetState(&st)
  5106  	deadlines, err := st.LoadDeadlines(rt.AdtStore())
  5107  	require.NoError(h.t, err)
  5108  	dlIdx, pIdx, err := miner.FindSector(rt.AdtStore(), deadlines, sno)
  5109  	require.NoError(h.t, err)
  5110  
  5111  	deadline, err := deadlines.LoadDeadline(rt.AdtStore(), dlIdx)
  5112  	require.NoError(h.t, err)
  5113  	partition, err := deadline.LoadPartition(rt.AdtStore(), pIdx)
  5114  	require.NoError(h.t, err)
  5115  	return deadline, partition
  5116  }
  5117  
  5118  // Collects all sector infos into a map.
  5119  func (h *actorHarness) collectSectors(rt *mock.Runtime) map[abi.SectorNumber]*miner.SectorOnChainInfo {
  5120  	sectors := map[abi.SectorNumber]*miner.SectorOnChainInfo{}
  5121  	st := getState(rt)
  5122  	_ = st.ForEachSector(rt.AdtStore(), func(info *miner.SectorOnChainInfo) {
  5123  		sector := *info
  5124  		sectors[info.SectorNumber] = &sector
  5125  	})
  5126  	return sectors
  5127  }
  5128  
  5129  func (h *actorHarness) collectDeadlineExpirations(rt *mock.Runtime, deadline *miner.Deadline) map[abi.ChainEpoch][]uint64 {
  5130  	queue, err := miner.LoadBitfieldQueue(rt.AdtStore(), deadline.ExpirationsEpochs, miner.NoQuantization, miner.DeadlineExpirationAmtBitwidth)
  5131  	require.NoError(h.t, err)
  5132  	expirations := map[abi.ChainEpoch][]uint64{}
  5133  	_ = queue.ForEach(func(epoch abi.ChainEpoch, bf bitfield.BitField) error {
  5134  		expanded, err := bf.All(miner.AddressedSectorsMax)
  5135  		require.NoError(h.t, err)
  5136  		expirations[epoch] = expanded
  5137  		return nil
  5138  	})
  5139  	return expirations
  5140  }
  5141  
  5142  func (h *actorHarness) collectPartitionExpirations(rt *mock.Runtime, partition *miner.Partition) map[abi.ChainEpoch]*miner.ExpirationSet {
  5143  	queue, err := miner.LoadExpirationQueue(rt.AdtStore(), partition.ExpirationsEpochs, miner.NoQuantization, miner.PartitionExpirationAmtBitwidth)
  5144  	require.NoError(h.t, err)
  5145  	expirations := map[abi.ChainEpoch]*miner.ExpirationSet{}
  5146  	var es miner.ExpirationSet
  5147  	_ = queue.ForEach(&es, func(i int64) error {
  5148  		cpy := es
  5149  		expirations[abi.ChainEpoch(i)] = &cpy
  5150  		return nil
  5151  	})
  5152  	return expirations
  5153  }
  5154  
  5155  func (h *actorHarness) getLockedFunds(rt *mock.Runtime) abi.TokenAmount {
  5156  	st := getState(rt)
  5157  	return st.LockedFunds
  5158  }
  5159  
  5160  func (h *actorHarness) checkState(rt *mock.Runtime) {
  5161  	st := getState(rt)
  5162  	_, msgs := miner.CheckStateInvariants(st, rt.AdtStore(), rt.Balance())
  5163  	assert.True(h.t, msgs.IsEmpty(), strings.Join(msgs.Messages(), "\n"))
  5164  }
  5165  
  5166  //
  5167  // Actor method calls
  5168  //
  5169  
  5170  func (h *actorHarness) changeWorkerAddress(rt *mock.Runtime, newWorker addr.Address, effectiveEpoch abi.ChainEpoch, newControlAddrs []addr.Address) {
  5171  	rt.SetAddressActorType(newWorker, builtin.AccountActorCodeID)
  5172  
  5173  	param := &miner.ChangeWorkerAddressParams{}
  5174  	param.NewControlAddrs = newControlAddrs
  5175  	param.NewWorker = newWorker
  5176  	rt.ExpectSend(newWorker, builtin.MethodsAccount.PubkeyAddress, nil, big.Zero(), &h.key, exitcode.Ok)
  5177  
  5178  	rt.ExpectValidateCallerAddr(h.owner)
  5179  	rt.SetCaller(h.owner, builtin.AccountActorCodeID)
  5180  	rt.Call(h.a.ChangeWorkerAddress, param)
  5181  	rt.Verify()
  5182  
  5183  	st := getState(rt)
  5184  	info, err := st.GetInfo(adt.AsStore(rt))
  5185  	require.NoError(h.t, err)
  5186  
  5187  	var controlAddrs []addr.Address
  5188  	for _, ca := range newControlAddrs {
  5189  		resolved, found := rt.GetIdAddr(ca)
  5190  		require.True(h.t, found)
  5191  		controlAddrs = append(controlAddrs, resolved)
  5192  	}
  5193  	require.EqualValues(h.t, controlAddrs, info.ControlAddresses)
  5194  
  5195  }
  5196  
  5197  func (h *actorHarness) confirmUpdateWorkerKey(rt *mock.Runtime) {
  5198  	rt.ExpectValidateCallerAddr(h.owner)
  5199  	rt.SetCaller(h.owner, builtin.AccountActorCodeID)
  5200  	rt.Call(h.a.ConfirmUpdateWorkerKey, nil)
  5201  	rt.Verify()
  5202  }
  5203  
  5204  func (h *actorHarness) changeOwnerAddress(rt *mock.Runtime, newAddr addr.Address) {
  5205  	if rt.Caller() == h.owner {
  5206  		rt.ExpectValidateCallerAddr(h.owner)
  5207  	} else {
  5208  		info := h.getInfo(rt)
  5209  		if info.PendingOwnerAddress != nil {
  5210  			rt.ExpectValidateCallerAddr(*info.PendingOwnerAddress)
  5211  		} else {
  5212  			rt.ExpectValidateCallerAddr(h.owner)
  5213  		}
  5214  	}
  5215  	rt.Call(h.a.ChangeOwnerAddress, &newAddr)
  5216  	rt.Verify()
  5217  }
  5218  
  5219  func (h *actorHarness) checkSectorProven(rt *mock.Runtime, sectorNum abi.SectorNumber) {
  5220  	param := &miner.CheckSectorProvenParams{SectorNumber: sectorNum}
  5221  
  5222  	rt.ExpectValidateCallerAny()
  5223  
  5224  	rt.Call(h.a.CheckSectorProven, param)
  5225  	rt.Verify()
  5226  }
  5227  
  5228  func (h *actorHarness) changeMultiAddrs(rt *mock.Runtime, newAddrs []abi.Multiaddrs) {
  5229  	param := &miner.ChangeMultiaddrsParams{NewMultiaddrs: newAddrs}
  5230  	rt.ExpectValidateCallerAddr(append(h.controlAddrs, h.owner, h.worker)...)
  5231  	rt.SetCaller(h.worker, builtin.AccountActorCodeID)
  5232  
  5233  	rt.Call(h.a.ChangeMultiaddrs, param)
  5234  	rt.Verify()
  5235  
  5236  	// assert addrs has changed
  5237  	st := getState(rt)
  5238  	info, err := st.GetInfo(adt.AsStore(rt))
  5239  	require.NoError(h.t, err)
  5240  	require.EqualValues(h.t, newAddrs, info.Multiaddrs)
  5241  }
  5242  
  5243  func (h *actorHarness) changePeerID(rt *mock.Runtime, newPID abi.PeerID) {
  5244  	param := &miner.ChangePeerIDParams{NewID: newPID}
  5245  	rt.ExpectValidateCallerAddr(append(h.controlAddrs, h.owner, h.worker)...)
  5246  	rt.SetCaller(h.worker, builtin.AccountActorCodeID)
  5247  
  5248  	rt.Call(h.a.ChangePeerID, param)
  5249  	rt.Verify()
  5250  	st := getState(rt)
  5251  	info, err := st.GetInfo(adt.AsStore(rt))
  5252  	require.NoError(h.t, err)
  5253  	require.EqualValues(h.t, newPID, info.PeerId)
  5254  }
  5255  
  5256  func (h *actorHarness) controlAddresses(rt *mock.Runtime) (owner, worker addr.Address, control []addr.Address) {
  5257  	rt.ExpectValidateCallerAny()
  5258  	ret := rt.Call(h.a.ControlAddresses, nil).(*miner.GetControlAddressesReturn)
  5259  	require.NotNil(h.t, ret)
  5260  	rt.Verify()
  5261  	return ret.Owner, ret.Worker, ret.ControlAddrs
  5262  }
  5263  
  5264  // Options for preCommitSector behaviour.
  5265  // Default zero values should let everything be ok.
  5266  type preCommitConf struct {
  5267  	dealWeight         abi.DealWeight
  5268  	verifiedDealWeight abi.DealWeight
  5269  	dealSpace          abi.SectorSize
  5270  	pledgeDelta        *abi.TokenAmount
  5271  }
  5272  
  5273  func (h *actorHarness) preCommitSector(rt *mock.Runtime, params *miner.PreCommitSectorParams, conf preCommitConf, first bool) *miner.SectorPreCommitOnChainInfo {
  5274  	rt.SetCaller(h.worker, builtin.AccountActorCodeID)
  5275  	rt.ExpectValidateCallerAddr(append(h.controlAddrs, h.owner, h.worker)...)
  5276  
  5277  	{
  5278  		expectQueryNetworkInfo(rt, h)
  5279  	}
  5280  	if len(params.DealIDs) > 0 {
  5281  		// If there are any deal IDs, allocate half the weight to non-verified and half to verified.
  5282  		vdParams := market.VerifyDealsForActivationParams{
  5283  			Sectors: []market.SectorDeals{{
  5284  				SectorExpiry: params.Expiration,
  5285  				DealIDs:      params.DealIDs,
  5286  			}},
  5287  		}
  5288  
  5289  		if conf.dealWeight.Nil() {
  5290  			conf.dealWeight = big.Zero()
  5291  		}
  5292  		if conf.verifiedDealWeight.Nil() {
  5293  			conf.verifiedDealWeight = big.Zero()
  5294  		}
  5295  		vdReturn := market.VerifyDealsForActivationReturn{
  5296  			Sectors: []market.SectorWeights{{
  5297  				DealSpace:          uint64(conf.dealSpace),
  5298  				DealWeight:         conf.dealWeight,
  5299  				VerifiedDealWeight: conf.verifiedDealWeight,
  5300  			}},
  5301  		}
  5302  		rt.ExpectSend(builtin.StorageMarketActorAddr, builtin.MethodsMarket.VerifyDealsForActivation, &vdParams, big.Zero(), &vdReturn, exitcode.Ok)
  5303  	}
  5304  	st := getState(rt)
  5305  	if st.FeeDebt.GreaterThan(big.Zero()) {
  5306  		rt.ExpectSend(builtin.BurntFundsActorAddr, builtin.MethodSend, nil, st.FeeDebt, nil, exitcode.Ok)
  5307  	}
  5308  
  5309  	if first {
  5310  		dlInfo := miner.NewDeadlineInfoFromOffsetAndEpoch(st.ProvingPeriodStart, rt.Epoch())
  5311  		cronParams := makeDeadlineCronEventParams(h.t, dlInfo.Last())
  5312  		rt.ExpectSend(builtin.StoragePowerActorAddr, builtin.MethodsPower.EnrollCronEvent, cronParams, big.Zero(), nil, exitcode.Ok)
  5313  	}
  5314  
  5315  	if conf.pledgeDelta != nil {
  5316  		if !conf.pledgeDelta.IsZero() {
  5317  			rt.ExpectSend(builtin.StoragePowerActorAddr, builtin.MethodsPower.UpdatePledgeTotal, conf.pledgeDelta, big.Zero(), nil, exitcode.Ok)
  5318  		}
  5319  	} else if rt.NetworkVersion() < network.Version7 {
  5320  		pledgeDelta := immediatelyVestingFunds(rt, st).Neg()
  5321  		if !pledgeDelta.IsZero() {
  5322  			rt.ExpectSend(builtin.StoragePowerActorAddr, builtin.MethodsPower.UpdatePledgeTotal, &pledgeDelta, big.Zero(), nil, exitcode.Ok)
  5323  		}
  5324  	}
  5325  
  5326  	rt.Call(h.a.PreCommitSector, params)
  5327  	rt.Verify()
  5328  	return h.getPreCommit(rt, params.SectorNumber)
  5329  }
  5330  
  5331  // Options for proveCommitSector behaviour.
  5332  // Default zero values should let everything be ok.
  5333  type proveCommitConf struct {
  5334  	verifyDealsExit    map[abi.SectorNumber]exitcode.ExitCode
  5335  	vestingPledgeDelta *abi.TokenAmount
  5336  }
  5337  
  5338  func (h *actorHarness) proveCommitSector(rt *mock.Runtime, precommit *miner.SectorPreCommitOnChainInfo, params *miner.ProveCommitSectorParams) {
  5339  	commd := cbg.CborCid(tutil.MakeCID("commd", &market.PieceCIDPrefix))
  5340  	sealRand := abi.SealRandomness([]byte{1, 2, 3, 4})
  5341  	sealIntRand := abi.InteractiveSealRandomness([]byte{5, 6, 7, 8})
  5342  	interactiveEpoch := precommit.PreCommitEpoch + miner.PreCommitChallengeDelay
  5343  
  5344  	// Prepare for and receive call to ProveCommitSector
  5345  	{
  5346  		cdcParams := market.ComputeDataCommitmentParams{
  5347  			DealIDs:    precommit.Info.DealIDs,
  5348  			SectorType: precommit.Info.SealProof,
  5349  		}
  5350  		rt.ExpectSend(builtin.StorageMarketActorAddr, builtin.MethodsMarket.ComputeDataCommitment, &cdcParams, big.Zero(), &commd, exitcode.Ok)
  5351  	}
  5352  	{
  5353  		var buf bytes.Buffer
  5354  		receiver := rt.Receiver()
  5355  		err := receiver.MarshalCBOR(&buf)
  5356  		require.NoError(h.t, err)
  5357  		rt.ExpectGetRandomnessTickets(crypto.DomainSeparationTag_SealRandomness, precommit.Info.SealRandEpoch, buf.Bytes(), abi.Randomness(sealRand))
  5358  		rt.ExpectGetRandomnessBeacon(crypto.DomainSeparationTag_InteractiveSealChallengeSeed, interactiveEpoch, buf.Bytes(), abi.Randomness(sealIntRand))
  5359  	}
  5360  	{
  5361  		actorId, err := addr.IDFromAddress(h.receiver)
  5362  		require.NoError(h.t, err)
  5363  		seal := proof.SealVerifyInfo{
  5364  			SectorID: abi.SectorID{
  5365  				Miner:  abi.ActorID(actorId),
  5366  				Number: precommit.Info.SectorNumber,
  5367  			},
  5368  			SealedCID:             precommit.Info.SealedCID,
  5369  			SealProof:             precommit.Info.SealProof,
  5370  			Proof:                 params.Proof,
  5371  			DealIDs:               precommit.Info.DealIDs,
  5372  			Randomness:            sealRand,
  5373  			InteractiveRandomness: sealIntRand,
  5374  			UnsealedCID:           cid.Cid(commd),
  5375  		}
  5376  		rt.ExpectSend(builtin.StoragePowerActorAddr, builtin.MethodsPower.SubmitPoRepForBulkVerify, &seal, abi.NewTokenAmount(0), nil, exitcode.Ok)
  5377  	}
  5378  	rt.SetCaller(h.worker, builtin.AccountActorCodeID)
  5379  	rt.ExpectValidateCallerAny()
  5380  	rt.Call(h.a.ProveCommitSector, params)
  5381  	rt.Verify()
  5382  }
  5383  
  5384  func (h *actorHarness) confirmSectorProofsValid(rt *mock.Runtime, conf proveCommitConf, precommits ...*miner.SectorPreCommitOnChainInfo) {
  5385  	// expect calls to get network stats
  5386  	expectQueryNetworkInfo(rt, h)
  5387  
  5388  	// Prepare for and receive call to ConfirmSectorProofsValid.
  5389  	var validPrecommits []*miner.SectorPreCommitOnChainInfo
  5390  	var allSectorNumbers []abi.SectorNumber
  5391  	for _, precommit := range precommits {
  5392  		allSectorNumbers = append(allSectorNumbers, precommit.Info.SectorNumber)
  5393  		validPrecommits = append(validPrecommits, precommit)
  5394  		if len(precommit.Info.DealIDs) > 0 {
  5395  			vdParams := market.ActivateDealsParams{
  5396  				DealIDs:      precommit.Info.DealIDs,
  5397  				SectorExpiry: precommit.Info.Expiration,
  5398  			}
  5399  			exit, found := conf.verifyDealsExit[precommit.Info.SectorNumber]
  5400  			if found {
  5401  				validPrecommits = validPrecommits[:len(validPrecommits)-1] // pop
  5402  			} else {
  5403  				exit = exitcode.Ok
  5404  			}
  5405  			rt.ExpectSend(builtin.StorageMarketActorAddr, builtin.MethodsMarket.ActivateDeals, &vdParams, big.Zero(), nil, exit)
  5406  		}
  5407  	}
  5408  
  5409  	// expected pledge is the sum of initial pledges
  5410  	if len(validPrecommits) > 0 {
  5411  		expectPledge := big.Zero()
  5412  
  5413  		expectQAPower := big.Zero()
  5414  		expectRawPower := big.Zero()
  5415  		for _, precommit := range validPrecommits {
  5416  			precommitOnChain := h.getPreCommit(rt, precommit.Info.SectorNumber)
  5417  
  5418  			duration := precommit.Info.Expiration - rt.Epoch()
  5419  			if duration >= miner.MinSectorExpiration {
  5420  				qaPowerDelta := miner.QAPowerForWeight(h.sectorSize, duration, precommitOnChain.DealWeight, precommitOnChain.VerifiedDealWeight)
  5421  				expectQAPower = big.Add(expectQAPower, qaPowerDelta)
  5422  				expectRawPower = big.Add(expectRawPower, big.NewIntUnsigned(uint64(h.sectorSize)))
  5423  				pledge := miner.InitialPledgeForPower(qaPowerDelta, h.baselinePower, h.epochRewardSmooth,
  5424  					h.epochQAPowerSmooth, rt.TotalFilCircSupply())
  5425  
  5426  				// if cc upgrade, pledge is max of new and replaced pledges
  5427  				if precommitOnChain.Info.ReplaceCapacity {
  5428  					replaced := h.getSector(rt, precommitOnChain.Info.ReplaceSectorNumber)
  5429  					pledge = big.Max(pledge, replaced.InitialPledge)
  5430  				}
  5431  
  5432  				expectPledge = big.Add(expectPledge, pledge)
  5433  			}
  5434  		}
  5435  
  5436  		if conf.vestingPledgeDelta != nil {
  5437  			expectPledge = big.Add(expectPledge, *conf.vestingPledgeDelta)
  5438  		}
  5439  
  5440  		if !expectPledge.IsZero() {
  5441  			rt.ExpectSend(builtin.StoragePowerActorAddr, builtin.MethodsPower.UpdatePledgeTotal, &expectPledge, big.Zero(), nil, exitcode.Ok)
  5442  		}
  5443  	}
  5444  
  5445  	rt.SetCaller(builtin.StoragePowerActorAddr, builtin.StoragePowerActorCodeID)
  5446  	rt.ExpectValidateCallerAddr(builtin.StoragePowerActorAddr)
  5447  	rt.Call(h.a.ConfirmSectorProofsValid, &builtin.ConfirmSectorProofsParams{Sectors: allSectorNumbers})
  5448  	rt.Verify()
  5449  }
  5450  
  5451  func (h *actorHarness) proveCommitSectorAndConfirm(rt *mock.Runtime, precommit *miner.SectorPreCommitOnChainInfo,
  5452  	params *miner.ProveCommitSectorParams, conf proveCommitConf) *miner.SectorOnChainInfo {
  5453  	h.proveCommitSector(rt, precommit, params)
  5454  	h.confirmSectorProofsValid(rt, conf, precommit)
  5455  
  5456  	newSector := h.getSector(rt, params.SectorNumber)
  5457  	return newSector
  5458  }
  5459  
  5460  // Pre-commits and then proves a number of sectors.
  5461  // The sectors will expire at the end of lifetimePeriods proving periods after now.
  5462  // The runtime epoch will be moved forward to the epoch of commitment proofs.
  5463  func (h *actorHarness) commitAndProveSectors(rt *mock.Runtime, n int, lifetimePeriods uint64, dealIDs [][]abi.DealID, first bool) []*miner.SectorOnChainInfo {
  5464  	precommitEpoch := rt.Epoch()
  5465  	deadline := h.deadline(rt)
  5466  	expiration := deadline.PeriodEnd() + abi.ChainEpoch(lifetimePeriods)*miner.WPoStProvingPeriod
  5467  
  5468  	// Precommit
  5469  	precommits := make([]*miner.SectorPreCommitOnChainInfo, n)
  5470  	for i := 0; i < n; i++ {
  5471  		sectorNo := h.nextSectorNo
  5472  		var sectorDealIDs []abi.DealID
  5473  		if dealIDs != nil {
  5474  			sectorDealIDs = dealIDs[i]
  5475  		}
  5476  		params := h.makePreCommit(sectorNo, precommitEpoch-1, expiration, sectorDealIDs)
  5477  		precommit := h.preCommitSector(rt, params, preCommitConf{}, first && i == 0)
  5478  		precommits[i] = precommit
  5479  		h.nextSectorNo++
  5480  	}
  5481  	advanceToEpochWithCron(rt, h, precommitEpoch+miner.PreCommitChallengeDelay+1)
  5482  
  5483  	info := []*miner.SectorOnChainInfo{}
  5484  	for _, pc := range precommits {
  5485  		sector := h.proveCommitSectorAndConfirm(rt, pc, makeProveCommit(pc.Info.SectorNumber), proveCommitConf{})
  5486  		info = append(info, sector)
  5487  	}
  5488  	rt.Reset()
  5489  	return info
  5490  }
  5491  
  5492  func (h *actorHarness) compactSectorNumbers(rt *mock.Runtime, bf bitfield.BitField) {
  5493  	rt.SetCaller(h.worker, builtin.AccountActorCodeID)
  5494  	rt.ExpectValidateCallerAddr(append(h.controlAddrs, h.owner, h.worker)...)
  5495  
  5496  	rt.Call(h.a.CompactSectorNumbers, &miner.CompactSectorNumbersParams{
  5497  		MaskSectorNumbers: bf,
  5498  	})
  5499  	rt.Verify()
  5500  }
  5501  
  5502  func (h *actorHarness) commitAndProveSector(rt *mock.Runtime, sectorNo abi.SectorNumber, lifetimePeriods uint64, dealIDs []abi.DealID) *miner.SectorOnChainInfo {
  5503  	precommitEpoch := rt.Epoch()
  5504  	deadline := h.deadline(rt)
  5505  	expiration := deadline.PeriodEnd() + abi.ChainEpoch(lifetimePeriods)*miner.WPoStProvingPeriod
  5506  
  5507  	// Precommit
  5508  	preCommitParams := h.makePreCommit(sectorNo, precommitEpoch-1, expiration, dealIDs)
  5509  	precommit := h.preCommitSector(rt, preCommitParams, preCommitConf{}, true)
  5510  
  5511  	advanceToEpochWithCron(rt, h, precommitEpoch+miner.PreCommitChallengeDelay+1)
  5512  
  5513  	sectorInfo := h.proveCommitSectorAndConfirm(rt, precommit, makeProveCommit(preCommitParams.SectorNumber), proveCommitConf{})
  5514  	rt.Reset()
  5515  	return sectorInfo
  5516  }
  5517  
  5518  func (h *actorHarness) commitProveAndUpgradeSector(rt *mock.Runtime, sectorNo, upgradeSectorNo abi.SectorNumber,
  5519  	lifetimePeriods uint64, dealIDs []abi.DealID,
  5520  ) (oldSector *miner.SectorOnChainInfo, newSector *miner.SectorOnChainInfo) {
  5521  	// Move the current epoch forward so that the first deadline is a stable candidate for both sectors
  5522  	rt.SetEpoch(h.periodOffset + miner.WPoStChallengeWindow)
  5523  
  5524  	// Commit a sector to upgrade
  5525  	// Use the max sector number to make sure everything works.
  5526  	oldSector = h.commitAndProveSector(rt, sectorNo, lifetimePeriods, nil)
  5527  
  5528  	// advance cron to activate power.
  5529  	advanceAndSubmitPoSts(rt, h, oldSector)
  5530  
  5531  	st := getState(rt)
  5532  	dlIdx, partIdx, err := st.FindSector(rt.AdtStore(), oldSector.SectorNumber)
  5533  	require.NoError(h.t, err)
  5534  
  5535  	// Reduce the epoch reward so that a new sector's initial pledge would otherwise be lesser.
  5536  	// It has to be reduced quite a lot to overcome the new sector having more power due to verified deal weight.
  5537  	h.epochRewardSmooth = smoothing.TestingConstantEstimate(big.Div(h.epochRewardSmooth.Estimate(), big.NewInt(20)))
  5538  
  5539  	challengeEpoch := rt.Epoch() - 1
  5540  	upgradeParams := h.makePreCommit(upgradeSectorNo, challengeEpoch, oldSector.Expiration, dealIDs)
  5541  	upgradeParams.ReplaceCapacity = true
  5542  	upgradeParams.ReplaceSectorDeadline = dlIdx
  5543  	upgradeParams.ReplaceSectorPartition = partIdx
  5544  	upgradeParams.ReplaceSectorNumber = oldSector.SectorNumber
  5545  	upgrade := h.preCommitSector(rt, upgradeParams, preCommitConf{
  5546  		dealWeight:         big.Zero(),
  5547  		verifiedDealWeight: big.NewInt(int64(h.sectorSize)),
  5548  		dealSpace:          h.sectorSize,
  5549  	}, false)
  5550  
  5551  	// Prove new sector
  5552  	rt.SetEpoch(upgrade.PreCommitEpoch + miner.PreCommitChallengeDelay + 1)
  5553  	newSector = h.proveCommitSectorAndConfirm(rt, upgrade, makeProveCommit(upgrade.Info.SectorNumber), proveCommitConf{})
  5554  
  5555  	return oldSector, newSector
  5556  }
  5557  
  5558  // Deprecated
  5559  func (h *actorHarness) advancePastProvingPeriodWithCron(rt *mock.Runtime) {
  5560  	st := getState(rt)
  5561  	deadline := st.DeadlineInfo(rt.Epoch())
  5562  	rt.SetEpoch(deadline.PeriodEnd())
  5563  	nextCron := deadline.NextPeriodStart() + miner.WPoStProvingPeriod - 1
  5564  	h.onDeadlineCron(rt, &cronConfig{
  5565  		expectedEnrollment: nextCron,
  5566  	})
  5567  	rt.SetEpoch(deadline.NextPeriodStart())
  5568  }
  5569  
  5570  func (h *actorHarness) advancePastDeadlineEndWithCron(rt *mock.Runtime) {
  5571  	deadline := h.deadline(rt)
  5572  	rt.SetEpoch(deadline.PeriodEnd())
  5573  	nextCron := deadline.Last() + miner.WPoStChallengeWindow
  5574  	h.onDeadlineCron(rt, &cronConfig{
  5575  		expectedEnrollment: nextCron,
  5576  	})
  5577  	rt.SetEpoch(deadline.NextPeriodStart())
  5578  }
  5579  
  5580  type poStDisputeResult struct {
  5581  	expectedPowerDelta  miner.PowerPair
  5582  	expectedPledgeDelta abi.TokenAmount
  5583  	expectedPenalty     abi.TokenAmount
  5584  	expectedReward      abi.TokenAmount
  5585  }
  5586  
  5587  func (h *actorHarness) disputeWindowPoSt(rt *mock.Runtime, deadline *dline.Info, proofIndex uint64, infos []*miner.SectorOnChainInfo, expectSuccess *poStDisputeResult) {
  5588  	rt.SetCaller(h.worker, builtin.AccountActorCodeID)
  5589  	rt.ExpectValidateCallerType(builtin.CallerTypesSignable...)
  5590  
  5591  	expectQueryNetworkInfo(rt, h)
  5592  	challengeRand := abi.SealRandomness([]byte{10, 11, 12, 13})
  5593  
  5594  	// only sectors that are not skipped and not existing non-recovered faults will be verified
  5595  	allIgnored := bf()
  5596  	dln := h.getDeadline(rt, deadline.Index)
  5597  
  5598  	post := h.getSubmittedProof(rt, dln, proofIndex)
  5599  
  5600  	var err error
  5601  	err = post.Partitions.ForEach(func(idx uint64) error {
  5602  		partition := h.getPartitionSnapshot(rt, dln, idx)
  5603  		allIgnored, err = bitfield.MergeBitFields(allIgnored, partition.Faults)
  5604  		require.NoError(h.t, err)
  5605  		noRecoveries, err := partition.Recoveries.IsEmpty()
  5606  		require.NoError(h.t, err)
  5607  		require.True(h.t, noRecoveries)
  5608  		return nil
  5609  	})
  5610  	require.NoError(h.t, err)
  5611  
  5612  	// find the first non-faulty, non-skipped sector in poSt to replace all faulty sectors.
  5613  	var goodInfo *miner.SectorOnChainInfo
  5614  	for _, ci := range infos {
  5615  		contains, err := allIgnored.IsSet(uint64(ci.SectorNumber))
  5616  		require.NoError(h.t, err)
  5617  		if !contains {
  5618  			goodInfo = ci
  5619  			break
  5620  		}
  5621  	}
  5622  	require.NotNil(h.t, goodInfo, "stored proof should prove at least one sector")
  5623  
  5624  	var buf bytes.Buffer
  5625  	receiver := rt.Receiver()
  5626  	err = receiver.MarshalCBOR(&buf)
  5627  	require.NoError(h.t, err)
  5628  
  5629  	rt.ExpectGetRandomnessBeacon(crypto.DomainSeparationTag_WindowedPoStChallengeSeed, deadline.Challenge, buf.Bytes(), abi.Randomness(challengeRand))
  5630  
  5631  	actorId, err := addr.IDFromAddress(h.receiver)
  5632  	require.NoError(h.t, err)
  5633  
  5634  	proofInfos := make([]proof.SectorInfo, len(infos))
  5635  	for i, ci := range infos {
  5636  		si := ci
  5637  		contains, err := allIgnored.IsSet(uint64(ci.SectorNumber))
  5638  		require.NoError(h.t, err)
  5639  		if contains {
  5640  			si = goodInfo
  5641  		}
  5642  		proofInfos[i] = proof.SectorInfo{
  5643  			SealProof:    si.SealProof,
  5644  			SectorNumber: si.SectorNumber,
  5645  			SealedCID:    si.SealedCID,
  5646  		}
  5647  	}
  5648  
  5649  	vi := proof.WindowPoStVerifyInfo{
  5650  		Randomness:        abi.PoStRandomness(challengeRand),
  5651  		Proofs:            post.Proofs,
  5652  		ChallengedSectors: proofInfos,
  5653  		Prover:            abi.ActorID(actorId),
  5654  	}
  5655  	var verifResult error
  5656  	if expectSuccess != nil {
  5657  		// if we succeed at challenging, proof verification needs to fail.
  5658  		verifResult = fmt.Errorf("invalid post")
  5659  	}
  5660  	rt.ExpectVerifyPoSt(vi, verifResult)
  5661  
  5662  	if expectSuccess != nil {
  5663  		// expect power update
  5664  		if !expectSuccess.expectedPowerDelta.IsZero() {
  5665  			claim := &power.UpdateClaimedPowerParams{
  5666  				RawByteDelta:         expectSuccess.expectedPowerDelta.Raw,
  5667  				QualityAdjustedDelta: expectSuccess.expectedPowerDelta.QA,
  5668  			}
  5669  			rt.ExpectSend(builtin.StoragePowerActorAddr, builtin.MethodsPower.UpdateClaimedPower, claim, abi.NewTokenAmount(0),
  5670  				nil, exitcode.Ok)
  5671  		}
  5672  		// expect reward
  5673  		if !expectSuccess.expectedReward.IsZero() {
  5674  			rt.ExpectSend(h.worker, builtin.MethodSend, nil, expectSuccess.expectedReward, nil, exitcode.Ok)
  5675  		}
  5676  		// expect penalty
  5677  		if !expectSuccess.expectedPenalty.IsZero() {
  5678  			rt.ExpectSend(builtin.BurntFundsActorAddr, builtin.MethodSend, nil, expectSuccess.expectedPenalty, nil, exitcode.Ok)
  5679  		}
  5680  		// expect pledge update
  5681  		if !expectSuccess.expectedPledgeDelta.IsZero() {
  5682  			rt.ExpectSend(builtin.StoragePowerActorAddr, builtin.MethodsPower.UpdatePledgeTotal,
  5683  				&expectSuccess.expectedPledgeDelta, abi.NewTokenAmount(0), nil, exitcode.Ok)
  5684  		}
  5685  	}
  5686  
  5687  	params := miner.DisputeWindowedPoStParams{
  5688  		Deadline:  deadline.Index,
  5689  		PoStIndex: proofIndex,
  5690  	}
  5691  	if expectSuccess == nil {
  5692  		rt.ExpectAbortContainsMessage(exitcode.ErrIllegalArgument, "failed to dispute valid post", func() {
  5693  			rt.Call(h.a.DisputeWindowedPoSt, &params)
  5694  		})
  5695  	} else {
  5696  		rt.Call(h.a.DisputeWindowedPoSt, &params)
  5697  	}
  5698  	rt.Verify()
  5699  }
  5700  
  5701  type poStConfig struct {
  5702  	expectedPowerDelta miner.PowerPair
  5703  	verificationError  error
  5704  }
  5705  
  5706  func (h *actorHarness) submitWindowPoSt(rt *mock.Runtime, deadline *dline.Info, partitions []miner.PoStPartition, infos []*miner.SectorOnChainInfo, poStCfg *poStConfig) {
  5707  	h.submitWindowPoStRaw(rt, deadline, partitions, infos, makePoStProofs(h.windowPostProofType), poStCfg)
  5708  }
  5709  
  5710  func (h *actorHarness) submitWindowPoStRaw(rt *mock.Runtime, deadline *dline.Info, partitions []miner.PoStPartition, infos []*miner.SectorOnChainInfo, proofs []proof.PoStProof, poStCfg *poStConfig) {
  5711  	rt.SetCaller(h.worker, builtin.AccountActorCodeID)
  5712  	commitRand := abi.Randomness("chaincommitment")
  5713  	rt.ExpectGetRandomnessTickets(crypto.DomainSeparationTag_PoStChainCommit, deadline.Challenge, nil, commitRand)
  5714  
  5715  	rt.ExpectValidateCallerAddr(append(h.controlAddrs, h.owner, h.worker)...)
  5716  
  5717  	challengeRand := abi.SealRandomness([]byte{10, 11, 12, 13})
  5718  
  5719  	// only sectors that are not skipped and not existing non-recovered faults will be verified
  5720  	allIgnored := bf()
  5721  	allRecovered := bf()
  5722  	dln := h.getDeadline(rt, deadline.Index)
  5723  
  5724  	for _, p := range partitions {
  5725  		partition := h.getPartition(rt, dln, p.Index)
  5726  		expectedFaults, err := bitfield.SubtractBitField(partition.Faults, partition.Recoveries)
  5727  		require.NoError(h.t, err)
  5728  		allIgnored, err = bitfield.MultiMerge(allIgnored, expectedFaults, p.Skipped)
  5729  		require.NoError(h.t, err)
  5730  		recovered, err := bitfield.SubtractBitField(partition.Recoveries, p.Skipped)
  5731  		require.NoError(h.t, err)
  5732  		allRecovered, err = bitfield.MergeBitFields(allRecovered, recovered)
  5733  		require.NoError(h.t, err)
  5734  	}
  5735  	optimistic, err := allRecovered.IsEmpty()
  5736  	require.NoError(h.t, err)
  5737  
  5738  	// find the first non-faulty, non-skipped sector in poSt to replace all faulty sectors.
  5739  	var goodInfo *miner.SectorOnChainInfo
  5740  	for _, ci := range infos {
  5741  		contains, err := allIgnored.IsSet(uint64(ci.SectorNumber))
  5742  		require.NoError(h.t, err)
  5743  		if !contains {
  5744  			goodInfo = ci
  5745  			break
  5746  		}
  5747  	}
  5748  
  5749  	// goodInfo == nil indicates all the sectors have been skipped and should PoSt verification should not occur
  5750  	if !optimistic && goodInfo != nil {
  5751  		var buf bytes.Buffer
  5752  		receiver := rt.Receiver()
  5753  		err := receiver.MarshalCBOR(&buf)
  5754  		require.NoError(h.t, err)
  5755  
  5756  		rt.ExpectGetRandomnessBeacon(crypto.DomainSeparationTag_WindowedPoStChallengeSeed, deadline.Challenge, buf.Bytes(), abi.Randomness(challengeRand))
  5757  
  5758  		actorId, err := addr.IDFromAddress(h.receiver)
  5759  		require.NoError(h.t, err)
  5760  
  5761  		// if not all sectors are skipped
  5762  		proofInfos := make([]proof.SectorInfo, len(infos))
  5763  		for i, ci := range infos {
  5764  			si := ci
  5765  			contains, err := allIgnored.IsSet(uint64(ci.SectorNumber))
  5766  			require.NoError(h.t, err)
  5767  			if contains {
  5768  				si = goodInfo
  5769  			}
  5770  			proofInfos[i] = proof.SectorInfo{
  5771  				SealProof:    si.SealProof,
  5772  				SectorNumber: si.SectorNumber,
  5773  				SealedCID:    si.SealedCID,
  5774  			}
  5775  		}
  5776  
  5777  		vi := proof.WindowPoStVerifyInfo{
  5778  			Randomness:        abi.PoStRandomness(challengeRand),
  5779  			Proofs:            proofs,
  5780  			ChallengedSectors: proofInfos,
  5781  			Prover:            abi.ActorID(actorId),
  5782  		}
  5783  		var verifResult error
  5784  		if poStCfg != nil {
  5785  			verifResult = poStCfg.verificationError
  5786  		}
  5787  		rt.ExpectVerifyPoSt(vi, verifResult)
  5788  	}
  5789  
  5790  	if poStCfg != nil {
  5791  		// expect power update
  5792  		if !poStCfg.expectedPowerDelta.IsZero() {
  5793  			claim := &power.UpdateClaimedPowerParams{
  5794  				RawByteDelta:         poStCfg.expectedPowerDelta.Raw,
  5795  				QualityAdjustedDelta: poStCfg.expectedPowerDelta.QA,
  5796  			}
  5797  			rt.ExpectSend(builtin.StoragePowerActorAddr, builtin.MethodsPower.UpdateClaimedPower, claim, abi.NewTokenAmount(0),
  5798  				nil, exitcode.Ok)
  5799  		}
  5800  	}
  5801  
  5802  	params := miner.SubmitWindowedPoStParams{
  5803  		Deadline:         deadline.Index,
  5804  		Partitions:       partitions,
  5805  		Proofs:           proofs,
  5806  		ChainCommitEpoch: deadline.Challenge,
  5807  		ChainCommitRand:  commitRand,
  5808  	}
  5809  
  5810  	rt.Call(h.a.SubmitWindowedPoSt, &params)
  5811  	rt.Verify()
  5812  }
  5813  
  5814  func (h *actorHarness) declareFaults(rt *mock.Runtime, faultSectorInfos ...*miner.SectorOnChainInfo) miner.PowerPair {
  5815  	rt.SetCaller(h.worker, builtin.AccountActorCodeID)
  5816  	rt.ExpectValidateCallerAddr(append(h.controlAddrs, h.owner, h.worker)...)
  5817  
  5818  	ss, err := faultSectorInfos[0].SealProof.SectorSize()
  5819  	require.NoError(h.t, err)
  5820  	expectedRawDelta, expectedQADelta := powerForSectors(ss, faultSectorInfos)
  5821  	expectedRawDelta = expectedRawDelta.Neg()
  5822  	expectedQADelta = expectedQADelta.Neg()
  5823  
  5824  	// expect power update
  5825  	claim := &power.UpdateClaimedPowerParams{
  5826  		RawByteDelta:         expectedRawDelta,
  5827  		QualityAdjustedDelta: expectedQADelta,
  5828  	}
  5829  	rt.ExpectSend(
  5830  		builtin.StoragePowerActorAddr,
  5831  		builtin.MethodsPower.UpdateClaimedPower,
  5832  		claim,
  5833  		abi.NewTokenAmount(0),
  5834  		nil,
  5835  		exitcode.Ok,
  5836  	)
  5837  
  5838  	// Calculate params from faulted sector infos
  5839  	st := getState(rt)
  5840  	params := makeFaultParamsFromFaultingSectors(h.t, st, rt.AdtStore(), faultSectorInfos)
  5841  	rt.Call(h.a.DeclareFaults, params)
  5842  	rt.Verify()
  5843  
  5844  	return miner.NewPowerPair(claim.RawByteDelta, claim.QualityAdjustedDelta)
  5845  }
  5846  
  5847  func (h *actorHarness) declareRecoveries(rt *mock.Runtime, deadlineIdx uint64, partitionIdx uint64, recoverySectors bitfield.BitField, expectedDebtRepaid abi.TokenAmount) {
  5848  	rt.SetCaller(h.worker, builtin.AccountActorCodeID)
  5849  	rt.ExpectValidateCallerAddr(append(h.controlAddrs, h.owner, h.worker)...)
  5850  
  5851  	if expectedDebtRepaid.GreaterThan(big.Zero()) {
  5852  		rt.ExpectSend(builtin.BurntFundsActorAddr, builtin.MethodSend, nil, expectedDebtRepaid, nil, exitcode.Ok)
  5853  	}
  5854  
  5855  	// Calculate params from faulted sector infos
  5856  	params := &miner.DeclareFaultsRecoveredParams{Recoveries: []miner.RecoveryDeclaration{{
  5857  		Deadline:  deadlineIdx,
  5858  		Partition: partitionIdx,
  5859  		Sectors:   recoverySectors,
  5860  	}}}
  5861  
  5862  	rt.Call(h.a.DeclareFaultsRecovered, params)
  5863  	rt.Verify()
  5864  }
  5865  
  5866  func (h *actorHarness) extendSectors(rt *mock.Runtime, params *miner.ExtendSectorExpirationParams) {
  5867  	rt.SetCaller(h.worker, builtin.AccountActorCodeID)
  5868  	rt.ExpectValidateCallerAddr(append(h.controlAddrs, h.owner, h.worker)...)
  5869  
  5870  	qaDelta := big.Zero()
  5871  	for _, extension := range params.Extensions {
  5872  		err := extension.Sectors.ForEach(func(sno uint64) error {
  5873  			sector := h.getSector(rt, abi.SectorNumber(sno))
  5874  			newSector := *sector
  5875  			newSector.Expiration = extension.NewExpiration
  5876  			qaDelta = big.Sum(qaDelta,
  5877  				miner.QAPowerForSector(h.sectorSize, &newSector),
  5878  				miner.QAPowerForSector(h.sectorSize, sector).Neg(),
  5879  			)
  5880  			return nil
  5881  		})
  5882  		require.NoError(h.t, err)
  5883  	}
  5884  	if !qaDelta.IsZero() {
  5885  		rt.ExpectSend(builtin.StoragePowerActorAddr,
  5886  			builtin.MethodsPower.UpdateClaimedPower,
  5887  			&power.UpdateClaimedPowerParams{
  5888  				RawByteDelta:         big.Zero(),
  5889  				QualityAdjustedDelta: qaDelta,
  5890  			},
  5891  			abi.NewTokenAmount(0),
  5892  			nil,
  5893  			exitcode.Ok,
  5894  		)
  5895  	}
  5896  	rt.Call(h.a.ExtendSectorExpiration, params)
  5897  	rt.Verify()
  5898  }
  5899  
  5900  func (h *actorHarness) terminateSectors(rt *mock.Runtime, sectors bitfield.BitField, expectedFee abi.TokenAmount) (miner.PowerPair, abi.TokenAmount) {
  5901  	rt.SetCaller(h.worker, builtin.AccountActorCodeID)
  5902  	rt.ExpectValidateCallerAddr(append(h.controlAddrs, h.owner, h.worker)...)
  5903  
  5904  	dealIDs := []abi.DealID{}
  5905  	sectorInfos := []*miner.SectorOnChainInfo{}
  5906  	err := sectors.ForEach(func(secNum uint64) error {
  5907  		sector := h.getSector(rt, abi.SectorNumber(secNum))
  5908  		dealIDs = append(dealIDs, sector.DealIDs...)
  5909  
  5910  		sectorInfos = append(sectorInfos, sector)
  5911  		return nil
  5912  	})
  5913  	require.NoError(h.t, err)
  5914  
  5915  	expectQueryNetworkInfo(rt, h)
  5916  
  5917  	pledgeDelta := big.Zero()
  5918  	var sectorPower miner.PowerPair
  5919  	if big.Zero().LessThan(expectedFee) {
  5920  		rt.ExpectSend(builtin.BurntFundsActorAddr, builtin.MethodSend, nil, expectedFee, nil, exitcode.Ok)
  5921  		pledgeDelta = big.Sum(pledgeDelta, expectedFee.Neg())
  5922  	}
  5923  	// notify change to initial pledge
  5924  	if len(sectorInfos) > 0 {
  5925  		for _, sector := range sectorInfos {
  5926  			pledgeDelta = big.Add(pledgeDelta, sector.InitialPledge.Neg())
  5927  		}
  5928  	}
  5929  	if !pledgeDelta.Equals(big.Zero()) {
  5930  		rt.ExpectSend(builtin.StoragePowerActorAddr, builtin.MethodsPower.UpdatePledgeTotal, &pledgeDelta, big.Zero(), nil, exitcode.Ok)
  5931  	}
  5932  	if len(dealIDs) > 0 {
  5933  		size := len(dealIDs)
  5934  		if size > cbg.MaxLength {
  5935  			size = cbg.MaxLength
  5936  		}
  5937  		rt.ExpectSend(builtin.StorageMarketActorAddr, builtin.MethodsMarket.OnMinerSectorsTerminate, &market.OnMinerSectorsTerminateParams{
  5938  			Epoch:   rt.Epoch(),
  5939  			DealIDs: dealIDs[:size],
  5940  		}, abi.NewTokenAmount(0), nil, exitcode.Ok)
  5941  		dealIDs = dealIDs[size:]
  5942  	}
  5943  	{
  5944  		sectorPower = miner.PowerForSectors(h.sectorSize, sectorInfos)
  5945  		rt.ExpectSend(builtin.StoragePowerActorAddr, builtin.MethodsPower.UpdateClaimedPower, &power.UpdateClaimedPowerParams{
  5946  			RawByteDelta:         sectorPower.Raw.Neg(),
  5947  			QualityAdjustedDelta: sectorPower.QA.Neg(),
  5948  		}, abi.NewTokenAmount(0), nil, exitcode.Ok)
  5949  	}
  5950  
  5951  	// create declarations
  5952  	st := getState(rt)
  5953  	deadlines, err := st.LoadDeadlines(rt.AdtStore())
  5954  	require.NoError(h.t, err)
  5955  
  5956  	declarations := []miner.TerminationDeclaration{}
  5957  	err = sectors.ForEach(func(id uint64) error {
  5958  		dlIdx, pIdx, err := miner.FindSector(rt.AdtStore(), deadlines, abi.SectorNumber(id))
  5959  		require.NoError(h.t, err)
  5960  
  5961  		declarations = append(declarations, miner.TerminationDeclaration{
  5962  			Deadline:  dlIdx,
  5963  			Partition: pIdx,
  5964  			Sectors:   bf(id),
  5965  		})
  5966  		return nil
  5967  	})
  5968  	require.NoError(h.t, err)
  5969  
  5970  	params := &miner.TerminateSectorsParams{Terminations: declarations}
  5971  	rt.Call(h.a.TerminateSectors, params)
  5972  	rt.Verify()
  5973  
  5974  	return sectorPower.Neg(), pledgeDelta
  5975  }
  5976  
  5977  func (h *actorHarness) reportConsensusFault(rt *mock.Runtime, from addr.Address, fault *runtime.ConsensusFault) {
  5978  	rt.SetCaller(from, builtin.AccountActorCodeID)
  5979  	rt.ExpectValidateCallerType(builtin.CallerTypesSignable...)
  5980  	params := &miner.ReportConsensusFaultParams{
  5981  		BlockHeader1:     nil,
  5982  		BlockHeader2:     nil,
  5983  		BlockHeaderExtra: nil,
  5984  	}
  5985  
  5986  	if fault != nil {
  5987  		rt.ExpectVerifyConsensusFault(params.BlockHeader1, params.BlockHeader2, params.BlockHeaderExtra, fault, nil)
  5988  	} else {
  5989  		rt.ExpectVerifyConsensusFault(params.BlockHeader1, params.BlockHeader2, params.BlockHeaderExtra, nil, fmt.Errorf("no fault"))
  5990  	}
  5991  
  5992  	currentReward := reward.ThisEpochRewardReturn{
  5993  		ThisEpochBaselinePower:  h.baselinePower,
  5994  		ThisEpochRewardSmoothed: h.epochRewardSmooth,
  5995  	}
  5996  	rt.ExpectSend(builtin.RewardActorAddr, builtin.MethodsReward.ThisEpochReward, nil, big.Zero(), &currentReward, exitcode.Ok)
  5997  
  5998  	penaltyTotal := miner.ConsensusFaultPenalty(h.epochRewardSmooth.Estimate())
  5999  	// slash reward
  6000  	rwd := miner.RewardForConsensusSlashReport(1, penaltyTotal)
  6001  	rt.ExpectSend(from, builtin.MethodSend, nil, rwd, nil, exitcode.Ok)
  6002  
  6003  	// pay fault fee
  6004  	toBurn := big.Sub(penaltyTotal, rwd)
  6005  	rt.ExpectSend(builtin.BurntFundsActorAddr, builtin.MethodSend, nil, toBurn, nil, exitcode.Ok)
  6006  
  6007  	rt.Call(h.a.ReportConsensusFault, params)
  6008  	rt.Verify()
  6009  }
  6010  
  6011  func (h *actorHarness) applyRewards(rt *mock.Runtime, amt, penalty abi.TokenAmount) {
  6012  	// This harness function does not handle the state where apply rewards is
  6013  	// on a miner with existing fee debt.  This state is not protocol reachable
  6014  	// because currently fee debt prevents election participation.
  6015  	//
  6016  	// We further assume the miner can pay the penalty.  If the miner
  6017  	// goes into debt we can't rely on the harness call
  6018  	// TODO unify those cases
  6019  	lockAmt, _ := miner.LockedRewardFromReward(amt)
  6020  	pledgeDelta := big.Sub(lockAmt, penalty)
  6021  
  6022  	rt.SetCaller(builtin.RewardActorAddr, builtin.RewardActorCodeID)
  6023  	rt.ExpectValidateCallerAddr(builtin.RewardActorAddr)
  6024  	// expect pledge update
  6025  	rt.ExpectSend(
  6026  		builtin.StoragePowerActorAddr,
  6027  		builtin.MethodsPower.UpdatePledgeTotal,
  6028  		&pledgeDelta,
  6029  		abi.NewTokenAmount(0),
  6030  		nil,
  6031  		exitcode.Ok,
  6032  	)
  6033  
  6034  	if penalty.GreaterThan(big.Zero()) {
  6035  		rt.ExpectSend(builtin.BurntFundsActorAddr, builtin.MethodSend, nil, penalty, nil, exitcode.Ok)
  6036  	}
  6037  
  6038  	rt.Call(h.a.ApplyRewards, &builtin.ApplyRewardParams{Reward: amt, Penalty: penalty})
  6039  	rt.Verify()
  6040  }
  6041  
  6042  type cronConfig struct {
  6043  	noEnrollment              bool // true if expect not to continue enrollment false otherwise
  6044  	expectedEnrollment        abi.ChainEpoch
  6045  	detectedFaultsPowerDelta  *miner.PowerPair
  6046  	expiredSectorsPowerDelta  *miner.PowerPair
  6047  	expiredSectorsPledgeDelta abi.TokenAmount
  6048  	continuedFaultsPenalty    abi.TokenAmount // Expected amount burnt to pay continued fault penalties.
  6049  	expiredPrecommitPenalty   abi.TokenAmount // Expected amount burnt to pay for expired precommits
  6050  	repaidFeeDebt             abi.TokenAmount // Expected amount burnt to repay fee debt.
  6051  	penaltyFromUnlocked       abi.TokenAmount // Expected reduction in unlocked balance from penalties exceeding vesting funds.
  6052  }
  6053  
  6054  func (h *actorHarness) onDeadlineCron(rt *mock.Runtime, config *cronConfig) {
  6055  	var st miner.State
  6056  	rt.GetState(&st)
  6057  	rt.ExpectValidateCallerAddr(builtin.StoragePowerActorAddr)
  6058  
  6059  	// Preamble
  6060  	rwd := reward.ThisEpochRewardReturn{
  6061  		ThisEpochBaselinePower:  h.baselinePower,
  6062  		ThisEpochRewardSmoothed: h.epochRewardSmooth,
  6063  	}
  6064  	rt.ExpectSend(builtin.RewardActorAddr, builtin.MethodsReward.ThisEpochReward, nil, big.Zero(), &rwd, exitcode.Ok)
  6065  	networkPower := big.NewIntUnsigned(1 << 50)
  6066  	rt.ExpectSend(builtin.StoragePowerActorAddr, builtin.MethodsPower.CurrentTotalPower, nil, big.Zero(),
  6067  		&power.CurrentTotalPowerReturn{
  6068  			RawBytePower:            networkPower,
  6069  			QualityAdjPower:         networkPower,
  6070  			PledgeCollateral:        h.networkPledge,
  6071  			QualityAdjPowerSmoothed: h.epochQAPowerSmooth,
  6072  		},
  6073  		exitcode.Ok)
  6074  
  6075  	powerDelta := miner.NewPowerPairZero()
  6076  	if config.detectedFaultsPowerDelta != nil {
  6077  		powerDelta = powerDelta.Add(*config.detectedFaultsPowerDelta)
  6078  	}
  6079  	if config.expiredSectorsPowerDelta != nil {
  6080  		powerDelta = powerDelta.Add(*config.expiredSectorsPowerDelta)
  6081  	}
  6082  
  6083  	if !powerDelta.IsZero() {
  6084  		rt.ExpectSend(builtin.StoragePowerActorAddr, builtin.MethodsPower.UpdateClaimedPower, &power.UpdateClaimedPowerParams{
  6085  			RawByteDelta:         powerDelta.Raw,
  6086  			QualityAdjustedDelta: powerDelta.QA,
  6087  		},
  6088  			abi.NewTokenAmount(0), nil, exitcode.Ok)
  6089  	}
  6090  
  6091  	penaltyTotal := big.Zero()
  6092  	pledgeDelta := big.Zero()
  6093  	if !config.continuedFaultsPenalty.NilOrZero() {
  6094  		penaltyTotal = big.Add(penaltyTotal, config.continuedFaultsPenalty)
  6095  	}
  6096  	if !config.repaidFeeDebt.NilOrZero() {
  6097  		penaltyTotal = big.Add(penaltyTotal, config.repaidFeeDebt)
  6098  	}
  6099  	if !config.expiredPrecommitPenalty.NilOrZero() {
  6100  		penaltyTotal = big.Add(penaltyTotal, config.expiredPrecommitPenalty)
  6101  	}
  6102  	if !penaltyTotal.IsZero() {
  6103  		rt.ExpectSend(builtin.BurntFundsActorAddr, builtin.MethodSend, nil, penaltyTotal, nil, exitcode.Ok)
  6104  		penaltyFromVesting := penaltyTotal
  6105  		// Outstanding fee debt is only repaid from unlocked balance, not vesting funds.
  6106  		if !config.repaidFeeDebt.NilOrZero() {
  6107  			penaltyFromVesting = big.Sub(penaltyFromVesting, config.repaidFeeDebt)
  6108  		}
  6109  		// Precommit deposit burns are repaid from PCD account
  6110  		if !config.expiredPrecommitPenalty.NilOrZero() {
  6111  			penaltyFromVesting = big.Sub(penaltyFromVesting, config.expiredPrecommitPenalty)
  6112  		}
  6113  		// New penalties are paid first from vesting funds but, if exhausted, overflow to unlocked balance.
  6114  		if !config.penaltyFromUnlocked.NilOrZero() {
  6115  			penaltyFromVesting = big.Sub(penaltyFromVesting, config.penaltyFromUnlocked)
  6116  		}
  6117  		pledgeDelta = big.Sub(pledgeDelta, penaltyFromVesting)
  6118  	}
  6119  
  6120  	if !config.expiredSectorsPledgeDelta.NilOrZero() {
  6121  		pledgeDelta = big.Add(pledgeDelta, config.expiredSectorsPledgeDelta)
  6122  	}
  6123  
  6124  	pledgeDelta = big.Sub(pledgeDelta, immediatelyVestingFunds(rt, &st))
  6125  
  6126  	if !pledgeDelta.IsZero() {
  6127  		rt.ExpectSend(builtin.StoragePowerActorAddr, builtin.MethodsPower.UpdatePledgeTotal, &pledgeDelta, big.Zero(), nil, exitcode.Ok)
  6128  	}
  6129  
  6130  	// Re-enrollment for next period.
  6131  	if !config.noEnrollment {
  6132  		rt.ExpectSend(builtin.StoragePowerActorAddr, builtin.MethodsPower.EnrollCronEvent,
  6133  			makeDeadlineCronEventParams(h.t, config.expectedEnrollment), big.Zero(), nil, exitcode.Ok)
  6134  	}
  6135  
  6136  	rt.SetCaller(builtin.StoragePowerActorAddr, builtin.StoragePowerActorCodeID)
  6137  	rt.Call(h.a.OnDeferredCronEvent, &miner.CronEventPayload{
  6138  		EventType: miner.CronEventProvingDeadline,
  6139  	})
  6140  	rt.Verify()
  6141  }
  6142  
  6143  func (h *actorHarness) withdrawFunds(rt *mock.Runtime, amountRequested, amountWithdrawn, expectedDebtRepaid abi.TokenAmount) {
  6144  	rt.SetCaller(h.owner, builtin.AccountActorCodeID)
  6145  	rt.ExpectValidateCallerAddr(h.owner)
  6146  
  6147  	rt.ExpectSend(h.owner, builtin.MethodSend, nil, amountWithdrawn, nil, exitcode.Ok)
  6148  	if expectedDebtRepaid.GreaterThan(big.Zero()) {
  6149  		rt.ExpectSend(builtin.BurntFundsActorAddr, builtin.MethodSend, nil, expectedDebtRepaid, nil, exitcode.Ok)
  6150  	}
  6151  	rt.Call(h.a.WithdrawBalance, &miner.WithdrawBalanceParams{
  6152  		AmountRequested: amountRequested,
  6153  	})
  6154  
  6155  	rt.Verify()
  6156  }
  6157  
  6158  func (h *actorHarness) repayDebt(rt *mock.Runtime, value, expectedRepayedFromVest, expectedRepaidFromBalance abi.TokenAmount) {
  6159  	rt.SetCaller(h.worker, builtin.AccountActorCodeID)
  6160  	rt.ExpectValidateCallerAddr(append(h.controlAddrs, h.owner, h.worker)...)
  6161  
  6162  	rt.SetBalance(big.Sum(rt.Balance(), value))
  6163  	rt.SetReceived(value)
  6164  	if expectedRepayedFromVest.GreaterThan(big.Zero()) {
  6165  		pledgeDelta := expectedRepayedFromVest.Neg()
  6166  		rt.ExpectSend(builtin.StoragePowerActorAddr, builtin.MethodsPower.UpdatePledgeTotal, &pledgeDelta, big.Zero(), nil, exitcode.Ok)
  6167  	}
  6168  
  6169  	totalRepaid := big.Sum(expectedRepayedFromVest, expectedRepaidFromBalance)
  6170  	if totalRepaid.GreaterThan((big.Zero())) {
  6171  		rt.ExpectSend(builtin.BurntFundsActorAddr, builtin.MethodSend, nil, totalRepaid, nil, exitcode.Ok)
  6172  	}
  6173  	rt.Call(h.a.RepayDebt, nil)
  6174  
  6175  	rt.Verify()
  6176  }
  6177  
  6178  func (h *actorHarness) compactPartitions(rt *mock.Runtime, deadline uint64, partitions bitfield.BitField) {
  6179  	param := miner.CompactPartitionsParams{Deadline: deadline, Partitions: partitions}
  6180  
  6181  	rt.ExpectValidateCallerAddr(append(h.controlAddrs, h.owner, h.worker)...)
  6182  	rt.SetCaller(h.worker, builtin.AccountActorCodeID)
  6183  
  6184  	rt.Call(h.a.CompactPartitions, &param)
  6185  	rt.Verify()
  6186  }
  6187  
  6188  func (h *actorHarness) continuedFaultPenalty(sectors []*miner.SectorOnChainInfo) abi.TokenAmount {
  6189  	_, qa := powerForSectors(h.sectorSize, sectors)
  6190  	return miner.PledgePenaltyForContinuedFault(h.epochRewardSmooth, h.epochQAPowerSmooth, qa)
  6191  }
  6192  
  6193  func (h *actorHarness) powerPairForSectors(sectors []*miner.SectorOnChainInfo) miner.PowerPair {
  6194  	rawPower, qaPower := powerForSectors(h.sectorSize, sectors)
  6195  	return miner.NewPowerPair(rawPower, qaPower)
  6196  }
  6197  
  6198  func (h *actorHarness) makePreCommit(sectorNo abi.SectorNumber, challenge, expiration abi.ChainEpoch, dealIDs []abi.DealID) *miner.PreCommitSectorParams {
  6199  	return &miner.PreCommitSectorParams{
  6200  		SealProof:     h.sealProofType,
  6201  		SectorNumber:  sectorNo,
  6202  		SealedCID:     tutil.MakeCID("commr", &miner.SealedCIDPrefix),
  6203  		SealRandEpoch: challenge,
  6204  		DealIDs:       dealIDs,
  6205  		Expiration:    expiration,
  6206  	}
  6207  }
  6208  
  6209  func (h *actorHarness) setPeerID(rt *mock.Runtime, newID abi.PeerID) {
  6210  	params := miner.ChangePeerIDParams{NewID: newID}
  6211  
  6212  	rt.SetCaller(h.worker, builtin.AccountActorCodeID)
  6213  	rt.ExpectValidateCallerAddr(append(h.controlAddrs, h.owner, h.worker)...)
  6214  
  6215  	ret := rt.Call(h.a.ChangePeerID, &params)
  6216  	assert.Nil(h.t, ret)
  6217  	rt.Verify()
  6218  
  6219  	var st miner.State
  6220  	rt.GetState(&st)
  6221  	info, err := st.GetInfo(adt.AsStore(rt))
  6222  	require.NoError(h.t, err)
  6223  
  6224  	assert.Equal(h.t, newID, info.PeerId)
  6225  }
  6226  
  6227  func (h *actorHarness) setMultiaddrs(rt *mock.Runtime, newMultiaddrs ...abi.Multiaddrs) {
  6228  	params := miner.ChangeMultiaddrsParams{NewMultiaddrs: newMultiaddrs}
  6229  
  6230  	rt.SetCaller(h.worker, builtin.AccountActorCodeID)
  6231  	rt.ExpectValidateCallerAddr(append(h.controlAddrs, h.owner, h.worker)...)
  6232  
  6233  	ret := rt.Call(h.a.ChangeMultiaddrs, &params)
  6234  	assert.Nil(h.t, ret)
  6235  	rt.Verify()
  6236  
  6237  	var st miner.State
  6238  	rt.GetState(&st)
  6239  	info, err := st.GetInfo(adt.AsStore(rt))
  6240  	require.NoError(h.t, err)
  6241  
  6242  	assert.Equal(h.t, newMultiaddrs, info.Multiaddrs)
  6243  }
  6244  
  6245  //
  6246  // Higher-level orchestration
  6247  //
  6248  
  6249  // Completes a deadline by moving the epoch forward to the penultimate one,
  6250  // if cron is active calling the deadline cron handler,
  6251  // and then advancing to the first epoch in the new deadline.
  6252  // If cron is run asserts that the deadline schedules a new cron on the next deadline
  6253  func advanceDeadline(rt *mock.Runtime, h *actorHarness, config *cronConfig) *dline.Info {
  6254  	st := getState(rt)
  6255  	deadline := miner.NewDeadlineInfoFromOffsetAndEpoch(st.ProvingPeriodStart, rt.Epoch())
  6256  
  6257  	if st.DeadlineCronActive {
  6258  		rt.SetEpoch(deadline.Last())
  6259  
  6260  		config.expectedEnrollment = deadline.Last() + miner.WPoStChallengeWindow
  6261  		h.onDeadlineCron(rt, config)
  6262  	}
  6263  	rt.SetEpoch(deadline.NextOpen())
  6264  	st = getState(rt)
  6265  
  6266  	return st.DeadlineInfo(rt.Epoch())
  6267  }
  6268  
  6269  func advanceToEpochWithCron(rt *mock.Runtime, h *actorHarness, e abi.ChainEpoch) {
  6270  	deadline := h.deadline(rt)
  6271  	for e > deadline.Last() {
  6272  		advanceDeadline(rt, h, &cronConfig{})
  6273  		deadline = h.deadline(rt)
  6274  	}
  6275  	rt.SetEpoch(e)
  6276  }
  6277  
  6278  // Advance between 0 and 48 deadlines submitting window posts where necessary to keep
  6279  // sectors proven.  If sectors is empty this is a noop. If sectors is a singleton this
  6280  // will advance to that sector's proving deadline running deadline crons up to and
  6281  // including this deadline. If sectors includes a sector assigned to the furthest
  6282  // away deadline this will process a whole proving period.
  6283  func advanceAndSubmitPoSts(rt *mock.Runtime, h *actorHarness, sectors ...*miner.SectorOnChainInfo) {
  6284  	st := getState(rt)
  6285  
  6286  	sectorArr, err := miner.LoadSectors(rt.AdtStore(), st.Sectors)
  6287  	require.NoError(h.t, err)
  6288  
  6289  	deadlines := map[uint64][]*miner.SectorOnChainInfo{}
  6290  	for _, sector := range sectors {
  6291  		dlIdx, _, err := st.FindSector(rt.AdtStore(), sector.SectorNumber)
  6292  		require.NoError(h.t, err)
  6293  		deadlines[dlIdx] = append(deadlines[dlIdx], sector)
  6294  	}
  6295  
  6296  	dlinfo := h.currentDeadline(rt)
  6297  	for len(deadlines) > 0 {
  6298  		dlSectors, ok := deadlines[dlinfo.Index]
  6299  		if ok {
  6300  			sectorNos := bitfield.New()
  6301  			for _, sector := range dlSectors {
  6302  				sectorNos.Set(uint64(sector.SectorNumber))
  6303  			}
  6304  
  6305  			dlArr, err := st.LoadDeadlines(rt.AdtStore())
  6306  			require.NoError(h.t, err)
  6307  			dl, err := dlArr.LoadDeadline(rt.AdtStore(), dlinfo.Index)
  6308  			require.NoError(h.t, err)
  6309  			parts, err := dl.PartitionsArray(rt.AdtStore())
  6310  			require.NoError(h.t, err)
  6311  
  6312  			var partition miner.Partition
  6313  			partitions := []miner.PoStPartition{}
  6314  			powerDelta := miner.NewPowerPairZero()
  6315  			require.NoError(h.t, parts.ForEach(&partition, func(partIdx int64) error {
  6316  				live, err := partition.LiveSectors()
  6317  				require.NoError(h.t, err)
  6318  				toProve, err := bitfield.IntersectBitField(live, sectorNos)
  6319  				require.NoError(h.t, err)
  6320  				noProven, err := toProve.IsEmpty()
  6321  				require.NoError(h.t, err)
  6322  				if noProven {
  6323  					// not proving anything in this partition.
  6324  					return nil
  6325  				}
  6326  
  6327  				toSkip, err := bitfield.SubtractBitField(live, toProve)
  6328  				require.NoError(h.t, err)
  6329  
  6330  				notRecovering, err := bitfield.SubtractBitField(partition.Faults, partition.Recoveries)
  6331  				require.NoError(h.t, err)
  6332  
  6333  				// Don't double-count skips.
  6334  				toSkip, err = bitfield.SubtractBitField(toSkip, notRecovering)
  6335  				require.NoError(h.t, err)
  6336  
  6337  				skippedProven, err := bitfield.SubtractBitField(toSkip, partition.Unproven)
  6338  				require.NoError(h.t, err)
  6339  
  6340  				skippedProvenSectorInfos, err := sectorArr.Load(skippedProven)
  6341  				require.NoError(h.t, err)
  6342  				newFaultyPower := h.powerPairForSectors(skippedProvenSectorInfos)
  6343  
  6344  				newProven, err := bitfield.SubtractBitField(partition.Unproven, toSkip)
  6345  				require.NoError(h.t, err)
  6346  
  6347  				newProvenInfos, err := sectorArr.Load(newProven)
  6348  				require.NoError(h.t, err)
  6349  				newProvenPower := h.powerPairForSectors(newProvenInfos)
  6350  
  6351  				powerDelta = powerDelta.Sub(newFaultyPower)
  6352  				powerDelta = powerDelta.Add(newProvenPower)
  6353  
  6354  				partitions = append(partitions, miner.PoStPartition{Index: uint64(partIdx), Skipped: toSkip})
  6355  				return nil
  6356  			}))
  6357  
  6358  			h.submitWindowPoSt(rt, dlinfo, partitions, dlSectors, &poStConfig{
  6359  				expectedPowerDelta: powerDelta,
  6360  			})
  6361  			delete(deadlines, dlinfo.Index)
  6362  		}
  6363  
  6364  		advanceDeadline(rt, h, &cronConfig{})
  6365  		dlinfo = h.currentDeadline(rt)
  6366  	}
  6367  }
  6368  
  6369  func immediatelyVestingFunds(rt *mock.Runtime, st *miner.State) big.Int {
  6370  	// Account just the very next vesting funds entry.
  6371  	var vesting miner.VestingFunds
  6372  	rt.StoreGet(st.VestingFunds, &vesting)
  6373  	sum := big.Zero()
  6374  	for _, v := range vesting.Funds {
  6375  		if v.Epoch <= rt.Epoch() {
  6376  			sum = big.Add(sum, v.Amount)
  6377  		} else {
  6378  			break
  6379  		}
  6380  	}
  6381  	return sum
  6382  }
  6383  
  6384  //
  6385  // Construction helpers, etc
  6386  //
  6387  
  6388  func builderForHarness(actor *actorHarness) mock.RuntimeBuilder {
  6389  	rb := mock.NewBuilder(actor.receiver).
  6390  		WithActorType(actor.owner, builtin.AccountActorCodeID).
  6391  		WithActorType(actor.worker, builtin.AccountActorCodeID).
  6392  		WithHasher(fixedHasher(uint64(actor.periodOffset)))
  6393  
  6394  	for _, ca := range actor.controlAddrs {
  6395  		rb = rb.WithActorType(ca, builtin.AccountActorCodeID)
  6396  	}
  6397  
  6398  	return rb
  6399  }
  6400  
  6401  func getState(rt *mock.Runtime) *miner.State {
  6402  	var st miner.State
  6403  	rt.GetState(&st)
  6404  	return &st
  6405  }
  6406  
  6407  func makeDeadlineCronEventParams(t testing.TB, epoch abi.ChainEpoch) *power.EnrollCronEventParams {
  6408  	eventPayload := miner.CronEventPayload{EventType: miner.CronEventProvingDeadline}
  6409  	buf := bytes.Buffer{}
  6410  	err := eventPayload.MarshalCBOR(&buf)
  6411  	require.NoError(t, err)
  6412  
  6413  	params := &power.EnrollCronEventParams{
  6414  		EventEpoch: epoch,
  6415  		Payload:    buf.Bytes(),
  6416  	}
  6417  	return params
  6418  }
  6419  
  6420  func makeProveCommit(sectorNo abi.SectorNumber) *miner.ProveCommitSectorParams {
  6421  	return &miner.ProveCommitSectorParams{
  6422  		SectorNumber: sectorNo,
  6423  		Proof:        make([]byte, 192),
  6424  	}
  6425  }
  6426  
  6427  func makePoStProofs(registeredPoStProof abi.RegisteredPoStProof) []proof.PoStProof {
  6428  	proofs := make([]proof.PoStProof, 1) // Number of proofs doesn't depend on partition count
  6429  	for i := range proofs {
  6430  		proofs[i].PoStProof = registeredPoStProof
  6431  		proofs[i].ProofBytes = []byte(fmt.Sprintf("proof%d", i))
  6432  	}
  6433  	return proofs
  6434  }
  6435  
  6436  func makeFaultParamsFromFaultingSectors(t testing.TB, st *miner.State, store adt.Store, faultSectorInfos []*miner.SectorOnChainInfo) *miner.DeclareFaultsParams {
  6437  	deadlines, err := st.LoadDeadlines(store)
  6438  	require.NoError(t, err)
  6439  
  6440  	declarationMap := map[string]*miner.FaultDeclaration{}
  6441  	for _, sector := range faultSectorInfos {
  6442  		dlIdx, pIdx, err := miner.FindSector(store, deadlines, sector.SectorNumber)
  6443  		require.NoError(t, err)
  6444  
  6445  		key := fmt.Sprintf("%d:%d", dlIdx, pIdx)
  6446  		declaration, ok := declarationMap[key]
  6447  		if !ok {
  6448  			declaration = &miner.FaultDeclaration{
  6449  				Deadline:  dlIdx,
  6450  				Partition: pIdx,
  6451  				Sectors:   bf(),
  6452  			}
  6453  			declarationMap[key] = declaration
  6454  		}
  6455  		declaration.Sectors.Set(uint64(sector.SectorNumber))
  6456  	}
  6457  	require.NoError(t, err)
  6458  
  6459  	var declarations []miner.FaultDeclaration
  6460  	for _, declaration := range declarationMap {
  6461  		declarations = append(declarations, *declaration)
  6462  	}
  6463  
  6464  	return &miner.DeclareFaultsParams{Faults: declarations}
  6465  }
  6466  
  6467  func sectorInfoAsBitfield(infos []*miner.SectorOnChainInfo) bitfield.BitField {
  6468  	bf := bitfield.New()
  6469  	for _, info := range infos {
  6470  		bf.Set(uint64(info.SectorNumber))
  6471  	}
  6472  	return bf
  6473  }
  6474  
  6475  func powerForSectors(sectorSize abi.SectorSize, sectors []*miner.SectorOnChainInfo) (rawBytePower, qaPower big.Int) {
  6476  	rawBytePower = big.Mul(big.NewIntUnsigned(uint64(sectorSize)), big.NewIntUnsigned(uint64(len(sectors))))
  6477  	qaPower = big.Zero()
  6478  	for _, s := range sectors {
  6479  		qaPower = big.Add(qaPower, miner.QAPowerForSector(sectorSize, s))
  6480  	}
  6481  	return rawBytePower, qaPower
  6482  }
  6483  
  6484  func assertEmptyBitfield(t *testing.T, b bitfield.BitField) {
  6485  	empty, err := b.IsEmpty()
  6486  	require.NoError(t, err)
  6487  	assert.True(t, empty)
  6488  }
  6489  
  6490  // Returns a fake hashing function that always arranges the first 8 bytes of the digest to be the binary
  6491  // encoding of a target uint64.
  6492  func fixedHasher(target uint64) func([]byte) [32]byte {
  6493  	return func(_ []byte) [32]byte {
  6494  		var buf bytes.Buffer
  6495  		err := binary.Write(&buf, binary.BigEndian, target)
  6496  		if err != nil {
  6497  			panic(err)
  6498  		}
  6499  		var digest [32]byte
  6500  		copy(digest[:], buf.Bytes())
  6501  		return digest
  6502  	}
  6503  }
  6504  
  6505  func expectQueryNetworkInfo(rt *mock.Runtime, h *actorHarness) {
  6506  	currentPower := power.CurrentTotalPowerReturn{
  6507  		RawBytePower:            h.networkRawPower,
  6508  		QualityAdjPower:         h.networkQAPower,
  6509  		PledgeCollateral:        h.networkPledge,
  6510  		QualityAdjPowerSmoothed: h.epochQAPowerSmooth,
  6511  	}
  6512  	currentReward := reward.ThisEpochRewardReturn{
  6513  		ThisEpochBaselinePower:  h.baselinePower,
  6514  		ThisEpochRewardSmoothed: h.epochRewardSmooth,
  6515  	}
  6516  
  6517  	rt.ExpectSend(
  6518  		builtin.RewardActorAddr,
  6519  		builtin.MethodsReward.ThisEpochReward,
  6520  		nil,
  6521  		big.Zero(),
  6522  		&currentReward,
  6523  		exitcode.Ok,
  6524  	)
  6525  
  6526  	rt.ExpectSend(
  6527  		builtin.StoragePowerActorAddr,
  6528  		builtin.MethodsPower.CurrentTotalPower,
  6529  		nil,
  6530  		big.Zero(),
  6531  		&currentPower,
  6532  		exitcode.Ok,
  6533  	)
  6534  }