github.com/filecoin-project/specs-actors/v4@v4.0.2/actors/builtin/power/power_test.go (about) 1 package power_test 2 3 import ( 4 "bytes" 5 "fmt" 6 "strconv" 7 "strings" 8 "testing" 9 10 addr "github.com/filecoin-project/go-address" 11 "github.com/filecoin-project/go-state-types/abi" 12 "github.com/filecoin-project/go-state-types/big" 13 "github.com/filecoin-project/go-state-types/exitcode" 14 "github.com/filecoin-project/go-state-types/network" 15 cid "github.com/ipfs/go-cid" 16 assert "github.com/stretchr/testify/assert" 17 require "github.com/stretchr/testify/require" 18 19 "github.com/filecoin-project/specs-actors/v4/actors/builtin" 20 initact "github.com/filecoin-project/specs-actors/v4/actors/builtin/init" 21 "github.com/filecoin-project/specs-actors/v4/actors/builtin/market" 22 mineract "github.com/filecoin-project/specs-actors/v4/actors/builtin/miner" 23 "github.com/filecoin-project/specs-actors/v4/actors/builtin/power" 24 "github.com/filecoin-project/specs-actors/v4/actors/runtime/proof" 25 "github.com/filecoin-project/specs-actors/v4/actors/util/adt" 26 "github.com/filecoin-project/specs-actors/v4/support/mock" 27 tutil "github.com/filecoin-project/specs-actors/v4/support/testing" 28 ) 29 30 func TestExports(t *testing.T) { 31 mock.CheckActorExports(t, power.Actor{}) 32 } 33 34 func TestConstruction(t *testing.T) { 35 actor := newHarness(t) 36 owner := tutil.NewIDAddr(t, 101) 37 miner := tutil.NewIDAddr(t, 103) 38 actr := tutil.NewActorAddr(t, "actor") 39 40 builder := mock.NewBuilder(builtin.StoragePowerActorAddr).WithCaller(builtin.SystemActorAddr, builtin.SystemActorCodeID) 41 42 t.Run("simple construction", func(t *testing.T) { 43 rt := builder.Build(t) 44 45 actor.constructAndVerify(rt) 46 actor.checkState(rt) 47 }) 48 49 t.Run("create miner", func(t *testing.T) { 50 rt := builder.Build(t) 51 actor.constructAndVerify(rt) 52 53 actor.createMiner(rt, owner, owner, miner, actr, abi.PeerID("miner"), []abi.Multiaddrs{{1}}, 54 abi.RegisteredPoStProof_StackedDrgWindow32GiBV1, abi.NewTokenAmount(10)) 55 56 var st power.State 57 rt.GetState(&st) 58 assert.Equal(t, int64(1), st.MinerCount) 59 assert.Equal(t, abi.NewStoragePower(0), st.TotalQualityAdjPower) 60 assert.Equal(t, abi.NewStoragePower(0), st.TotalRawBytePower) 61 assert.Equal(t, int64(0), st.MinerAboveMinPowerCount) 62 63 claim, err := adt.AsMap(adt.AsStore(rt), st.Claims, builtin.DefaultHamtBitwidth) 64 assert.NoError(t, err) 65 keys, err := claim.CollectKeys() 66 require.NoError(t, err) 67 assert.Equal(t, 1, len(keys)) 68 var actualClaim power.Claim 69 found, err_ := claim.Get(asKey(keys[0]), &actualClaim) 70 require.NoError(t, err_) 71 assert.True(t, found) 72 assert.Equal(t, power.Claim{abi.RegisteredPoStProof_StackedDrgWindow32GiBV1, big.Zero(), big.Zero()}, actualClaim) // miner has not proven anything 73 74 verifyEmptyMap(t, rt, st.CronEventQueue) 75 actor.checkState(rt) 76 }) 77 } 78 79 func TestCreateMinerFailures(t *testing.T) { 80 owner := tutil.NewIDAddr(t, 101) 81 peer := abi.PeerID("miner") 82 mAddr := []abi.Multiaddrs{{1}} 83 windowPoStProofType := abi.RegisteredPoStProof_StackedDrgWindow2KiBV1 84 85 t.Run("fails when caller is not of signable type", func(t *testing.T) { 86 rt, ac := basicPowerSetup(t) 87 88 rt.SetCaller(owner, builtin.StorageMinerActorCodeID) 89 rt.ExpectValidateCallerType(builtin.CallerTypesSignable...) 90 rt.ExpectAbort(exitcode.SysErrForbidden, func() { 91 rt.Call(ac.CreateMiner, &power.CreateMinerParams{}) 92 }) 93 rt.Verify() 94 }) 95 96 t.Run("fails if send to Init Actor fails", func(t *testing.T) { 97 rt, ac := basicPowerSetup(t) 98 99 createMinerParams := &power.CreateMinerParams{ 100 Owner: owner, 101 Worker: owner, 102 WindowPoStProofType: windowPoStProofType, 103 Peer: peer, 104 Multiaddrs: mAddr, 105 } 106 107 // owner send CreateMiner to Actor 108 rt.SetCaller(owner, builtin.AccountActorCodeID) 109 rt.SetReceived(abi.NewTokenAmount(10)) 110 rt.SetBalance(abi.NewTokenAmount(10)) 111 rt.ExpectValidateCallerType(builtin.AccountActorCodeID, builtin.MultisigActorCodeID) 112 113 msgParams := &initact.ExecParams{ 114 CodeCID: builtin.StorageMinerActorCodeID, 115 ConstructorParams: initCreateMinerBytes(t, owner, owner, peer, mAddr, windowPoStProofType), 116 } 117 expRet := initact.ExecReturn{ 118 IDAddress: tutil.NewIDAddr(t, 1475), 119 RobustAddress: tutil.NewActorAddr(t, "test"), 120 } 121 rt.ExpectSend(builtin.InitActorAddr, builtin.MethodsInit.Exec, msgParams, abi.NewTokenAmount(10), 122 &expRet, exitcode.ErrInsufficientFunds) 123 124 rt.ExpectAbort(exitcode.ErrInsufficientFunds, func() { 125 rt.Call(ac.CreateMiner, createMinerParams) 126 }) 127 }) 128 } 129 130 func TestUpdateClaimedPowerFailures(t *testing.T) { 131 rawDelta := big.NewInt(100) 132 qaDelta := big.NewInt(200) 133 miner := tutil.NewIDAddr(t, 101) 134 135 t.Run("fails if caller is not a StorageMinerActor", func(t *testing.T) { 136 rt, ac := basicPowerSetup(t) 137 params := power.UpdateClaimedPowerParams{ 138 RawByteDelta: rawDelta, 139 QualityAdjustedDelta: qaDelta, 140 } 141 rt.SetCaller(miner, builtin.SystemActorCodeID) 142 rt.ExpectValidateCallerType(builtin.StorageMinerActorCodeID) 143 144 rt.ExpectAbort(exitcode.SysErrForbidden, func() { 145 rt.Call(ac.UpdateClaimedPower, ¶ms) 146 }) 147 148 rt.Verify() 149 }) 150 151 t.Run("fails if claim does not exist for caller", func(t *testing.T) { 152 rt, ac := basicPowerSetup(t) 153 params := power.UpdateClaimedPowerParams{ 154 RawByteDelta: rawDelta, 155 QualityAdjustedDelta: qaDelta, 156 } 157 rt.SetCaller(miner, builtin.StorageMinerActorCodeID) 158 rt.ExpectValidateCallerType(builtin.StorageMinerActorCodeID) 159 160 rt.ExpectAbort(exitcode.ErrNotFound, func() { 161 rt.Call(ac.UpdateClaimedPower, ¶ms) 162 }) 163 164 rt.Verify() 165 }) 166 } 167 168 func TestEnrollCronEpoch(t *testing.T) { 169 owner := tutil.NewBLSAddr(t, 0) 170 miner := tutil.NewIDAddr(t, 101) 171 172 t.Run("enroll multiple events", func(t *testing.T) { 173 rt, ac := basicPowerSetup(t) 174 ac.createMinerBasic(rt, owner, owner, miner) 175 e1 := abi.ChainEpoch(1) 176 177 // enroll event with miner 1 178 p1 := []byte("hello") 179 ac.enrollCronEvent(rt, miner, e1, p1) 180 181 events := ac.getEnrolledCronTicks(rt, e1) 182 183 evt := events[0] 184 require.EqualValues(t, p1, evt.CallbackPayload) 185 require.EqualValues(t, miner, evt.MinerAddr) 186 187 // enroll another event with the same miner 188 p2 := []byte("hello2") 189 ac.enrollCronEvent(rt, miner, e1, p2) 190 events = ac.getEnrolledCronTicks(rt, e1) 191 evt = events[0] 192 require.EqualValues(t, p1, evt.CallbackPayload) 193 require.EqualValues(t, miner, evt.MinerAddr) 194 195 evt = events[1] 196 require.EqualValues(t, p2, evt.CallbackPayload) 197 require.EqualValues(t, miner, evt.MinerAddr) 198 199 // enroll another event with a different miner for a different epoch 200 e2 := abi.ChainEpoch(2) 201 p3 := []byte("test") 202 miner2 := tutil.NewIDAddr(t, 501) 203 ac.createMinerBasic(rt, owner, owner, miner2) 204 ac.enrollCronEvent(rt, miner2, e2, p3) 205 events = ac.getEnrolledCronTicks(rt, e2) 206 evt = events[0] 207 require.EqualValues(t, p3, evt.CallbackPayload) 208 require.EqualValues(t, miner2, evt.MinerAddr) 209 ac.checkState(rt) 210 }) 211 212 t.Run("enroll for an epoch before the current epoch", func(t *testing.T) { 213 rt, ac := basicPowerSetup(t) 214 ac.createMinerBasic(rt, owner, owner, miner) 215 216 // current epoch is 5 217 current := abi.ChainEpoch(5) 218 rt.SetEpoch(current) 219 220 // enroll event with miner at epoch=2 221 p1 := []byte("hello") 222 e1 := abi.ChainEpoch(2) 223 ac.enrollCronEvent(rt, miner, e1, p1) 224 events := ac.getEnrolledCronTicks(rt, e1) 225 evt := events[0] 226 require.EqualValues(t, p1, evt.CallbackPayload) 227 require.EqualValues(t, miner, evt.MinerAddr) 228 st := getState(rt) 229 require.EqualValues(t, abi.ChainEpoch(0), st.FirstCronEpoch) 230 231 // enroll event with miner at epoch=1 232 p2 := []byte("hello2") 233 e2 := abi.ChainEpoch(1) 234 ac.enrollCronEvent(rt, miner, e2, p2) 235 events = ac.getEnrolledCronTicks(rt, e2) 236 evt = events[0] 237 require.EqualValues(t, p2, evt.CallbackPayload) 238 require.EqualValues(t, miner, evt.MinerAddr) 239 require.EqualValues(t, abi.ChainEpoch(0), st.FirstCronEpoch) 240 ac.checkState(rt) 241 }) 242 243 t.Run("fails if epoch is negative", func(t *testing.T) { 244 rt, ac := basicPowerSetup(t) 245 246 rt.ExpectAbort(exitcode.ErrIllegalArgument, func() { 247 ac.enrollCronEvent(rt, miner, abi.ChainEpoch(-1), []byte("payload")) 248 }) 249 }) 250 } 251 252 func TestPowerAndPledgeAccounting(t *testing.T) { 253 actor := newHarness(t) 254 owner := tutil.NewIDAddr(t, 101) 255 miner1 := tutil.NewIDAddr(t, 111) 256 miner2 := tutil.NewIDAddr(t, 112) 257 miner3 := tutil.NewIDAddr(t, 113) 258 miner4 := tutil.NewIDAddr(t, 114) 259 miner5 := tutil.NewIDAddr(t, 115) 260 261 // These tests use the min power for consensus to check the accounting above and below that value. 262 powerUnit, err := builtin.ConsensusMinerMinPower(abi.RegisteredPoStProof_StackedDrgWindow32GiBV1) 263 require.NoError(t, err) 264 265 mul := func(a big.Int, b int64) big.Int { 266 return big.Mul(a, big.NewInt(b)) 267 } 268 div := func(a big.Int, b int64) big.Int { 269 return big.Div(a, big.NewInt(b)) 270 } 271 smallPowerUnit := big.NewInt(1_000_000) 272 require.True(t, smallPowerUnit.LessThan(powerUnit), "power.ConsensusMinerMinPower has changed requiring update to this test") 273 // Subtests implicitly rely on ConsensusMinerMinMiners = 3 274 require.Equal(t, 4, power.ConsensusMinerMinMiners, "power.ConsensusMinerMinMiners has changed requiring update to this test") 275 276 builder := mock.NewBuilder(builtin.StoragePowerActorAddr). 277 WithCaller(builtin.SystemActorAddr, builtin.SystemActorCodeID) 278 279 t.Run("power & pledge accounted below threshold", func(t *testing.T) { 280 281 rt := builder.Build(t) 282 actor.constructAndVerify(rt) 283 284 actor.createMinerBasic(rt, owner, owner, miner1) 285 actor.createMinerBasic(rt, owner, owner, miner2) 286 287 ret := actor.currentPowerTotal(rt) 288 assert.Equal(t, big.Zero(), ret.RawBytePower) 289 assert.Equal(t, big.Zero(), ret.QualityAdjPower) 290 assert.Equal(t, big.Zero(), ret.PledgeCollateral) 291 292 // Add power for miner1 293 actor.updateClaimedPower(rt, miner1, smallPowerUnit, mul(smallPowerUnit, 2)) 294 actor.expectTotalPowerEager(rt, smallPowerUnit, mul(smallPowerUnit, 2)) 295 assert.Equal(t, big.Zero(), ret.PledgeCollateral) 296 297 // Add power and pledge for miner2 298 actor.updateClaimedPower(rt, miner2, smallPowerUnit, smallPowerUnit) 299 actor.updatePledgeTotal(rt, miner1, abi.NewTokenAmount(1e6)) 300 actor.expectTotalPowerEager(rt, mul(smallPowerUnit, 2), mul(smallPowerUnit, 3)) 301 actor.expectTotalPledgeEager(rt, abi.NewTokenAmount(1e6)) 302 303 rt.Verify() 304 305 // Verify claims in state. 306 var st power.State 307 rt.GetState(&st) 308 claim1 := actor.getClaim(rt, miner1) 309 require.Equal(t, smallPowerUnit, claim1.RawBytePower) 310 require.Equal(t, mul(smallPowerUnit, 2), claim1.QualityAdjPower) 311 312 claim2 := actor.getClaim(rt, miner2) 313 require.Equal(t, smallPowerUnit, claim2.RawBytePower) 314 require.Equal(t, smallPowerUnit, claim2.QualityAdjPower) 315 316 // Subtract power and some pledge for miner2 317 actor.updateClaimedPower(rt, miner2, smallPowerUnit.Neg(), smallPowerUnit.Neg()) 318 actor.updatePledgeTotal(rt, miner2, abi.NewTokenAmount(1e5).Neg()) 319 actor.expectTotalPowerEager(rt, mul(smallPowerUnit, 1), mul(smallPowerUnit, 2)) 320 actor.expectTotalPledgeEager(rt, abi.NewTokenAmount(9e5)) 321 322 rt.GetState(&st) 323 claim2 = actor.getClaim(rt, miner2) 324 require.Equal(t, big.Zero(), claim2.RawBytePower) 325 require.Equal(t, big.Zero(), claim2.QualityAdjPower) 326 actor.checkState(rt) 327 }) 328 329 t.Run("new miner updates MinerAboveMinPowerCount", func(t *testing.T) { 330 for _, test := range []struct { 331 version network.Version 332 proof abi.RegisteredPoStProof 333 expectedMiners int64 334 }{{ 335 version: network.Version7, 336 proof: abi.RegisteredPoStProof_StackedDrgWindow2KiBV1, 337 expectedMiners: 0, 338 }, { 339 version: network.Version7, 340 proof: abi.RegisteredPoStProof_StackedDrgWindow32GiBV1, 341 expectedMiners: 0, 342 }} { 343 rt := builder.WithNetworkVersion(test.version).Build(t) 344 actor.constructAndVerify(rt) 345 actor.windowPoStProof = test.proof 346 actor.createMinerBasic(rt, owner, owner, miner1) 347 348 st := getState(rt) 349 assert.Equal(t, test.expectedMiners, st.MinerAboveMinPowerCount) 350 } 351 }) 352 353 t.Run("power accounting crossing threshold", func(t *testing.T) { 354 rt := builder.Build(t) 355 actor.constructAndVerify(rt) 356 357 actor.createMinerBasic(rt, owner, owner, miner1) 358 actor.createMinerBasic(rt, owner, owner, miner2) 359 actor.createMinerBasic(rt, owner, owner, miner3) 360 actor.createMinerBasic(rt, owner, owner, miner4) 361 actor.createMinerBasic(rt, owner, owner, miner5) 362 363 // Use qa power 10x raw power to show it's not being used for threshold calculations. 364 actor.updateClaimedPower(rt, miner1, smallPowerUnit, mul(smallPowerUnit, 10)) 365 actor.updateClaimedPower(rt, miner2, smallPowerUnit, mul(smallPowerUnit, 10)) 366 367 actor.updateClaimedPower(rt, miner3, powerUnit, mul(powerUnit, 10)) 368 actor.updateClaimedPower(rt, miner4, powerUnit, mul(powerUnit, 10)) 369 actor.updateClaimedPower(rt, miner5, powerUnit, mul(powerUnit, 10)) 370 371 // Below threshold small miner power is counted 372 expectedTotalBelow := big.Sum(mul(smallPowerUnit, 2), mul(powerUnit, 3)) 373 actor.expectTotalPowerEager(rt, expectedTotalBelow, mul(expectedTotalBelow, 10)) 374 375 // Above threshold (power.ConsensusMinerMinMiners = 4) small miner power is ignored 376 delta := big.Sub(powerUnit, smallPowerUnit) 377 actor.updateClaimedPower(rt, miner2, delta, mul(delta, 10)) 378 expectedTotalAbove := mul(powerUnit, 4) 379 actor.expectTotalPowerEager(rt, expectedTotalAbove, mul(expectedTotalAbove, 10)) 380 381 st := getState(rt) 382 assert.Equal(t, int64(4), st.MinerAboveMinPowerCount) 383 384 // Less than 4 miners above threshold again small miner power is counted again 385 actor.updateClaimedPower(rt, miner4, delta.Neg(), mul(delta.Neg(), 10)) 386 actor.expectTotalPowerEager(rt, expectedTotalBelow, mul(expectedTotalBelow, 10)) 387 actor.checkState(rt) 388 }) 389 390 t.Run("all of one miner's power disappears when that miner dips below min power threshold", func(t *testing.T) { 391 // Setup four miners above threshold 392 rt := builder.Build(t) 393 actor.constructAndVerify(rt) 394 395 actor.createMinerBasic(rt, owner, owner, miner1) 396 actor.createMinerBasic(rt, owner, owner, miner2) 397 actor.createMinerBasic(rt, owner, owner, miner3) 398 actor.createMinerBasic(rt, owner, owner, miner4) 399 actor.createMinerBasic(rt, owner, owner, miner5) 400 401 actor.updateClaimedPower(rt, miner1, powerUnit, powerUnit) 402 actor.updateClaimedPower(rt, miner2, powerUnit, powerUnit) 403 actor.updateClaimedPower(rt, miner3, powerUnit, powerUnit) 404 actor.updateClaimedPower(rt, miner4, powerUnit, powerUnit) 405 actor.updateClaimedPower(rt, miner5, powerUnit, powerUnit) 406 407 expectedTotal := mul(powerUnit, 5) 408 actor.expectTotalPowerEager(rt, expectedTotal, expectedTotal) 409 410 // miner4 dips just below threshold 411 actor.updateClaimedPower(rt, miner4, smallPowerUnit.Neg(), smallPowerUnit.Neg()) 412 413 expectedTotal = mul(powerUnit, 4) 414 actor.expectTotalPowerEager(rt, expectedTotal, expectedTotal) 415 actor.checkState(rt) 416 }) 417 418 t.Run("power gets added when miner crosses minPower but not before", func(t *testing.T) { 419 // Setup four miners above threshold 420 rt := builder.Build(t) 421 actor.constructAndVerify(rt) 422 423 // create 4 miners that meet minimum 424 actor.createMinerBasic(rt, owner, owner, miner1) 425 actor.createMinerBasic(rt, owner, owner, miner2) 426 actor.createMinerBasic(rt, owner, owner, miner3) 427 actor.createMinerBasic(rt, owner, owner, miner4) 428 429 actor.updateClaimedPower(rt, miner1, powerUnit, powerUnit) 430 actor.updateClaimedPower(rt, miner2, powerUnit, powerUnit) 431 actor.updateClaimedPower(rt, miner3, powerUnit, powerUnit) 432 actor.updateClaimedPower(rt, miner4, powerUnit, powerUnit) 433 434 actor.expectMinersAboveMinPower(rt, 4) 435 expectedTotal := mul(powerUnit, 4) 436 actor.expectTotalPowerEager(rt, expectedTotal, expectedTotal) 437 438 actor.createMinerBasic(rt, owner, owner, miner5) 439 belowLimitUnit := big.Div(powerUnit, big.NewInt(2)) 440 441 // below limit actors power is not added 442 actor.updateClaimedPower(rt, miner5, belowLimitUnit, belowLimitUnit) 443 actor.expectMinersAboveMinPower(rt, 4) 444 actor.expectTotalPowerEager(rt, expectedTotal, expectedTotal) 445 446 // just below limit 447 delta := big.Subtract(powerUnit, belowLimitUnit, big.NewInt(1)) 448 actor.updateClaimedPower(rt, miner5, delta, delta) 449 actor.expectMinersAboveMinPower(rt, 4) 450 actor.expectTotalPowerEager(rt, expectedTotal, expectedTotal) 451 452 // at limit power is added 453 actor.updateClaimedPower(rt, miner5, big.NewInt(1), big.NewInt(1)) 454 actor.expectMinersAboveMinPower(rt, 5) 455 newExpectedTotal := big.Add(expectedTotal, powerUnit) 456 actor.expectTotalPowerEager(rt, newExpectedTotal, newExpectedTotal) 457 actor.checkState(rt) 458 }) 459 460 t.Run("threshold only depends on raw power, not qa power", func(t *testing.T) { 461 rt := builder.Build(t) 462 actor.constructAndVerify(rt) 463 464 actor.createMinerBasic(rt, owner, owner, miner1) 465 actor.createMinerBasic(rt, owner, owner, miner2) 466 actor.createMinerBasic(rt, owner, owner, miner3) 467 actor.createMinerBasic(rt, owner, owner, miner4) 468 469 actor.updateClaimedPower(rt, miner1, div(powerUnit, 2), powerUnit) 470 actor.updateClaimedPower(rt, miner2, div(powerUnit, 2), powerUnit) 471 actor.updateClaimedPower(rt, miner3, div(powerUnit, 2), powerUnit) 472 st := getState(rt) 473 assert.Equal(t, int64(0), st.MinerAboveMinPowerCount) 474 475 actor.updateClaimedPower(rt, miner1, div(powerUnit, 2), powerUnit) 476 actor.updateClaimedPower(rt, miner2, div(powerUnit, 2), powerUnit) 477 actor.updateClaimedPower(rt, miner3, div(powerUnit, 2), powerUnit) 478 st = getState(rt) 479 assert.Equal(t, int64(3), st.MinerAboveMinPowerCount) 480 actor.checkState(rt) 481 }) 482 483 t.Run("qa power is above threshold before and after update", func(t *testing.T) { 484 rt := builder.Build(t) 485 actor.constructAndVerify(rt) 486 487 // update claim so qa is above threshold 488 actor.createMinerBasic(rt, owner, owner, miner1) 489 actor.updateClaimedPower(rt, miner1, mul(powerUnit, 3), mul(powerUnit, 3)) 490 st := getState(rt) 491 require.EqualValues(t, mul(powerUnit, 3), st.TotalQualityAdjPower) 492 require.EqualValues(t, mul(powerUnit, 3), st.TotalRawBytePower) 493 494 // update such that it's above threshold again 495 actor.updateClaimedPower(rt, miner1, powerUnit, powerUnit) 496 st = getState(rt) 497 require.EqualValues(t, mul(powerUnit, 4), st.TotalQualityAdjPower) 498 require.EqualValues(t, mul(powerUnit, 4), st.TotalRawBytePower) 499 actor.checkState(rt) 500 }) 501 502 t.Run("claimed power is externally available", func(t *testing.T) { 503 rt := builder.Build(t) 504 actor.constructAndVerify(rt) 505 506 actor.createMinerBasic(rt, owner, owner, miner1) 507 actor.updateClaimedPower(rt, miner1, powerUnit, powerUnit) 508 st := getState(rt) 509 510 claim, found, err := st.GetClaim(rt.AdtStore(), miner1) 511 require.NoError(t, err) 512 require.True(t, found) 513 514 assert.Equal(t, powerUnit, claim.RawBytePower) 515 assert.Equal(t, powerUnit, claim.QualityAdjPower) 516 actor.checkState(rt) 517 }) 518 } 519 520 func TestUpdatePledgeTotal(t *testing.T) { 521 // most coverage of update pledge total is in accounting test above 522 523 actor := newHarness(t) 524 owner := tutil.NewIDAddr(t, 101) 525 miner := tutil.NewIDAddr(t, 111) 526 builder := mock.NewBuilder(builtin.StoragePowerActorAddr). 527 WithCaller(builtin.SystemActorAddr, builtin.SystemActorCodeID) 528 529 t.Run("update pledge total aborts if miner has no claim", func(t *testing.T) { 530 rt := builder.Build(t) 531 actor.constructAndVerify(rt) 532 actor.createMinerBasic(rt, owner, owner, miner) 533 534 // explicitly delete miner claim 535 actor.deleteClaim(rt, miner) 536 537 rt.ExpectAbortContainsMessage(exitcode.ErrForbidden, "unknown miner", func() { 538 actor.updatePledgeTotal(rt, miner, abi.NewTokenAmount(1e6)) 539 }) 540 }) 541 } 542 543 func TestCron(t *testing.T) { 544 actor := newHarness(t) 545 miner1 := tutil.NewIDAddr(t, 101) 546 miner2 := tutil.NewIDAddr(t, 102) 547 owner := tutil.NewIDAddr(t, 103) 548 549 builder := mock.NewBuilder(builtin.StoragePowerActorAddr).WithCaller(builtin.SystemActorAddr, builtin.SystemActorCodeID) 550 551 t.Run("calls reward actor", func(t *testing.T) { 552 rt := builder.Build(t) 553 actor.constructAndVerify(rt) 554 555 expectedPower := big.NewInt(0) 556 rt.SetEpoch(1) 557 rt.ExpectValidateCallerAddr(builtin.CronActorAddr) 558 rt.ExpectSend(builtin.RewardActorAddr, builtin.MethodsReward.UpdateNetworkKPI, &expectedPower, abi.NewTokenAmount(0), nil, 0) 559 rt.SetCaller(builtin.CronActorAddr, builtin.CronActorCodeID) 560 561 rt.ExpectBatchVerifySeals(nil, nil, nil) 562 rt.Call(actor.Actor.OnEpochTickEnd, nil) 563 rt.Verify() 564 actor.checkState(rt) 565 }) 566 567 t.Run("test amount sent to reward actor and state change", func(t *testing.T) { 568 powerUnit, err := builtin.ConsensusMinerMinPower(abi.RegisteredPoStProof_StackedDrgWindow2KiBV1) 569 require.NoError(t, err) 570 571 miner3 := tutil.NewIDAddr(t, 103) 572 miner4 := tutil.NewIDAddr(t, 104) 573 574 rt := builder.Build(t) 575 actor.constructAndVerify(rt) 576 577 actor.createMinerBasic(rt, owner, owner, miner1) 578 actor.createMinerBasic(rt, owner, owner, miner2) 579 actor.createMinerBasic(rt, owner, owner, miner3) 580 actor.createMinerBasic(rt, owner, owner, miner4) 581 actor.updateClaimedPower(rt, miner1, powerUnit, powerUnit) 582 actor.updateClaimedPower(rt, miner1, powerUnit, powerUnit) 583 actor.updateClaimedPower(rt, miner1, powerUnit, powerUnit) 584 actor.updateClaimedPower(rt, miner1, powerUnit, powerUnit) 585 586 expectedPower := big.Mul(big.NewInt(4), powerUnit) 587 588 delta := abi.NewTokenAmount(1) 589 actor.updatePledgeTotal(rt, miner1, delta) 590 actor.onEpochTickEnd(rt, 0, expectedPower, nil, nil) 591 592 st := getState(rt) 593 require.EqualValues(t, delta, st.ThisEpochPledgeCollateral) 594 require.EqualValues(t, expectedPower, st.ThisEpochQualityAdjPower) 595 require.EqualValues(t, expectedPower, st.ThisEpochRawBytePower) 596 actor.checkState(rt) 597 }) 598 599 t.Run("event scheduled in null round called next round", func(t *testing.T) { 600 rt := builder.Build(t) 601 actor.constructAndVerify(rt) 602 actor.createMinerBasic(rt, owner, owner, miner1) 603 actor.createMinerBasic(rt, owner, owner, miner2) 604 605 // 0 - genesis 606 // 1 - block - registers events 607 // 2 - null - has event 608 // 3 - null 609 // 4 - block - has event 610 611 rt.SetEpoch(1) 612 actor.enrollCronEvent(rt, miner1, 2, []byte{0x1, 0x3}) 613 actor.enrollCronEvent(rt, miner2, 4, []byte{0x2, 0x3}) 614 615 expectedRawBytePower := big.NewInt(0) 616 rt.SetEpoch(4) 617 rt.ExpectValidateCallerAddr(builtin.CronActorAddr) 618 rt.ExpectSend(miner1, builtin.MethodsMiner.OnDeferredCronEvent, builtin.CBORBytes([]byte{0x1, 0x3}), big.Zero(), nil, exitcode.Ok) 619 rt.ExpectSend(miner2, builtin.MethodsMiner.OnDeferredCronEvent, builtin.CBORBytes([]byte{0x2, 0x3}), big.Zero(), nil, exitcode.Ok) 620 rt.ExpectSend(builtin.RewardActorAddr, builtin.MethodsReward.UpdateNetworkKPI, &expectedRawBytePower, big.Zero(), nil, exitcode.Ok) 621 rt.SetCaller(builtin.CronActorAddr, builtin.CronActorCodeID) 622 rt.ExpectBatchVerifySeals(nil, nil, nil) 623 624 rt.Call(actor.Actor.OnEpochTickEnd, nil) 625 rt.Verify() 626 actor.checkState(rt) 627 }) 628 629 t.Run("event scheduled in past called next round", func(t *testing.T) { 630 rt := builder.Build(t) 631 actor.constructAndVerify(rt) 632 actor.createMinerBasic(rt, owner, owner, miner1) 633 634 // run cron once to put it in a clean state at epoch 4 635 rt.SetEpoch(4) 636 expectedRawBytePower := big.NewInt(0) 637 rt.ExpectValidateCallerAddr(builtin.CronActorAddr) 638 rt.ExpectSend(builtin.RewardActorAddr, builtin.MethodsReward.UpdateNetworkKPI, &expectedRawBytePower, big.Zero(), nil, exitcode.Ok) 639 rt.SetCaller(builtin.CronActorAddr, builtin.CronActorCodeID) 640 641 rt.ExpectBatchVerifySeals(nil, nil, nil) 642 643 rt.Call(actor.Actor.OnEpochTickEnd, nil) 644 rt.Verify() 645 646 // enroll a cron task at epoch 2 (which is in the past) 647 actor.enrollCronEvent(rt, miner1, 2, []byte{0x1, 0x3}) 648 649 // run cron again in the future 650 rt.SetEpoch(6) 651 rt.ExpectValidateCallerAddr(builtin.CronActorAddr) 652 rt.ExpectSend(miner1, builtin.MethodsMiner.OnDeferredCronEvent, builtin.CBORBytes([]byte{0x1, 0x3}), big.Zero(), nil, exitcode.Ok) 653 rt.ExpectSend(builtin.RewardActorAddr, builtin.MethodsReward.UpdateNetworkKPI, &expectedRawBytePower, big.Zero(), nil, exitcode.Ok) 654 rt.SetCaller(builtin.CronActorAddr, builtin.CronActorCodeID) 655 rt.ExpectBatchVerifySeals(nil, nil, nil) 656 657 rt.Call(actor.Actor.OnEpochTickEnd, nil) 658 rt.Verify() 659 660 // assert used cron events are cleaned up 661 st := getState(rt) 662 663 mmap, err := adt.AsMultimap(rt.AdtStore(), st.CronEventQueue, power.CronQueueHamtBitwidth, power.CronQueueAmtBitwidth) 664 require.NoError(t, err) 665 666 var ev power.CronEvent 667 err = mmap.ForEach(abi.IntKey(int64(2)), &ev, func(i int64) error { 668 t.Errorf("Unexpected bitfield at epoch %d", i) 669 return nil 670 }) 671 require.NoError(t, err) 672 actor.checkState(rt) 673 }) 674 675 t.Run("fails to enroll if epoch is negative", func(t *testing.T) { 676 rt := builder.Build(t) 677 actor.constructAndVerify(rt) 678 679 // enroll a cron task at epoch 2 (which is in the past) 680 rt.ExpectAbortContainsMessage(exitcode.ErrIllegalArgument, "epoch -2 cannot be less than zero", func() { 681 actor.enrollCronEvent(rt, miner1, -2, []byte{0x1, 0x3}) 682 }) 683 }) 684 685 t.Run("skips invocation if miner has no claim", func(t *testing.T) { 686 rt := builder.Build(t) 687 actor.constructAndVerify(rt) 688 689 rt.SetEpoch(1) 690 actor.createMinerBasic(rt, owner, owner, miner1) 691 actor.createMinerBasic(rt, owner, owner, miner2) 692 693 actor.enrollCronEvent(rt, miner1, 2, []byte{}) 694 actor.enrollCronEvent(rt, miner2, 2, []byte{}) 695 696 // explicitly delete miner 1's claim 697 actor.deleteClaim(rt, miner1) 698 699 rt.SetEpoch(2) 700 rt.ExpectValidateCallerAddr(builtin.CronActorAddr) 701 702 // process batch verifies first 703 rt.ExpectBatchVerifySeals(nil, nil, nil) 704 705 // only expect second deferred cron event call 706 rt.ExpectSend(miner2, builtin.MethodsMiner.OnDeferredCronEvent, builtin.CBORBytes(nil), big.Zero(), nil, exitcode.Ok) 707 708 // Reward actor still invoked 709 expectedPower := big.NewInt(0) 710 rt.ExpectSend(builtin.RewardActorAddr, builtin.MethodsReward.UpdateNetworkKPI, &expectedPower, big.Zero(), nil, exitcode.Ok) 711 rt.SetCaller(builtin.CronActorAddr, builtin.CronActorCodeID) 712 rt.Call(actor.Actor.OnEpochTickEnd, nil) 713 rt.Verify() 714 715 // expect cron skip was logged 716 rt.ExpectLogsContain("skipping cron event for unknown miner t0101") 717 actor.checkState(rt) 718 }) 719 720 t.Run("handles failed call", func(t *testing.T) { 721 rt := builder.Build(t) 722 actor.constructAndVerify(rt) 723 724 rt.SetEpoch(1) 725 actor.createMinerBasic(rt, owner, owner, miner1) 726 actor.createMinerBasic(rt, owner, owner, miner2) 727 728 actor.enrollCronEvent(rt, miner1, 2, []byte{}) 729 actor.enrollCronEvent(rt, miner2, 2, []byte{}) 730 731 rawPow, err := builtin.ConsensusMinerMinPower(abi.RegisteredPoStProof_StackedDrgWindow32GiBV1) 732 require.NoError(t, err) 733 734 qaPow := rawPow 735 actor.updateClaimedPower(rt, miner1, rawPow, qaPow) 736 actor.expectTotalPowerEager(rt, rawPow, qaPow) 737 actor.expectMinersAboveMinPower(rt, 1) 738 739 expectedPower := big.NewInt(0) 740 rt.SetEpoch(2) 741 rt.ExpectValidateCallerAddr(builtin.CronActorAddr) 742 743 // process batch verifies first 744 rt.ExpectBatchVerifySeals(nil, nil, nil) 745 746 // First send fails 747 rt.ExpectSend(miner1, builtin.MethodsMiner.OnDeferredCronEvent, builtin.CBORBytes(nil), big.Zero(), nil, exitcode.ErrIllegalState) 748 749 // Subsequent one still invoked 750 rt.ExpectSend(miner2, builtin.MethodsMiner.OnDeferredCronEvent, builtin.CBORBytes(nil), big.Zero(), nil, exitcode.Ok) 751 // Reward actor still invoked 752 rt.ExpectSend(builtin.RewardActorAddr, builtin.MethodsReward.UpdateNetworkKPI, &expectedPower, big.Zero(), nil, exitcode.Ok) 753 rt.SetCaller(builtin.CronActorAddr, builtin.CronActorCodeID) 754 rt.Call(actor.Actor.OnEpochTickEnd, nil) 755 rt.Verify() 756 757 // expect cron failure was logged 758 rt.ExpectLogsContain("OnDeferredCronEvent failed for miner") 759 760 // expect power stats to be decremented due to claim deletion 761 actor.expectTotalPowerEager(rt, big.Zero(), big.Zero()) 762 actor.expectMinersAboveMinPower(rt, 0) 763 764 // miner's claim is removed 765 st := getState(rt) 766 _, found, err := st.GetClaim(rt.AdtStore(), miner1) 767 require.NoError(t, err) 768 assert.False(t, found) 769 770 // miner count has been reduced to 1 771 assert.Equal(t, int64(1), st.MinerCount) 772 773 // Next epoch, only the reward actor is invoked 774 rt.SetEpoch(3) 775 rt.ExpectValidateCallerAddr(builtin.CronActorAddr) 776 rt.ExpectSend(builtin.RewardActorAddr, builtin.MethodsReward.UpdateNetworkKPI, &expectedPower, big.Zero(), nil, exitcode.Ok) 777 rt.SetCaller(builtin.CronActorAddr, builtin.CronActorCodeID) 778 rt.ExpectBatchVerifySeals(nil, nil, nil) 779 780 rt.Call(actor.Actor.OnEpochTickEnd, nil) 781 rt.Verify() 782 actor.checkState(rt) 783 }) 784 } 785 786 func TestSubmitPoRepForBulkVerify(t *testing.T) { 787 actor := newHarness(t) 788 miner := tutil.NewIDAddr(t, 101) 789 owner := tutil.NewIDAddr(t, 101) 790 builder := mock.NewBuilder(builtin.StoragePowerActorAddr).WithCaller(builtin.SystemActorAddr, builtin.SystemActorCodeID) 791 792 t.Run("registers porep and charges gas", func(t *testing.T) { 793 rt := builder.Build(t) 794 actor.constructAndVerify(rt) 795 actor.createMinerBasic(rt, owner, owner, miner) 796 commR := tutil.MakeCID("commR", &mineract.SealedCIDPrefix) 797 commD := tutil.MakeCID("commD", &market.PieceCIDPrefix) 798 sealInfo := &proof.SealVerifyInfo{ 799 SealProof: actor.sealProof, 800 SealedCID: commR, 801 UnsealedCID: commD, 802 } 803 actor.submitPoRepForBulkVerify(rt, miner, sealInfo) 804 rt.ExpectGasCharged(power.GasOnSubmitVerifySeal) 805 st := getState(rt) 806 store := rt.AdtStore() 807 require.NotNil(t, st.ProofValidationBatch) 808 mmap, err := adt.AsMultimap(store, *st.ProofValidationBatch, builtin.DefaultHamtBitwidth, power.ProofValidationBatchAmtBitwidth) 809 require.NoError(t, err) 810 arr, found, err := mmap.Get(abi.AddrKey(miner)) 811 require.NoError(t, err) 812 require.True(t, found) 813 assert.Equal(t, uint64(1), arr.Length()) 814 var storedSealInfo proof.SealVerifyInfo 815 found, err = arr.Get(0, &storedSealInfo) 816 require.NoError(t, err) 817 require.True(t, found) 818 assert.Equal(t, commR, storedSealInfo.SealedCID) 819 actor.checkState(rt) 820 }) 821 822 t.Run("aborts when too many poreps", func(t *testing.T) { 823 rt := builder.Build(t) 824 actor.constructAndVerify(rt) 825 actor.createMinerBasic(rt, owner, owner, miner) 826 827 sealInfo := func(i int) *proof.SealVerifyInfo { 828 var sealInfo proof.SealVerifyInfo 829 sealInfo.SealedCID = tutil.MakeCID(fmt.Sprintf("commR-%d", i), &mineract.SealedCIDPrefix) 830 sealInfo.UnsealedCID = tutil.MakeCID(fmt.Sprintf("commD-%d", i), &market.PieceCIDPrefix) 831 return &sealInfo 832 } 833 834 // Adding MaxMinerProveCommitsPerEpoch works without error 835 for i := 0; i < power.MaxMinerProveCommitsPerEpoch; i++ { 836 actor.submitPoRepForBulkVerify(rt, miner, sealInfo(i)) 837 } 838 839 rt.ExpectAbort(power.ErrTooManyProveCommits, func() { 840 actor.submitPoRepForBulkVerify(rt, miner, sealInfo(power.MaxMinerProveCommitsPerEpoch)) 841 }) 842 843 // Gas only charged for successful submissions 844 rt.ExpectGasCharged(power.GasOnSubmitVerifySeal * power.MaxMinerProveCommitsPerEpoch) 845 }) 846 847 t.Run("aborts when miner has no claim", func(t *testing.T) { 848 rt := builder.Build(t) 849 actor.constructAndVerify(rt) 850 actor.createMinerBasic(rt, owner, owner, miner) 851 commR := tutil.MakeCID("commR", &mineract.SealedCIDPrefix) 852 commD := tutil.MakeCID("commD", &market.PieceCIDPrefix) 853 sealInfo := &proof.SealVerifyInfo{ 854 SealedCID: commR, 855 UnsealedCID: commD, 856 } 857 858 // delete miner 859 actor.deleteClaim(rt, miner) 860 861 rt.ExpectAbortContainsMessage(exitcode.ErrForbidden, "unknown miner", func() { 862 actor.submitPoRepForBulkVerify(rt, miner, sealInfo) 863 }) 864 }) 865 } 866 867 func TestCronBatchProofVerifies(t *testing.T) { 868 sealInfo := func(i int) *proof.SealVerifyInfo { 869 var sealInfo proof.SealVerifyInfo 870 sealInfo.SealedCID = tutil.MakeCID(fmt.Sprintf("commR-%d", i), &mineract.SealedCIDPrefix) 871 sealInfo.UnsealedCID = tutil.MakeCID(fmt.Sprintf("commD-%d", i), &market.PieceCIDPrefix) 872 sealInfo.SectorID = abi.SectorID{Number: abi.SectorNumber(i)} 873 return &sealInfo 874 } 875 876 miner1 := tutil.NewIDAddr(t, 101) 877 owner := tutil.NewIDAddr(t, 102) 878 info := sealInfo(0) 879 info1 := sealInfo(1) 880 info2 := sealInfo(2) 881 info3 := sealInfo(3) 882 info4 := sealInfo(101) 883 info5 := sealInfo(200) 884 info6 := sealInfo(201) 885 info7 := sealInfo(300) 886 info8 := sealInfo(301) 887 888 t.Run("success with one miner and one confirmed sector", func(t *testing.T) { 889 rt, ac := basicPowerSetup(t) 890 ac.createMinerBasic(rt, owner, owner, miner1) 891 892 ac.submitPoRepForBulkVerify(rt, miner1, info) 893 894 infos := map[addr.Address][]proof.SealVerifyInfo{miner1: {*info}} 895 cs := []confirmedSectorSend{{miner1, []abi.SectorNumber{info.Number}}} 896 897 ac.onEpochTickEnd(rt, 0, big.Zero(), cs, infos) 898 ac.checkState(rt) 899 }) 900 901 t.Run("success with one miner and multiple confirmed sectors", func(t *testing.T) { 902 rt, ac := basicPowerSetup(t) 903 ac.createMinerBasic(rt, owner, owner, miner1) 904 905 ac.submitPoRepForBulkVerify(rt, miner1, info1) 906 ac.submitPoRepForBulkVerify(rt, miner1, info2) 907 ac.submitPoRepForBulkVerify(rt, miner1, info3) 908 909 infos := map[addr.Address][]proof.SealVerifyInfo{miner1: {*info1, *info2, *info3}} 910 cs := []confirmedSectorSend{{miner1, []abi.SectorNumber{info1.Number, info2.Number, info3.Number}}} 911 912 ac.onEpochTickEnd(rt, 0, big.Zero(), cs, infos) 913 ac.checkState(rt) 914 }) 915 916 t.Run("duplicate sector numbers are ignored for a miner", func(t *testing.T) { 917 rt, ac := basicPowerSetup(t) 918 ac.createMinerBasic(rt, owner, owner, miner1) 919 920 ac.submitPoRepForBulkVerify(rt, miner1, info1) 921 ac.submitPoRepForBulkVerify(rt, miner1, info1) 922 ac.submitPoRepForBulkVerify(rt, miner1, info2) 923 924 // duplicates will be sent to the batch verify call 925 infos := map[addr.Address][]proof.SealVerifyInfo{miner1: {*info1, *info1, *info2}} 926 927 // however, duplicates will not be sent to the miner as confirmed 928 cs := []confirmedSectorSend{{miner1, []abi.SectorNumber{info1.Number, info2.Number}}} 929 930 ac.onEpochTickEnd(rt, 0, big.Zero(), cs, infos) 931 ac.checkState(rt) 932 }) 933 934 t.Run("skips verify if miner has no claim", func(t *testing.T) { 935 rt, ac := basicPowerSetup(t) 936 ac.createMinerBasic(rt, owner, owner, miner1) 937 938 ac.submitPoRepForBulkVerify(rt, miner1, info1) 939 940 // now explicitly delete miner's claim 941 ac.deleteClaim(rt, miner1) 942 943 // all infos will be skipped 944 infos := map[addr.Address][]proof.SealVerifyInfo{} 945 946 // nothing will be sent to miner 947 cs := []confirmedSectorSend{} 948 949 ac.onEpochTickEnd(rt, 0, big.Zero(), cs, infos) 950 951 // expect cron failure was logged 952 rt.ExpectLogsContain("skipping batch verifies for unknown miner t0101") 953 ac.checkState(rt) 954 }) 955 956 t.Run("success with multiple miners and multiple confirmed sectors and assert expected power", func(t *testing.T) { 957 miner2 := tutil.NewIDAddr(t, 102) 958 miner3 := tutil.NewIDAddr(t, 103) 959 miner4 := tutil.NewIDAddr(t, 104) 960 961 rt, ac := basicPowerSetup(t) 962 ac.createMinerBasic(rt, owner, owner, miner1) 963 ac.createMinerBasic(rt, owner, owner, miner2) 964 ac.createMinerBasic(rt, owner, owner, miner3) 965 ac.createMinerBasic(rt, owner, owner, miner4) 966 967 ac.submitPoRepForBulkVerify(rt, miner1, info1) 968 ac.submitPoRepForBulkVerify(rt, miner1, info2) 969 970 ac.submitPoRepForBulkVerify(rt, miner2, info3) 971 ac.submitPoRepForBulkVerify(rt, miner2, info4) 972 973 ac.submitPoRepForBulkVerify(rt, miner3, info5) 974 ac.submitPoRepForBulkVerify(rt, miner3, info6) 975 976 ac.submitPoRepForBulkVerify(rt, miner4, info7) 977 ac.submitPoRepForBulkVerify(rt, miner4, info8) 978 979 // TODO Because read order of keys in a multi-map is not as per insertion order, 980 // we have to move around the expected sends 981 cs := []confirmedSectorSend{{miner1, []abi.SectorNumber{info1.Number, info2.Number}}, 982 {miner3, []abi.SectorNumber{info5.Number, info6.Number}}, 983 {miner4, []abi.SectorNumber{info7.Number, info8.Number}}, 984 {miner2, []abi.SectorNumber{info3.Number, info4.Number}}} 985 986 infos := map[addr.Address][]proof.SealVerifyInfo{miner1: {*info1, *info2}, 987 miner2: {*info3, *info4}, 988 miner3: {*info5, *info6}, 989 miner4: {*info7, *info8}} 990 991 ac.onEpochTickEnd(rt, 0, big.Zero(), cs, infos) 992 ac.checkState(rt) 993 }) 994 995 t.Run("success when no confirmed sector", func(t *testing.T) { 996 rt, ac := basicPowerSetup(t) 997 ac.onEpochTickEnd(rt, 0, big.Zero(), nil, nil) 998 ac.checkState(rt) 999 }) 1000 1001 t.Run("verification for one sector fails but others succeeds for a miner", func(t *testing.T) { 1002 rt, ac := basicPowerSetup(t) 1003 ac.createMinerBasic(rt, owner, owner, miner1) 1004 1005 ac.submitPoRepForBulkVerify(rt, miner1, info1) 1006 ac.submitPoRepForBulkVerify(rt, miner1, info2) 1007 ac.submitPoRepForBulkVerify(rt, miner1, info3) 1008 1009 infos := map[addr.Address][]proof.SealVerifyInfo{miner1: {*info1, *info2, *info3}} 1010 1011 res := map[addr.Address][]bool{ 1012 miner1: {true, false, true}, 1013 } 1014 1015 // send will only be for the first and third sector as the middle sector will fail verification 1016 cs := []confirmedSectorSend{{miner1, []abi.SectorNumber{info1.Number, info3.Number}}} 1017 1018 // expect sends for confirmed sectors 1019 for _, cs := range cs { 1020 param := &builtin.ConfirmSectorProofsParams{Sectors: cs.sectorNums} 1021 rt.ExpectSend(cs.miner, builtin.MethodsMiner.ConfirmSectorProofsValid, param, abi.NewTokenAmount(0), nil, 0) 1022 } 1023 1024 rt.ExpectBatchVerifySeals(infos, res, nil) 1025 power := big.Zero() 1026 //expect power sends to reward actor 1027 rt.ExpectSend(builtin.RewardActorAddr, builtin.MethodsReward.UpdateNetworkKPI, &power, abi.NewTokenAmount(0), nil, 0) 1028 rt.ExpectValidateCallerAddr(builtin.CronActorAddr) 1029 1030 rt.SetEpoch(0) 1031 rt.SetCaller(builtin.CronActorAddr, builtin.CronActorCodeID) 1032 1033 rt.Call(ac.OnEpochTickEnd, nil) 1034 rt.Verify() 1035 ac.checkState(rt) 1036 }) 1037 1038 t.Run("fails if batch verify seals fails", func(t *testing.T) { 1039 rt, ac := basicPowerSetup(t) 1040 ac.createMinerBasic(rt, owner, owner, miner1) 1041 1042 ac.submitPoRepForBulkVerify(rt, miner1, info1) 1043 ac.submitPoRepForBulkVerify(rt, miner1, info2) 1044 ac.submitPoRepForBulkVerify(rt, miner1, info3) 1045 1046 infos := map[addr.Address][]proof.SealVerifyInfo{miner1: {*info1, *info2, *info3}} 1047 1048 rt.ExpectBatchVerifySeals(infos, batchVerifyDefaultOutput(infos), fmt.Errorf("fail")) 1049 rt.ExpectValidateCallerAddr(builtin.CronActorAddr) 1050 1051 rt.SetEpoch(abi.ChainEpoch(0)) 1052 rt.SetCaller(builtin.CronActorAddr, builtin.CronActorCodeID) 1053 1054 rt.ExpectAbort(exitcode.ErrIllegalState, func() { 1055 rt.Call(ac.Actor.OnEpochTickEnd, nil) 1056 }) 1057 rt.Verify() 1058 }) 1059 } 1060 1061 // 1062 // Misc. Utility Functions 1063 // 1064 1065 type key string 1066 1067 func asKey(in string) abi.Keyer { 1068 return key(in) 1069 } 1070 1071 func verifyEmptyMap(t testing.TB, rt *mock.Runtime, cid cid.Cid) { 1072 mapChecked, err := adt.AsMap(adt.AsStore(rt), cid, builtin.DefaultHamtBitwidth) 1073 assert.NoError(t, err) 1074 keys, err := mapChecked.CollectKeys() 1075 require.NoError(t, err) 1076 assert.Empty(t, keys) 1077 } 1078 1079 type spActorHarness struct { 1080 power.Actor 1081 t *testing.T 1082 minerSeq int 1083 sealProof abi.RegisteredSealProof 1084 windowPoStProof abi.RegisteredPoStProof 1085 } 1086 1087 func newHarness(t *testing.T) *spActorHarness { 1088 return &spActorHarness{ 1089 Actor: power.Actor{}, 1090 t: t, 1091 sealProof: abi.RegisteredSealProof_StackedDrg32GiBV1_1, 1092 windowPoStProof: abi.RegisteredPoStProof_StackedDrgWindow32GiBV1, 1093 } 1094 } 1095 1096 func (h *spActorHarness) constructAndVerify(rt *mock.Runtime) { 1097 rt.ExpectValidateCallerAddr(builtin.SystemActorAddr) 1098 ret := rt.Call(h.Actor.Constructor, nil) 1099 assert.Nil(h.t, ret) 1100 rt.Verify() 1101 1102 var st power.State 1103 1104 rt.GetState(&st) 1105 assert.Equal(h.t, abi.NewStoragePower(0), st.TotalRawBytePower) 1106 assert.Equal(h.t, abi.NewStoragePower(0), st.TotalBytesCommitted) 1107 assert.Equal(h.t, abi.NewStoragePower(0), st.TotalQualityAdjPower) 1108 assert.Equal(h.t, abi.NewStoragePower(0), st.TotalQABytesCommitted) 1109 assert.Equal(h.t, abi.NewTokenAmount(0), st.TotalPledgeCollateral) 1110 assert.Equal(h.t, abi.NewStoragePower(0), st.ThisEpochRawBytePower) 1111 assert.Equal(h.t, abi.NewStoragePower(0), st.ThisEpochQualityAdjPower) 1112 assert.Equal(h.t, abi.NewTokenAmount(0), st.ThisEpochPledgeCollateral) 1113 assert.Equal(h.t, abi.ChainEpoch(0), st.FirstCronEpoch) 1114 assert.Equal(h.t, int64(0), st.MinerCount) 1115 assert.Equal(h.t, int64(0), st.MinerAboveMinPowerCount) 1116 1117 verifyEmptyMap(h.t, rt, st.Claims) 1118 verifyEmptyMap(h.t, rt, st.CronEventQueue) 1119 } 1120 1121 type confirmedSectorSend struct { 1122 miner addr.Address 1123 sectorNums []abi.SectorNumber 1124 } 1125 1126 func (h *spActorHarness) onEpochTickEnd(rt *mock.Runtime, currEpoch abi.ChainEpoch, expectedRawPower abi.StoragePower, 1127 confirmedSectors []confirmedSectorSend, infos map[addr.Address][]proof.SealVerifyInfo) { 1128 1129 // expect sends for confirmed sectors 1130 for _, cs := range confirmedSectors { 1131 param := &builtin.ConfirmSectorProofsParams{Sectors: cs.sectorNums} 1132 rt.ExpectSend(cs.miner, builtin.MethodsMiner.ConfirmSectorProofsValid, param, abi.NewTokenAmount(0), nil, 0) 1133 } 1134 1135 rt.ExpectBatchVerifySeals(infos, batchVerifyDefaultOutput(infos), nil) 1136 //expect power sends to reward actor 1137 rt.ExpectSend(builtin.RewardActorAddr, builtin.MethodsReward.UpdateNetworkKPI, &expectedRawPower, abi.NewTokenAmount(0), nil, 0) 1138 rt.ExpectValidateCallerAddr(builtin.CronActorAddr) 1139 1140 rt.SetEpoch(currEpoch) 1141 rt.SetCaller(builtin.CronActorAddr, builtin.CronActorCodeID) 1142 1143 rt.Call(h.Actor.OnEpochTickEnd, nil) 1144 rt.Verify() 1145 1146 st := getState(rt) 1147 require.Nil(h.t, st.ProofValidationBatch) 1148 } 1149 1150 func (h *spActorHarness) createMiner(rt *mock.Runtime, owner, worker, miner, robust addr.Address, peer abi.PeerID, 1151 multiaddrs []abi.Multiaddrs, windowPoStProofType abi.RegisteredPoStProof, value abi.TokenAmount) { 1152 1153 st := getState(rt) 1154 prevMinerCount := st.MinerCount 1155 1156 createMinerParams := &power.CreateMinerParams{ 1157 Owner: owner, 1158 Worker: worker, 1159 WindowPoStProofType: windowPoStProofType, 1160 Peer: peer, 1161 Multiaddrs: multiaddrs, 1162 } 1163 1164 // owner send CreateMiner to Actor 1165 rt.SetCaller(owner, builtin.AccountActorCodeID) 1166 rt.SetReceived(value) 1167 rt.SetBalance(value) 1168 rt.ExpectValidateCallerType(builtin.AccountActorCodeID, builtin.MultisigActorCodeID) 1169 1170 createMinerRet := &power.CreateMinerReturn{ 1171 IDAddress: miner, // miner actor id address 1172 RobustAddress: robust, // should be long miner actor address 1173 } 1174 1175 msgParams := &initact.ExecParams{ 1176 CodeCID: builtin.StorageMinerActorCodeID, 1177 ConstructorParams: initCreateMinerBytes(h.t, owner, worker, peer, multiaddrs, windowPoStProofType), 1178 } 1179 rt.ExpectSend(builtin.InitActorAddr, builtin.MethodsInit.Exec, msgParams, value, createMinerRet, 0) 1180 rt.Call(h.Actor.CreateMiner, createMinerParams) 1181 rt.Verify() 1182 1183 cl := h.getClaim(rt, miner) 1184 require.True(h.t, cl.RawBytePower.IsZero()) 1185 require.True(h.t, cl.QualityAdjPower.IsZero()) 1186 require.EqualValues(h.t, prevMinerCount+1, getState(rt).MinerCount) 1187 1188 } 1189 1190 func (h *spActorHarness) getClaim(rt *mock.Runtime, a addr.Address) *power.Claim { 1191 var st power.State 1192 rt.GetState(&st) 1193 1194 claims, err := adt.AsMap(adt.AsStore(rt), st.Claims, builtin.DefaultHamtBitwidth) 1195 require.NoError(h.t, err) 1196 1197 var out power.Claim 1198 found, err := claims.Get(abi.AddrKey(a), &out) 1199 require.NoError(h.t, err) 1200 require.True(h.t, found) 1201 1202 return &out 1203 } 1204 1205 func (h *spActorHarness) deleteClaim(rt *mock.Runtime, a addr.Address) { 1206 st := getState(rt) 1207 claims, err := adt.AsMap(adt.AsStore(rt), st.Claims, builtin.DefaultHamtBitwidth) 1208 require.NoError(h.t, err) 1209 err = claims.Delete(abi.AddrKey(a)) 1210 require.NoError(h.t, err) 1211 st.Claims, err = claims.Root() 1212 require.NoError(h.t, err) 1213 rt.ReplaceState(st) 1214 } 1215 1216 func (h *spActorHarness) getEnrolledCronTicks(rt *mock.Runtime, epoch abi.ChainEpoch) []power.CronEvent { 1217 var st power.State 1218 rt.GetState(&st) 1219 1220 events, err := adt.AsMultimap(adt.AsStore(rt), st.CronEventQueue, power.CronQueueHamtBitwidth, power.CronQueueAmtBitwidth) 1221 builtin.RequireNoErr(rt, err, exitcode.ErrIllegalState, "failed to load cron events") 1222 1223 evts, found, err := events.Get(abi.IntKey(int64(epoch))) 1224 require.NoError(h.t, err) 1225 require.True(h.t, found) 1226 1227 cronEvt := &power.CronEvent{} 1228 var cronEvents []power.CronEvent 1229 err = evts.ForEach(cronEvt, func(i int64) error { 1230 cronEvents = append(cronEvents, *cronEvt) 1231 return nil 1232 }) 1233 require.NoError(h.t, err) 1234 1235 return cronEvents 1236 } 1237 1238 func basicPowerSetup(t *testing.T) (*mock.Runtime, *spActorHarness) { 1239 builder := mock.NewBuilder(builtin.StoragePowerActorAddr).WithCaller(builtin.SystemActorAddr, builtin.SystemActorCodeID) 1240 rt := builder.Build(t) 1241 h := newHarness(t) 1242 h.constructAndVerify(rt) 1243 1244 return rt, h 1245 } 1246 1247 func (h *spActorHarness) createMinerBasic(rt *mock.Runtime, owner, worker, miner addr.Address) { 1248 label := strconv.Itoa(h.minerSeq) 1249 actrAddr := tutil.NewActorAddr(h.t, label) 1250 h.minerSeq += 1 1251 h.createMiner(rt, owner, worker, miner, actrAddr, abi.PeerID(label), nil, h.windowPoStProof, big.Zero()) 1252 } 1253 1254 func (h *spActorHarness) updateClaimedPower(rt *mock.Runtime, miner addr.Address, rawDelta, qaDelta abi.StoragePower) { 1255 prevCl := h.getClaim(rt, miner) 1256 1257 params := power.UpdateClaimedPowerParams{ 1258 RawByteDelta: rawDelta, 1259 QualityAdjustedDelta: qaDelta, 1260 } 1261 rt.SetCaller(miner, builtin.StorageMinerActorCodeID) 1262 rt.ExpectValidateCallerType(builtin.StorageMinerActorCodeID) 1263 rt.Call(h.UpdateClaimedPower, ¶ms) 1264 rt.Verify() 1265 1266 cl := h.getClaim(rt, miner) 1267 expectedRaw := big.Add(prevCl.RawBytePower, rawDelta) 1268 expectedAdjusted := big.Add(prevCl.QualityAdjPower, qaDelta) 1269 if expectedRaw.IsZero() { 1270 require.True(h.t, cl.RawBytePower.IsZero()) 1271 } else { 1272 require.EqualValues(h.t, big.Add(prevCl.RawBytePower, rawDelta), cl.RawBytePower) 1273 } 1274 1275 if expectedAdjusted.IsZero() { 1276 require.True(h.t, cl.QualityAdjPower.IsZero()) 1277 } else { 1278 require.EqualValues(h.t, big.Add(prevCl.QualityAdjPower, qaDelta), cl.QualityAdjPower) 1279 } 1280 } 1281 1282 func (h *spActorHarness) updatePledgeTotal(rt *mock.Runtime, miner addr.Address, delta abi.TokenAmount) { 1283 st := getState(rt) 1284 prev := st.TotalPledgeCollateral 1285 1286 rt.SetCaller(miner, builtin.StorageMinerActorCodeID) 1287 rt.ExpectValidateCallerType(builtin.StorageMinerActorCodeID) 1288 rt.Call(h.UpdatePledgeTotal, &delta) 1289 rt.Verify() 1290 1291 st = getState(rt) 1292 new := st.TotalPledgeCollateral 1293 require.EqualValues(h.t, big.Add(prev, delta), new) 1294 } 1295 1296 func (h *spActorHarness) currentPowerTotal(rt *mock.Runtime) *power.CurrentTotalPowerReturn { 1297 rt.ExpectValidateCallerAny() 1298 ret := rt.Call(h.CurrentTotalPower, nil).(*power.CurrentTotalPowerReturn) 1299 rt.Verify() 1300 return ret 1301 } 1302 1303 func (h *spActorHarness) enrollCronEvent(rt *mock.Runtime, miner addr.Address, epoch abi.ChainEpoch, payload []byte) { 1304 rt.ExpectValidateCallerType(builtin.StorageMinerActorCodeID) 1305 rt.SetCaller(miner, builtin.StorageMinerActorCodeID) 1306 rt.Call(h.Actor.EnrollCronEvent, &power.EnrollCronEventParams{ 1307 EventEpoch: epoch, 1308 Payload: payload, 1309 }) 1310 rt.Verify() 1311 1312 } 1313 1314 func (h *spActorHarness) submitPoRepForBulkVerify(rt *mock.Runtime, minerAddr addr.Address, sealInfo *proof.SealVerifyInfo) { 1315 rt.ExpectValidateCallerType(builtin.StorageMinerActorCodeID) 1316 rt.SetCaller(minerAddr, builtin.StorageMinerActorCodeID) 1317 rt.Call(h.Actor.SubmitPoRepForBulkVerify, sealInfo) 1318 rt.Verify() 1319 } 1320 1321 func (h *spActorHarness) expectTotalPowerEager(rt *mock.Runtime, expectedRaw, expectedQA abi.StoragePower) { 1322 st := getState(rt) 1323 1324 rawBytePower, qualityAdjPower := power.CurrentTotalPower(st) 1325 assert.Equal(h.t, expectedRaw, rawBytePower) 1326 assert.Equal(h.t, expectedQA, qualityAdjPower) 1327 } 1328 1329 func (h *spActorHarness) expectMinersAboveMinPower(rt *mock.Runtime, count int64) { 1330 st := getState(rt) 1331 assert.Equal(h.t, count, st.MinerAboveMinPowerCount) 1332 } 1333 1334 func (h *spActorHarness) expectTotalPledgeEager(rt *mock.Runtime, expectedPledge abi.TokenAmount) { 1335 st := getState(rt) 1336 assert.Equal(h.t, expectedPledge, st.TotalPledgeCollateral) 1337 } 1338 1339 func (h *spActorHarness) checkState(rt *mock.Runtime) { 1340 st := getState(rt) 1341 _, msgs := power.CheckStateInvariants(st, rt.AdtStore()) 1342 assert.True(h.t, msgs.IsEmpty(), strings.Join(msgs.Messages(), "\n")) 1343 } 1344 1345 func initCreateMinerBytes(t testing.TB, owner, worker addr.Address, peer abi.PeerID, multiaddrs []abi.Multiaddrs, windowPoStProofType abi.RegisteredPoStProof) []byte { 1346 params := &power.MinerConstructorParams{ 1347 OwnerAddr: owner, 1348 WorkerAddr: worker, 1349 WindowPoStProofType: windowPoStProofType, 1350 PeerId: peer, 1351 Multiaddrs: multiaddrs, 1352 } 1353 1354 buf := new(bytes.Buffer) 1355 require.NoError(t, params.MarshalCBOR(buf)) 1356 return buf.Bytes() 1357 } 1358 1359 func (s key) Key() string { 1360 return string(s) 1361 } 1362 1363 func getState(rt *mock.Runtime) *power.State { 1364 var st power.State 1365 rt.GetState(&st) 1366 return &st 1367 } 1368 1369 func batchVerifyDefaultOutput(vis map[addr.Address][]proof.SealVerifyInfo) map[addr.Address][]bool { 1370 out := make(map[addr.Address][]bool) 1371 for k, v := range vis { //nolint:nomaprange 1372 validations := make([]bool, len(v)) 1373 for i := range validations { 1374 validations[i] = true 1375 } 1376 out[k] = validations 1377 } 1378 return out 1379 }