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

     1  package miner_test
     2  
     3  import (
     4  	"context"
     5  	"fmt"
     6  	"math"
     7  	"testing"
     8  
     9  	"github.com/filecoin-project/go-bitfield"
    10  	"github.com/filecoin-project/go-state-types/abi"
    11  	"github.com/filecoin-project/go-state-types/big"
    12  	"github.com/filecoin-project/go-state-types/exitcode"
    13  	cid "github.com/ipfs/go-cid"
    14  	"github.com/stretchr/testify/assert"
    15  	"github.com/stretchr/testify/require"
    16  
    17  	"github.com/filecoin-project/specs-actors/v4/actors/builtin"
    18  	"github.com/filecoin-project/specs-actors/v4/actors/builtin/miner"
    19  	"github.com/filecoin-project/specs-actors/v4/actors/util/adt"
    20  	"github.com/filecoin-project/specs-actors/v4/support/ipld"
    21  	tutils "github.com/filecoin-project/specs-actors/v4/support/testing"
    22  )
    23  
    24  func TestPrecommittedSectorsStore(t *testing.T) {
    25  	t.Run("Put, get and delete", func(t *testing.T) {
    26  		harness := constructStateHarness(t, abi.ChainEpoch(0))
    27  		pc1 := newSectorPreCommitOnChainInfo(1, tutils.MakeCID("1", &miner.SealedCIDPrefix), abi.NewTokenAmount(1), abi.ChainEpoch(1))
    28  		harness.putPreCommit(pc1)
    29  		assert.Equal(t, pc1, harness.getPreCommit(1))
    30  
    31  		pc2 := newSectorPreCommitOnChainInfo(2, tutils.MakeCID("2", &miner.SealedCIDPrefix), abi.NewTokenAmount(1), abi.ChainEpoch(1))
    32  		harness.putPreCommit(pc2)
    33  		assert.Equal(t, pc2, harness.getPreCommit(2))
    34  
    35  		harness.deletePreCommit(1)
    36  		assert.False(t, harness.hasPreCommit(1))
    37  	})
    38  
    39  	t.Run("Delete nonexistent value returns an error", func(t *testing.T) {
    40  		harness := constructStateHarness(t, abi.ChainEpoch(0))
    41  		err := harness.s.DeletePrecommittedSectors(harness.store, 1)
    42  		assert.Error(t, err)
    43  	})
    44  
    45  	t.Run("Get nonexistent value returns false", func(t *testing.T) {
    46  		harness := constructStateHarness(t, abi.ChainEpoch(0))
    47  		assert.False(t, harness.hasPreCommit(1))
    48  	})
    49  
    50  	t.Run("Duplicate put rejected", func(t *testing.T) {
    51  		harness := constructStateHarness(t, abi.ChainEpoch(0))
    52  		pc1 := newSectorPreCommitOnChainInfo(1, tutils.MakeCID("1", &miner.SealedCIDPrefix), abi.NewTokenAmount(1), abi.ChainEpoch(1))
    53  		harness.putPreCommit(pc1)
    54  		err := harness.s.PutPrecommittedSector(harness.store, pc1)
    55  		assert.Error(t, err)
    56  	})
    57  }
    58  
    59  func TestSectorsStore(t *testing.T) {
    60  	t.Run("Put get and delete", func(t *testing.T) {
    61  		harness := constructStateHarness(t, abi.ChainEpoch(0))
    62  
    63  		sectorNo := abi.SectorNumber(1)
    64  		sectorInfo1 := newSectorOnChainInfo(sectorNo, tutils.MakeCID("1", &miner.SealedCIDPrefix), big.NewInt(1), abi.ChainEpoch(1))
    65  		sectorInfo2 := newSectorOnChainInfo(sectorNo, tutils.MakeCID("2", &miner.SealedCIDPrefix), big.NewInt(2), abi.ChainEpoch(2))
    66  
    67  		harness.putSector(sectorInfo1)
    68  		assert.True(t, harness.hasSectorNo(sectorNo))
    69  		out := harness.getSector(sectorNo)
    70  		assert.Equal(t, sectorInfo1, out)
    71  
    72  		harness.putSector(sectorInfo2)
    73  		out = harness.getSector(sectorNo)
    74  		assert.Equal(t, sectorInfo2, out)
    75  
    76  		harness.deleteSectors(uint64(sectorNo))
    77  		assert.False(t, harness.hasSectorNo(sectorNo))
    78  	})
    79  
    80  	t.Run("Delete nonexistent value returns an error", func(t *testing.T) {
    81  		harness := constructStateHarness(t, abi.ChainEpoch(0))
    82  
    83  		sectorNo := abi.SectorNumber(1)
    84  		bf := bitfield.New()
    85  		bf.Set(uint64(sectorNo))
    86  
    87  		assert.Error(t, harness.s.DeleteSectors(harness.store, bf))
    88  	})
    89  
    90  	t.Run("Get nonexistent value returns false", func(t *testing.T) {
    91  		harness := constructStateHarness(t, abi.ChainEpoch(0))
    92  
    93  		sectorNo := abi.SectorNumber(1)
    94  		assert.False(t, harness.hasSectorNo(sectorNo))
    95  	})
    96  
    97  	t.Run("Iterate and Delete multiple sector", func(t *testing.T) {
    98  		harness := constructStateHarness(t, abi.ChainEpoch(0))
    99  
   100  		// set of sectors, the larger numbers here are not significant
   101  		sectorNos := []uint64{100, 200, 300, 400, 500, 600, 700, 800, 900, 1000}
   102  
   103  		// put all the sectors in the store
   104  		for _, s := range sectorNos {
   105  			i := int64(0)
   106  			harness.putSector(newSectorOnChainInfo(abi.SectorNumber(s), tutils.MakeCID(fmt.Sprintf("%d", i), &miner.SealedCIDPrefix), big.NewInt(i), abi.ChainEpoch(i)))
   107  			i++
   108  		}
   109  
   110  		sectorNoIdx := 0
   111  		err := harness.s.ForEachSector(harness.store, func(si *miner.SectorOnChainInfo) {
   112  			require.Equal(t, abi.SectorNumber(sectorNos[sectorNoIdx]), si.SectorNumber)
   113  			sectorNoIdx++
   114  		})
   115  		assert.NoError(t, err)
   116  
   117  		// ensure we iterated over the expected number of sectors
   118  		assert.Equal(t, len(sectorNos), sectorNoIdx)
   119  
   120  		harness.deleteSectors(sectorNos...)
   121  		for _, s := range sectorNos {
   122  			assert.False(t, harness.hasSectorNo(abi.SectorNumber(s)))
   123  		}
   124  	})
   125  }
   126  
   127  // TODO minerstate: move to partition
   128  //func TestRecoveriesBitfield(t *testing.T) {
   129  //	t.Run("Add new recoveries happy path", func(t *testing.T) {
   130  //		harness := constructStateHarness(t, abi.ChainEpoch(0))
   131  //
   132  //		// set of sectors, the larger numbers here are not significant
   133  //		sectorNos := []uint64{100, 200, 300, 400, 500, 600, 700, 800, 900, 1000}
   134  //		harness.addRecoveries(sectorNos...)
   135  //		assert.Equal(t, uint64(len(sectorNos)), harness.getRecoveriesCount())
   136  //	})
   137  //
   138  //	t.Run("Add new recoveries excludes duplicates", func(t *testing.T) {
   139  //		harness := constructStateHarness(t, abi.ChainEpoch(0))
   140  //
   141  //		sectorNos := []uint64{1, 1, 2, 2, 3, 4, 5}
   142  //		harness.addRecoveries(sectorNos...)
   143  //		assert.Equal(t, uint64(5), harness.getRecoveriesCount())
   144  //	})
   145  //
   146  //	t.Run("Remove recoveries happy path", func(t *testing.T) {
   147  //		harness := constructStateHarness(t, abi.ChainEpoch(0))
   148  //
   149  //		sectorNos := []uint64{1, 2, 3, 4, 5}
   150  //		harness.addRecoveries(sectorNos...)
   151  //		assert.Equal(t, uint64(len(sectorNos)), harness.getRecoveriesCount())
   152  //
   153  //		harness.removeRecoveries(1, 3, 5)
   154  //		assert.Equal(t, uint64(2), harness.getRecoveriesCount())
   155  //
   156  //		recoveries, err := harness.s.Recoveries.All(uint64(len(sectorNos)))
   157  //		assert.NoError(t, err)
   158  //		assert.Equal(t, []uint64{2, 4}, recoveries)
   159  //	})
   160  //}
   161  
   162  //func TestPostSubmissionsBitfield(t *testing.T) {
   163  //	t.Run("Add new submission happy path", func(t *testing.T) {
   164  //		harness := constructStateHarness(t, abi.ChainEpoch(0))
   165  //
   166  //		// set of sectors, the larger numbers here are not significant
   167  //		partitionNos := []uint64{10, 20, 30, 40}
   168  //		harness.addPoStSubmissions(partitionNos...)
   169  //		assert.Equal(t, uint64(len(partitionNos)), harness.getPoStSubmissionsCount())
   170  //	})
   171  //
   172  //	t.Run("Add new submission excludes duplicates", func(t *testing.T) {
   173  //		harness := constructStateHarness(t, abi.ChainEpoch(0))
   174  //
   175  //		sectorNos := []uint64{1, 1, 2, 2, 3, 4, 5}
   176  //		harness.addPoStSubmissions(sectorNos...)
   177  //		assert.Equal(t, uint64(5), harness.getPoStSubmissionsCount())
   178  //	})
   179  //
   180  //	t.Run("Clear submission happy path", func(t *testing.T) {
   181  //		harness := constructStateHarness(t, abi.ChainEpoch(0))
   182  //
   183  //		sectorNos := []uint64{1, 2, 3, 4, 5}
   184  //		harness.addPoStSubmissions(sectorNos...)
   185  //		assert.Equal(t, uint64(len(sectorNos)), harness.getPoStSubmissionsCount())
   186  //
   187  //		harness.clearPoStSubmissions()
   188  //		assert.Equal(t, uint64(0), harness.getPoStSubmissionsCount())
   189  //	})
   190  //}
   191  
   192  func TestVesting_AddLockedFunds_Table(t *testing.T) {
   193  	vestStartDelay := abi.ChainEpoch(10)
   194  	vestSum := int64(100)
   195  
   196  	testcase := []struct {
   197  		desc        string
   198  		vspec       *miner.VestSpec
   199  		periodStart abi.ChainEpoch
   200  		vepocs      []int64
   201  	}{
   202  		{
   203  			desc: "vest funds in a single epoch",
   204  			vspec: &miner.VestSpec{
   205  				InitialDelay: 0,
   206  				VestPeriod:   1,
   207  				StepDuration: 1,
   208  				Quantization: 1,
   209  			},
   210  			vepocs: []int64{0, 0, 100, 0},
   211  		},
   212  		{
   213  			desc: "vest funds with period=2",
   214  			vspec: &miner.VestSpec{
   215  				InitialDelay: 0,
   216  				VestPeriod:   2,
   217  				StepDuration: 1,
   218  				Quantization: 1,
   219  			},
   220  			vepocs: []int64{0, 0, 50, 50, 0},
   221  		},
   222  		{
   223  			desc: "vest funds with period=2 quantization=2",
   224  			vspec: &miner.VestSpec{
   225  				InitialDelay: 0,
   226  				VestPeriod:   2,
   227  				StepDuration: 1,
   228  				Quantization: 2,
   229  			},
   230  			vepocs: []int64{0, 0, 0, 100, 0},
   231  		},
   232  		{desc: "vest funds with period=3",
   233  			vspec: &miner.VestSpec{
   234  				InitialDelay: 0,
   235  				VestPeriod:   3,
   236  				StepDuration: 1,
   237  				Quantization: 1,
   238  			},
   239  			vepocs: []int64{0, 0, 33, 33, 34, 0},
   240  		},
   241  		{
   242  			desc: "vest funds with period=3 quantization=2",
   243  			vspec: &miner.VestSpec{
   244  				InitialDelay: 0,
   245  				VestPeriod:   3,
   246  				StepDuration: 1,
   247  				Quantization: 2,
   248  			},
   249  			vepocs: []int64{0, 0, 0, 66, 0, 34, 0},
   250  		},
   251  		{desc: "vest funds with period=2 step=2",
   252  			vspec: &miner.VestSpec{
   253  				InitialDelay: 0,
   254  				VestPeriod:   2,
   255  				StepDuration: 2,
   256  				Quantization: 1,
   257  			},
   258  			vepocs: []int64{0, 0, 0, 100, 0},
   259  		},
   260  		{
   261  			desc: "vest funds with period=5 step=2",
   262  			vspec: &miner.VestSpec{
   263  				InitialDelay: 0,
   264  				VestPeriod:   5,
   265  				StepDuration: 2,
   266  				Quantization: 1,
   267  			},
   268  			vepocs: []int64{0, 0, 0, 40, 0, 40, 0, 20, 0},
   269  		},
   270  		{
   271  			desc: "vest funds with delay=1 period=5 step=2",
   272  			vspec: &miner.VestSpec{
   273  				InitialDelay: 1,
   274  				VestPeriod:   5,
   275  				StepDuration: 2,
   276  				Quantization: 1,
   277  			},
   278  			vepocs: []int64{0, 0, 0, 0, 40, 0, 40, 0, 20, 0},
   279  		},
   280  		{
   281  			desc: "vest funds with period=5 step=2 quantization=2",
   282  			vspec: &miner.VestSpec{
   283  				InitialDelay: 0,
   284  				VestPeriod:   5,
   285  				StepDuration: 2,
   286  				Quantization: 2,
   287  			},
   288  			vepocs: []int64{0, 0, 0, 40, 0, 40, 0, 20, 0},
   289  		},
   290  		{
   291  			desc: "vest funds with period=5 step=3 quantization=1",
   292  			vspec: &miner.VestSpec{
   293  				InitialDelay: 0,
   294  				VestPeriod:   5,
   295  				StepDuration: 3,
   296  				Quantization: 1,
   297  			},
   298  			vepocs: []int64{0, 0, 0, 0, 60, 0, 0, 40, 0},
   299  		},
   300  		{
   301  			desc: "vest funds with period=5 step=3 quantization=2",
   302  			vspec: &miner.VestSpec{
   303  				InitialDelay: 0,
   304  				VestPeriod:   5,
   305  				StepDuration: 3,
   306  				Quantization: 2,
   307  			},
   308  			vepocs: []int64{0, 0, 0, 0, 0, 80, 0, 20, 0},
   309  		},
   310  		{
   311  			desc: "(step greater than period) vest funds with period=5 step=6 quantization=1",
   312  			vspec: &miner.VestSpec{
   313  				InitialDelay: 0,
   314  				VestPeriod:   5,
   315  				StepDuration: 6,
   316  				Quantization: 1,
   317  			},
   318  			vepocs: []int64{0, 0, 0, 0, 0, 0, 0, 100, 0},
   319  		},
   320  		{
   321  			desc: "vest funds with delay=5 period=5 step=1 quantization=1",
   322  			vspec: &miner.VestSpec{
   323  				InitialDelay: 5,
   324  				VestPeriod:   5,
   325  				StepDuration: 1,
   326  				Quantization: 1,
   327  			},
   328  			vepocs: []int64{0, 0, 0, 0, 0, 0, 0, 20, 20, 20, 20, 20, 0},
   329  		},
   330  		{
   331  			desc: "vest funds with offset 0",
   332  			vspec: &miner.VestSpec{
   333  				InitialDelay: 0,
   334  				VestPeriod:   10,
   335  				StepDuration: 2,
   336  				Quantization: 2,
   337  			},
   338  			vepocs: []int64{0, 0, 0, 20, 0, 20, 0, 20, 0, 20, 0, 20},
   339  		},
   340  		{
   341  			desc: "vest funds with offset 1",
   342  			vspec: &miner.VestSpec{
   343  				InitialDelay: 0,
   344  				VestPeriod:   10,
   345  				StepDuration: 2,
   346  				Quantization: 2,
   347  			},
   348  			periodStart: abi.ChainEpoch(1),
   349  			// start epoch is at 11 instead of 10 so vepocs are shifted by one from above case
   350  			vepocs: []int64{0, 0, 0, 20, 0, 20, 0, 20, 0, 20, 0, 20},
   351  		},
   352  		{
   353  			desc: "vest funds with proving period start > quantization unit",
   354  			vspec: &miner.VestSpec{
   355  				InitialDelay: 0,
   356  				VestPeriod:   10,
   357  				StepDuration: 2,
   358  				Quantization: 2,
   359  			},
   360  			// 55 % 2 = 1 so expect same vepocs with offset 1 as in previous case
   361  			periodStart: abi.ChainEpoch(55),
   362  			vepocs:      []int64{0, 0, 0, 20, 0, 20, 0, 20, 0, 20, 0, 20},
   363  		},
   364  		{
   365  			desc: "vest funds with step much smaller than quantization",
   366  			vspec: &miner.VestSpec{
   367  				InitialDelay: 0,
   368  				VestPeriod:   10,
   369  				StepDuration: 1,
   370  				Quantization: 5,
   371  			},
   372  			vepocs: []int64{0, 0, 0, 0, 0, 0, 50, 0, 0, 0, 0, 50},
   373  		},
   374  	}
   375  	for _, tc := range testcase {
   376  		t.Run(tc.desc, func(t *testing.T) {
   377  			harness := constructStateHarness(t, tc.periodStart)
   378  			vestStart := tc.periodStart + vestStartDelay
   379  
   380  			harness.addLockedFunds(vestStart, abi.NewTokenAmount(vestSum), tc.vspec)
   381  			assert.Equal(t, abi.NewTokenAmount(vestSum), harness.s.LockedFunds)
   382  
   383  			var totalVested int64
   384  			for e, v := range tc.vepocs {
   385  				assert.Equal(t, abi.NewTokenAmount(v), harness.unlockVestedFunds(vestStart+abi.ChainEpoch(e)))
   386  				totalVested += v
   387  				assert.Equal(t, vestSum-totalVested, harness.s.LockedFunds.Int64())
   388  			}
   389  
   390  			assert.Equal(t, abi.NewTokenAmount(vestSum), abi.NewTokenAmount(totalVested))
   391  			assert.True(t, harness.vestingFundsStoreEmpty())
   392  			assert.Zero(t, harness.s.LockedFunds.Int64())
   393  		})
   394  	}
   395  }
   396  
   397  func TestVestingFunds_AddLockedFunds(t *testing.T) {
   398  	t.Run("LockedFunds increases with sequential calls", func(t *testing.T) {
   399  		harness := constructStateHarness(t, abi.ChainEpoch(0))
   400  		vspec := &miner.VestSpec{
   401  			InitialDelay: 0,
   402  			VestPeriod:   1,
   403  			StepDuration: 1,
   404  			Quantization: 1,
   405  		}
   406  
   407  		vestStart := abi.ChainEpoch(10)
   408  		vestSum := abi.NewTokenAmount(100)
   409  
   410  		harness.addLockedFunds(vestStart, vestSum, vspec)
   411  		assert.Equal(t, vestSum, harness.s.LockedFunds)
   412  
   413  		harness.addLockedFunds(vestStart, vestSum, vspec)
   414  		assert.Equal(t, big.Mul(vestSum, big.NewInt(2)), harness.s.LockedFunds)
   415  	})
   416  
   417  	t.Run("Vests when quantize, step duration, and vesting period are coprime", func(t *testing.T) {
   418  		harness := constructStateHarness(t, abi.ChainEpoch(0))
   419  		vspec := &miner.VestSpec{
   420  			InitialDelay: 0,
   421  			VestPeriod:   27,
   422  			StepDuration: 5,
   423  			Quantization: 7,
   424  		}
   425  		vestStart := abi.ChainEpoch(10)
   426  		vestSum := abi.NewTokenAmount(100)
   427  		harness.addLockedFunds(vestStart, vestSum, vspec)
   428  		assert.Equal(t, vestSum, harness.s.LockedFunds)
   429  
   430  		totalVested := abi.NewTokenAmount(0)
   431  		for e := vestStart; e <= 43; e++ {
   432  			amountVested := harness.unlockVestedFunds(e)
   433  			switch e {
   434  			case 22:
   435  				assert.Equal(t, abi.NewTokenAmount(40), amountVested)
   436  				totalVested = big.Add(totalVested, amountVested)
   437  			case 29:
   438  				assert.Equal(t, abi.NewTokenAmount(26), amountVested)
   439  				totalVested = big.Add(totalVested, amountVested)
   440  			case 36:
   441  				assert.Equal(t, abi.NewTokenAmount(26), amountVested)
   442  				totalVested = big.Add(totalVested, amountVested)
   443  			case 43:
   444  				assert.Equal(t, abi.NewTokenAmount(8), amountVested)
   445  				totalVested = big.Add(totalVested, amountVested)
   446  			default:
   447  				assert.Equal(t, abi.NewTokenAmount(0), amountVested)
   448  			}
   449  		}
   450  		assert.Equal(t, vestSum, totalVested)
   451  		assert.Zero(t, harness.s.LockedFunds.Int64())
   452  		assert.True(t, harness.vestingFundsStoreEmpty())
   453  	})
   454  }
   455  
   456  func TestVestingFunds_UnvestedFunds(t *testing.T) {
   457  	t.Run("Unlock unvested funds leaving bucket with non-zero tokens", func(t *testing.T) {
   458  		harness := constructStateHarness(t, abi.ChainEpoch(0))
   459  		vspec := &miner.VestSpec{
   460  			InitialDelay: 0,
   461  			VestPeriod:   5,
   462  			StepDuration: 1,
   463  			Quantization: 1,
   464  		}
   465  		vestStart := abi.ChainEpoch(100)
   466  		vestSum := abi.NewTokenAmount(100)
   467  
   468  		harness.addLockedFunds(vestStart, vestSum, vspec)
   469  
   470  		amountUnlocked := harness.unlockUnvestedFunds(vestStart, big.NewInt(39))
   471  		assert.Equal(t, big.NewInt(39), amountUnlocked)
   472  
   473  		assert.Equal(t, abi.NewTokenAmount(0), harness.unlockVestedFunds(vestStart))
   474  		assert.Equal(t, abi.NewTokenAmount(0), harness.unlockVestedFunds(vestStart+1))
   475  
   476  		// expected to be zero due to unlocking of UNvested funds
   477  		assert.Equal(t, abi.NewTokenAmount(0), harness.unlockVestedFunds(vestStart+2))
   478  		// expected to be non-zero due to unlocking of UNvested funds
   479  		assert.Equal(t, abi.NewTokenAmount(1), harness.unlockVestedFunds(vestStart+3))
   480  
   481  		assert.Equal(t, abi.NewTokenAmount(20), harness.unlockVestedFunds(vestStart+4))
   482  		assert.Equal(t, abi.NewTokenAmount(20), harness.unlockVestedFunds(vestStart+5))
   483  		assert.Equal(t, abi.NewTokenAmount(20), harness.unlockVestedFunds(vestStart+6))
   484  
   485  		assert.Equal(t, abi.NewTokenAmount(0), harness.unlockVestedFunds(vestStart+7))
   486  
   487  		assert.Zero(t, harness.s.LockedFunds.Int64())
   488  		assert.True(t, harness.vestingFundsStoreEmpty())
   489  	})
   490  
   491  	t.Run("Unlock unvested funds leaving bucket with zero tokens", func(t *testing.T) {
   492  		harness := constructStateHarness(t, abi.ChainEpoch(0))
   493  		vspec := &miner.VestSpec{
   494  			InitialDelay: 0,
   495  			VestPeriod:   5,
   496  			StepDuration: 1,
   497  			Quantization: 1,
   498  		}
   499  		vestStart := abi.ChainEpoch(100)
   500  		vestSum := abi.NewTokenAmount(100)
   501  
   502  		harness.addLockedFunds(vestStart, vestSum, vspec)
   503  
   504  		amountUnlocked := harness.unlockUnvestedFunds(vestStart, big.NewInt(40))
   505  		assert.Equal(t, big.NewInt(40), amountUnlocked)
   506  
   507  		assert.Equal(t, abi.NewTokenAmount(0), harness.unlockVestedFunds(vestStart))
   508  		assert.Equal(t, abi.NewTokenAmount(0), harness.unlockVestedFunds(vestStart+1))
   509  
   510  		// expected to be zero due to unlocking of UNvested funds
   511  		assert.Equal(t, abi.NewTokenAmount(0), harness.unlockVestedFunds(vestStart+2))
   512  		assert.Equal(t, abi.NewTokenAmount(0), harness.unlockVestedFunds(vestStart+3))
   513  
   514  		assert.Equal(t, abi.NewTokenAmount(20), harness.unlockVestedFunds(vestStart+4))
   515  		assert.Equal(t, abi.NewTokenAmount(20), harness.unlockVestedFunds(vestStart+5))
   516  		assert.Equal(t, abi.NewTokenAmount(20), harness.unlockVestedFunds(vestStart+6))
   517  
   518  		assert.Equal(t, abi.NewTokenAmount(0), harness.unlockVestedFunds(vestStart+7))
   519  
   520  		assert.Zero(t, harness.s.LockedFunds.Int64())
   521  		assert.True(t, harness.vestingFundsStoreEmpty())
   522  	})
   523  
   524  	t.Run("Unlock all unvested funds", func(t *testing.T) {
   525  		harness := constructStateHarness(t, abi.ChainEpoch(0))
   526  		vspec := &miner.VestSpec{
   527  			InitialDelay: 0,
   528  			VestPeriod:   5,
   529  			StepDuration: 1,
   530  			Quantization: 1,
   531  		}
   532  		vestStart := abi.ChainEpoch(10)
   533  		vestSum := abi.NewTokenAmount(100)
   534  		harness.addLockedFunds(vestStart, vestSum, vspec)
   535  		unvestedFunds := harness.unlockUnvestedFunds(vestStart, vestSum)
   536  		assert.Equal(t, vestSum, unvestedFunds)
   537  
   538  		assert.Zero(t, harness.s.LockedFunds.Int64())
   539  		assert.True(t, harness.vestingFundsStoreEmpty())
   540  	})
   541  
   542  	t.Run("Unlock unvested funds value greater than LockedFunds", func(t *testing.T) {
   543  		harness := constructStateHarness(t, abi.ChainEpoch(0))
   544  		vspec := &miner.VestSpec{
   545  			InitialDelay: 0,
   546  			VestPeriod:   1,
   547  			StepDuration: 1,
   548  			Quantization: 1,
   549  		}
   550  		vestStart := abi.ChainEpoch(10)
   551  		vestSum := abi.NewTokenAmount(100)
   552  		harness.addLockedFunds(vestStart, vestSum, vspec)
   553  		unvestedFunds := harness.unlockUnvestedFunds(vestStart, abi.NewTokenAmount(200))
   554  		assert.Equal(t, vestSum, unvestedFunds)
   555  
   556  		assert.Zero(t, harness.s.LockedFunds.Int64())
   557  		assert.True(t, harness.vestingFundsStoreEmpty())
   558  
   559  	})
   560  
   561  	t.Run("Unlock unvested funds when there are vested funds in the table", func(t *testing.T) {
   562  		harness := constructStateHarness(t, abi.ChainEpoch(0))
   563  		vspec := &miner.VestSpec{
   564  			InitialDelay: 0,
   565  			VestPeriod:   50,
   566  			StepDuration: 1,
   567  			Quantization: 1,
   568  		}
   569  
   570  		vestStart := abi.ChainEpoch(10)
   571  		vestSum := abi.NewTokenAmount(100)
   572  
   573  		// will lock funds from epochs 11 to 60
   574  		harness.addLockedFunds(vestStart, vestSum, vspec)
   575  
   576  		// unlock funds from epochs 30 to 60
   577  		newEpoch := abi.ChainEpoch(30)
   578  		target := abi.NewTokenAmount(60)
   579  		remaining := big.Sub(vestSum, target)
   580  		unvestedFunds := harness.unlockUnvestedFunds(newEpoch, target)
   581  		assert.Equal(t, target, unvestedFunds)
   582  
   583  		assert.EqualValues(t, remaining, harness.s.LockedFunds)
   584  
   585  		// vesting funds should have all epochs from 11 to 29
   586  		funds, err := harness.s.LoadVestingFunds(harness.store)
   587  		assert.NoError(t, err)
   588  		epoch := 11
   589  		for _, vf := range funds.Funds {
   590  			assert.EqualValues(t, epoch, vf.Epoch)
   591  			epoch = epoch + 1
   592  			if epoch == 30 {
   593  				break
   594  			}
   595  		}
   596  	})
   597  }
   598  
   599  func TestAddPreCommitExpiry(t *testing.T) {
   600  	epoch := abi.ChainEpoch(10)
   601  	sectorNum := abi.SectorNumber(1)
   602  
   603  	t.Run("successfully add a proof to pre commit expiry queue", func(t *testing.T) {
   604  		harness := constructStateHarness(t, abi.ChainEpoch(0))
   605  		err := harness.s.AddPreCommitExpiry(harness.store, epoch, sectorNum)
   606  		require.NoError(t, err)
   607  
   608  		// assert
   609  		quant := harness.s.QuantSpecEveryDeadline()
   610  		queue, err := miner.LoadBitfieldQueue(harness.store, harness.s.PreCommittedSectorsExpiry, quant, miner.PrecommitExpiryAmtBitwidth)
   611  		require.NoError(t, err)
   612  
   613  		require.EqualValues(t, 1, queue.Length())
   614  		bf := bitfield.BitField{}
   615  		qEpoch := quant.QuantizeUp(epoch)
   616  		found, err := queue.Get(uint64(qEpoch), &bf)
   617  		require.NoError(t, err)
   618  		require.True(t, found)
   619  		c, err := bf.Count()
   620  		require.NoError(t, err)
   621  		require.EqualValues(t, 1, c)
   622  		f, err := bf.IsSet(uint64(sectorNum))
   623  		require.NoError(t, err)
   624  		require.True(t, f)
   625  	})
   626  }
   627  
   628  func TestSectorAssignment(t *testing.T) {
   629  	partitionSectors, err := builtin.SealProofWindowPoStPartitionSectors(abi.RegisteredSealProof_StackedDrg32GiBV1_1)
   630  	require.NoError(t, err)
   631  	sectorSize, err := abi.RegisteredSealProof_StackedDrg32GiBV1_1.SectorSize()
   632  	require.NoError(t, err)
   633  
   634  	openDeadlines := miner.WPoStPeriodDeadlines - 2
   635  
   636  	partitionsPerDeadline := uint64(3)
   637  	noSectors := int(partitionSectors * openDeadlines * partitionsPerDeadline)
   638  	sectorInfos := make([]*miner.SectorOnChainInfo, noSectors)
   639  	for i := range sectorInfos {
   640  		sectorInfos[i] = newSectorOnChainInfo(
   641  			abi.SectorNumber(i), tutils.MakeCID(fmt.Sprintf("%d", i), &miner.SealedCIDPrefix), big.NewInt(1), abi.ChainEpoch(0),
   642  		)
   643  	}
   644  
   645  	dlState := expectedDeadlineState{
   646  		sectorSize:    sectorSize,
   647  		partitionSize: partitionSectors,
   648  		sectors:       sectorInfos,
   649  	}
   650  
   651  	t.Run("assign sectors to deadlines", func(t *testing.T) {
   652  		harness := constructStateHarness(t, abi.ChainEpoch(0))
   653  
   654  		err := harness.s.AssignSectorsToDeadlines(harness.store, 0, sectorInfos,
   655  			partitionSectors, sectorSize)
   656  		require.NoError(t, err)
   657  
   658  		sectorArr := sectorsArr(t, harness.store, sectorInfos)
   659  
   660  		dls, err := harness.s.LoadDeadlines(harness.store)
   661  		require.NoError(t, err)
   662  		require.NoError(t, dls.ForEach(harness.store, func(dlIdx uint64, dl *miner.Deadline) error {
   663  			quantSpec := harness.s.QuantSpecForDeadline(dlIdx)
   664  			// deadlines 0 & 1 are closed for assignment right now.
   665  			if dlIdx < 2 {
   666  				dlState.withQuantSpec(quantSpec).
   667  					assert(t, harness.store, dl)
   668  				return nil
   669  			}
   670  
   671  			var partitions []bitfield.BitField
   672  			var postPartitions []miner.PoStPartition
   673  			for i := uint64(0); i < uint64(partitionsPerDeadline); i++ {
   674  				start := ((i * openDeadlines) + (dlIdx - 2)) * partitionSectors
   675  				partBf := seq(t, start, partitionSectors)
   676  				partitions = append(partitions, partBf)
   677  				postPartitions = append(postPartitions, miner.PoStPartition{
   678  					Index:   i,
   679  					Skipped: bf(),
   680  				})
   681  			}
   682  			allSectorBf, err := bitfield.MultiMerge(partitions...)
   683  			require.NoError(t, err)
   684  			allSectorNos, err := allSectorBf.All(uint64(noSectors))
   685  			require.NoError(t, err)
   686  
   687  			dlState.withQuantSpec(quantSpec).
   688  				withUnproven(allSectorNos...).
   689  				withPartitions(partitions...).
   690  				assert(t, harness.store, dl)
   691  
   692  			// Now make sure proving activates power.
   693  
   694  			result, err := dl.RecordProvenSectors(harness.store, sectorArr, sectorSize, quantSpec, 0, postPartitions)
   695  			require.NoError(t, err)
   696  
   697  			expectedPowerDelta := miner.PowerForSectors(sectorSize, selectSectors(t, sectorInfos, allSectorBf))
   698  
   699  			assertBitfieldsEqual(t, allSectorBf, result.Sectors)
   700  			assertBitfieldEmpty(t, result.IgnoredSectors)
   701  			assert.True(t, result.NewFaultyPower.Equals(miner.NewPowerPairZero()))
   702  			assert.True(t, result.PowerDelta.Equals(expectedPowerDelta))
   703  			assert.True(t, result.RecoveredPower.Equals(miner.NewPowerPairZero()))
   704  			assert.True(t, result.RetractedRecoveryPower.Equals(miner.NewPowerPairZero()))
   705  			return nil
   706  		}))
   707  
   708  		// Now prove and activate/check power.
   709  	})
   710  }
   711  
   712  func TestSectorNumberAllocation(t *testing.T) {
   713  	t.Run("can't allocate the same sector number twice", func(t *testing.T) {
   714  		harness := constructStateHarness(t, abi.ChainEpoch(0))
   715  		sectorNo := abi.SectorNumber(1)
   716  
   717  		assert.NoError(t, harness.s.AllocateSectorNumber(harness.store, sectorNo))
   718  		assert.Error(t, harness.s.AllocateSectorNumber(harness.store, sectorNo))
   719  	})
   720  
   721  	t.Run("can mask sector numbers", func(t *testing.T) {
   722  		harness := constructStateHarness(t, abi.ChainEpoch(0))
   723  		sectorNo := abi.SectorNumber(1)
   724  
   725  		assert.NoError(t, harness.s.AllocateSectorNumber(harness.store, sectorNo))
   726  
   727  		assert.NoError(t, harness.s.MaskSectorNumbers(harness.store, bf(0, 1, 2, 3)))
   728  
   729  		assert.Error(t, harness.s.AllocateSectorNumber(harness.store, 3))
   730  		assert.NoError(t, harness.s.AllocateSectorNumber(harness.store, 4))
   731  	})
   732  
   733  	t.Run("can't allocate or mask out of range", func(t *testing.T) {
   734  		harness := constructStateHarness(t, abi.ChainEpoch(0))
   735  		assert.Error(t, harness.s.AllocateSectorNumber(harness.store, abi.MaxSectorNumber+1))
   736  		assert.Error(t, harness.s.MaskSectorNumbers(harness.store, bf(99, abi.MaxSectorNumber+1)))
   737  	})
   738  
   739  	t.Run("can allocate in range", func(t *testing.T) {
   740  		harness := constructStateHarness(t, abi.ChainEpoch(0))
   741  		assert.NoError(t, harness.s.AllocateSectorNumber(harness.store, abi.MaxSectorNumber))
   742  		assert.NoError(t, harness.s.MaskSectorNumbers(harness.store, bf(99, abi.MaxSectorNumber)))
   743  	})
   744  
   745  	t.Run("can compact after growing too large", func(t *testing.T) {
   746  		harness := constructStateHarness(t, abi.ChainEpoch(0))
   747  
   748  		// keep going till we run out of space
   749  		for i := uint64(0); i < math.MaxUint64; i++ {
   750  			no := abi.SectorNumber((i + 1) << 50)
   751  			err := harness.s.AllocateSectorNumber(harness.store, no)
   752  			if err != nil {
   753  				// We failed, yay!
   754  				code := exitcode.Unwrap(err, exitcode.Ok)
   755  				assert.Equal(t, code, exitcode.ErrIllegalArgument)
   756  
   757  				// mask half the sector ranges.
   758  				mask := seq(t, 0, uint64(no)/2)
   759  				require.NoError(t, harness.s.MaskSectorNumbers(harness.store, mask))
   760  
   761  				// try again
   762  				require.NoError(t, harness.s.AllocateSectorNumber(harness.store, no))
   763  				return
   764  			}
   765  		}
   766  	})
   767  }
   768  
   769  func TestRepayDebtInPriorityOrder(t *testing.T) {
   770  	harness := constructStateHarness(t, abi.ChainEpoch(0))
   771  
   772  	currentBalance := abi.NewTokenAmount(300)
   773  	fee := abi.NewTokenAmount(1000)
   774  	err := harness.s.ApplyPenalty(fee)
   775  	require.NoError(t, err)
   776  
   777  	assert.Equal(t, harness.s.FeeDebt, fee)
   778  	penaltyFromVesting, penaltyFromBalance, err := harness.s.RepayPartialDebtInPriorityOrder(harness.store, abi.ChainEpoch(0), currentBalance)
   779  	require.NoError(t, err)
   780  
   781  	assert.Equal(t, penaltyFromVesting, big.Zero())
   782  	assert.Equal(t, penaltyFromBalance, currentBalance)
   783  
   784  	expectedDebt := big.Sub(currentBalance, fee).Neg()
   785  	assert.Equal(t, expectedDebt, harness.s.FeeDebt)
   786  
   787  	currentBalance = abi.NewTokenAmount(0)
   788  	fee = abi.NewTokenAmount(2050)
   789  	err = harness.s.ApplyPenalty(fee)
   790  	require.NoError(t, err)
   791  
   792  	_, _, err = harness.s.RepayPartialDebtInPriorityOrder(harness.store, abi.ChainEpoch(33), currentBalance)
   793  	require.NoError(t, err)
   794  
   795  	expectedDebt = big.Add(expectedDebt, fee)
   796  	assert.Equal(t, expectedDebt, harness.s.FeeDebt)
   797  }
   798  
   799  type stateHarness struct {
   800  	t testing.TB
   801  
   802  	s     *miner.State
   803  	store adt.Store
   804  }
   805  
   806  //
   807  // Vesting Store
   808  //
   809  
   810  func (h *stateHarness) addLockedFunds(epoch abi.ChainEpoch, sum abi.TokenAmount, spec *miner.VestSpec) {
   811  	_, err := h.s.AddLockedFunds(h.store, epoch, sum, spec)
   812  	require.NoError(h.t, err)
   813  }
   814  
   815  func (h *stateHarness) unlockUnvestedFunds(epoch abi.ChainEpoch, target abi.TokenAmount) abi.TokenAmount {
   816  	amount, err := h.s.UnlockUnvestedFunds(h.store, epoch, target)
   817  	require.NoError(h.t, err)
   818  	return amount
   819  }
   820  
   821  func (h *stateHarness) unlockVestedFunds(epoch abi.ChainEpoch) abi.TokenAmount {
   822  	amount, err := h.s.UnlockVestedFunds(h.store, epoch)
   823  	require.NoError(h.t, err)
   824  
   825  	return amount
   826  }
   827  
   828  func (h *stateHarness) vestingFundsStoreEmpty() bool {
   829  	funds, err := h.s.LoadVestingFunds(h.store)
   830  	require.NoError(h.t, err)
   831  
   832  	return len(funds.Funds) == 0
   833  }
   834  
   835  //
   836  // Sector Store Assertion Operations
   837  //
   838  
   839  func (h *stateHarness) hasSectorNo(sectorNo abi.SectorNumber) bool {
   840  	found, err := h.s.HasSectorNo(h.store, sectorNo)
   841  	require.NoError(h.t, err)
   842  	return found
   843  }
   844  
   845  func (h *stateHarness) putSector(sector *miner.SectorOnChainInfo) {
   846  	err := h.s.PutSectors(h.store, sector)
   847  	require.NoError(h.t, err)
   848  }
   849  
   850  func (h *stateHarness) getSector(sectorNo abi.SectorNumber) *miner.SectorOnChainInfo {
   851  	sectors, found, err := h.s.GetSector(h.store, sectorNo)
   852  	require.NoError(h.t, err)
   853  	assert.True(h.t, found)
   854  	assert.NotNil(h.t, sectors)
   855  	return sectors
   856  }
   857  
   858  // makes a bit field from the passed sector numbers
   859  func (h *stateHarness) deleteSectors(sectorNos ...uint64) {
   860  	bf := bitfield.NewFromSet(sectorNos)
   861  	err := h.s.DeleteSectors(h.store, bf)
   862  	require.NoError(h.t, err)
   863  }
   864  
   865  //
   866  // Precommit Store Operations
   867  //
   868  
   869  func (h *stateHarness) putPreCommit(info *miner.SectorPreCommitOnChainInfo) {
   870  	err := h.s.PutPrecommittedSector(h.store, info)
   871  	require.NoError(h.t, err)
   872  }
   873  
   874  func (h *stateHarness) getPreCommit(sectorNo abi.SectorNumber) *miner.SectorPreCommitOnChainInfo {
   875  	out, found, err := h.s.GetPrecommittedSector(h.store, sectorNo)
   876  	require.NoError(h.t, err)
   877  	assert.True(h.t, found)
   878  	return out
   879  }
   880  
   881  func (h *stateHarness) hasPreCommit(sectorNo abi.SectorNumber) bool {
   882  	_, found, err := h.s.GetPrecommittedSector(h.store, sectorNo)
   883  	require.NoError(h.t, err)
   884  	return found
   885  }
   886  
   887  func (h *stateHarness) deletePreCommit(sectorNo abi.SectorNumber) {
   888  	err := h.s.DeletePrecommittedSectors(h.store, sectorNo)
   889  	require.NoError(h.t, err)
   890  }
   891  
   892  func constructStateHarness(t *testing.T, periodBoundary abi.ChainEpoch) *stateHarness {
   893  	// store init
   894  	store := ipld.NewADTStore(context.Background())
   895  	// state field init
   896  	owner := tutils.NewBLSAddr(t, 1)
   897  	worker := tutils.NewBLSAddr(t, 2)
   898  
   899  	testWindowPoStProofType := abi.RegisteredPoStProof_StackedDrgWindow2KiBV1
   900  
   901  	sectorSize, err := testWindowPoStProofType.SectorSize()
   902  	require.NoError(t, err)
   903  
   904  	partitionSectors, err := builtin.PoStProofWindowPoStPartitionSectors(testWindowPoStProofType)
   905  	require.NoError(t, err)
   906  
   907  	info := miner.MinerInfo{
   908  		Owner:                      owner,
   909  		Worker:                     worker,
   910  		PendingWorkerKey:           nil,
   911  		PeerId:                     abi.PeerID("peer"),
   912  		Multiaddrs:                 testMultiaddrs,
   913  		WindowPoStProofType:        testWindowPoStProofType,
   914  		SectorSize:                 sectorSize,
   915  		WindowPoStPartitionSectors: partitionSectors,
   916  	}
   917  	infoCid, err := store.Put(context.Background(), &info)
   918  	require.NoError(t, err)
   919  
   920  	state, err := miner.ConstructState(store, infoCid, periodBoundary, 0)
   921  	require.NoError(t, err)
   922  
   923  	return &stateHarness{
   924  		t: t,
   925  
   926  		s:     state,
   927  		store: store,
   928  	}
   929  }
   930  
   931  //
   932  // Type Construction Methods
   933  //
   934  
   935  // returns a unique SectorPreCommitOnChainInfo with each invocation with SectorNumber set to `sectorNo`.
   936  func newSectorPreCommitOnChainInfo(sectorNo abi.SectorNumber, sealed cid.Cid, deposit abi.TokenAmount, epoch abi.ChainEpoch) *miner.SectorPreCommitOnChainInfo {
   937  	info := newSectorPreCommitInfo(sectorNo, sealed)
   938  	return &miner.SectorPreCommitOnChainInfo{
   939  		Info:               *info,
   940  		PreCommitDeposit:   deposit,
   941  		PreCommitEpoch:     epoch,
   942  		DealWeight:         big.Zero(),
   943  		VerifiedDealWeight: big.Zero(),
   944  	}
   945  }
   946  
   947  const (
   948  	sectorSealRandEpochValue = abi.ChainEpoch(1)
   949  	sectorExpiration         = abi.ChainEpoch(1)
   950  )
   951  
   952  // returns a unique SectorOnChainInfo with each invocation with SectorNumber set to `sectorNo`.
   953  func newSectorOnChainInfo(sectorNo abi.SectorNumber, sealed cid.Cid, weight big.Int, activation abi.ChainEpoch) *miner.SectorOnChainInfo {
   954  	return &miner.SectorOnChainInfo{
   955  		SectorNumber:          sectorNo,
   956  		SealProof:             abi.RegisteredSealProof_StackedDrg32GiBV1_1,
   957  		SealedCID:             sealed,
   958  		DealIDs:               nil,
   959  		Activation:            activation,
   960  		Expiration:            sectorExpiration,
   961  		DealWeight:            weight,
   962  		VerifiedDealWeight:    weight,
   963  		InitialPledge:         abi.NewTokenAmount(0),
   964  		ExpectedDayReward:     abi.NewTokenAmount(0),
   965  		ExpectedStoragePledge: abi.NewTokenAmount(0),
   966  		ReplacedSectorAge:     abi.ChainEpoch(0),
   967  		ReplacedDayReward:     big.Zero(),
   968  	}
   969  }
   970  
   971  // returns a unique SectorPreCommitInfo with each invocation with SectorNumber set to `sectorNo`.
   972  func newSectorPreCommitInfo(sectorNo abi.SectorNumber, sealed cid.Cid) *miner.SectorPreCommitInfo {
   973  	return &miner.SectorPreCommitInfo{
   974  		SealProof:     abi.RegisteredSealProof_StackedDrg32GiBV1_1,
   975  		SectorNumber:  sectorNo,
   976  		SealedCID:     sealed,
   977  		SealRandEpoch: sectorSealRandEpochValue,
   978  		DealIDs:       nil,
   979  		Expiration:    sectorExpiration,
   980  	}
   981  }