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 }