github.com/filecoin-project/specs-actors/v4@v4.0.2/support/agent/cases_test.go (about)

     1  package agent_test
     2  
     3  import (
     4  	"context"
     5  	"fmt"
     6  	"math/rand"
     7  	"strings"
     8  	"testing"
     9  
    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/rt"
    13  	power2 "github.com/filecoin-project/specs-actors/v2/actors/builtin/power"
    14  	states2 "github.com/filecoin-project/specs-actors/v2/actors/states"
    15  	vm_test2 "github.com/filecoin-project/specs-actors/v2/support/vm"
    16  	states3 "github.com/filecoin-project/specs-actors/v3/actors/states"
    17  	vm_test3 "github.com/filecoin-project/specs-actors/v3/support/vm"
    18  	cid "github.com/ipfs/go-cid"
    19  	cbor "github.com/ipfs/go-ipld-cbor"
    20  	"github.com/stretchr/testify/assert"
    21  	"github.com/stretchr/testify/require"
    22  
    23  	"github.com/filecoin-project/specs-actors/v4/actors/builtin"
    24  	"github.com/filecoin-project/specs-actors/v4/actors/builtin/exported"
    25  	"github.com/filecoin-project/specs-actors/v4/actors/builtin/power"
    26  	"github.com/filecoin-project/specs-actors/v4/actors/migration/nv10"
    27  	"github.com/filecoin-project/specs-actors/v4/actors/states"
    28  	"github.com/filecoin-project/specs-actors/v4/actors/util/adt"
    29  	"github.com/filecoin-project/specs-actors/v4/support/agent"
    30  	"github.com/filecoin-project/specs-actors/v4/support/ipld"
    31  	vm_test "github.com/filecoin-project/specs-actors/v4/support/vm"
    32  )
    33  
    34  func TestCreate20Miners(t *testing.T) {
    35  	ctx := context.Background()
    36  	initialBalance := big.Mul(big.NewInt(1000), big.NewInt(1e18))
    37  	minerCount := 20
    38  
    39  	rnd := rand.New(rand.NewSource(42))
    40  
    41  	sim := agent.NewSim(ctx, t, newBlockStore, agent.SimConfig{Seed: rnd.Int63()})
    42  	accounts := vm_test.CreateAccounts(ctx, t, getV3VM(t, sim), minerCount, initialBalance, rnd.Int63())
    43  	sim.AddAgent(agent.NewMinerGenerator(
    44  		accounts,
    45  		agent.MinerAgentConfig{
    46  			PrecommitRate:    2.5,
    47  			ProofType:        abi.RegisteredSealProof_StackedDrg32GiBV1_1,
    48  			StartingBalance:  initialBalance,
    49  			MinMarketBalance: big.Zero(),
    50  			MaxMarketBalance: big.Zero(),
    51  		},
    52  		1.0, // create miner probability of 1 means a new miner is created every tick
    53  		rnd.Int63(),
    54  	))
    55  
    56  	// give it twice the number of ticks to account for variation in the rate
    57  	for i := 0; i < 2*minerCount; i++ {
    58  		require.NoError(t, sim.Tick())
    59  	}
    60  
    61  	// add 1 agent for miner generator
    62  	assert.Equal(t, minerCount+1, len(sim.Agents))
    63  
    64  	for _, a := range sim.Agents {
    65  		miner, ok := a.(*agent.MinerAgent)
    66  		if ok {
    67  			actor, found, err := sim.GetVM().GetActor(miner.IDAddress)
    68  			require.NoError(t, err)
    69  			require.True(t, found)
    70  
    71  			// demonstrate actor is created and has correct balance
    72  			assert.Equal(t, initialBalance, actor.Balance)
    73  		}
    74  	}
    75  }
    76  
    77  // This test covers all the simulation functionality.
    78  // 500 epochs is long enough for most, not all, important processes to take place, but runs fast enough
    79  // to keep in CI.
    80  func Test500Epochs(t *testing.T) {
    81  	ctx := context.Background()
    82  	initialBalance := big.Mul(big.NewInt(1e8), big.NewInt(1e18))
    83  	cumulativeStats := make(vm_test.StatsByCall)
    84  	minerCount := 10
    85  	clientCount := 9
    86  
    87  	// set up sim
    88  	rnd := rand.New(rand.NewSource(42))
    89  	sim := agent.NewSim(ctx, t, newBlockStore, agent.SimConfig{
    90  		Seed:             rnd.Int63(),
    91  		CheckpointEpochs: 1000,
    92  	})
    93  
    94  	// create miners
    95  	workerAccounts := vm_test.CreateAccounts(ctx, t, getV3VM(t, sim), minerCount, initialBalance, rnd.Int63())
    96  	sim.AddAgent(agent.NewMinerGenerator(
    97  		workerAccounts,
    98  		agent.MinerAgentConfig{
    99  			PrecommitRate:    2.0,
   100  			FaultRate:        0.0001,
   101  			RecoveryRate:     0.0001,
   102  			UpgradeSectors:   true,
   103  			ProofType:        abi.RegisteredSealProof_StackedDrg32GiBV1_1,
   104  			StartingBalance:  big.Div(initialBalance, big.NewInt(2)),
   105  			MinMarketBalance: big.NewInt(1e18),
   106  			MaxMarketBalance: big.NewInt(2e18),
   107  		},
   108  		1.0, // create miner probability of 1 means a new miner is created every tick
   109  		rnd.Int63(),
   110  	))
   111  
   112  	clientAccounts := vm_test.CreateAccounts(ctx, t, getV3VM(t, sim), clientCount, initialBalance, rnd.Int63())
   113  	dealAgents := agent.AddDealClientsForAccounts(sim, clientAccounts, rnd.Int63(), agent.DealClientConfig{
   114  		DealRate:         .05,
   115  		MinPieceSize:     1 << 29,
   116  		MaxPieceSize:     32 << 30,
   117  		MinStoragePrice:  big.Zero(),
   118  		MaxStoragePrice:  abi.NewTokenAmount(200_000_000),
   119  		MinMarketBalance: big.NewInt(1e18),
   120  		MaxMarketBalance: big.NewInt(2e18),
   121  	})
   122  
   123  	var pwrSt power.State
   124  	for i := 0; i < 500; i++ {
   125  		require.NoError(t, sim.Tick())
   126  
   127  		epoch := sim.GetVM().GetEpoch()
   128  		if epoch%100 == 0 {
   129  			// compute number of deals
   130  			deals := 0
   131  			for _, da := range dealAgents {
   132  				deals += da.DealCount
   133  			}
   134  
   135  			stateTree, err := getV3VM(t, sim).GetStateTree()
   136  			require.NoError(t, err)
   137  
   138  			totalBalance, err := getV3VM(t, sim).GetTotalActorBalance()
   139  			require.NoError(t, err)
   140  
   141  			acc, err := states.CheckStateInvariants(stateTree, totalBalance, sim.GetVM().GetEpoch()-1)
   142  			require.NoError(t, err)
   143  			require.True(t, acc.IsEmpty(), strings.Join(acc.Messages(), "\n"))
   144  
   145  			require.NoError(t, sim.GetVM().GetState(builtin.StoragePowerActorAddr, &pwrSt))
   146  
   147  			// assume each sector is 32Gb
   148  			sectorCount := big.Div(pwrSt.TotalBytesCommitted, big.NewInt(32<<30))
   149  
   150  			fmt.Printf("Power at %d: raw: %v  cmtRaw: %v  cmtSecs: %d  msgs: %d  deals: %d  gets: %d  puts: %d  write bytes: %d  read bytes: %d\n",
   151  				epoch, pwrSt.TotalRawBytePower, pwrSt.TotalBytesCommitted, sectorCount.Uint64(),
   152  				sim.MessageCount, deals, getV3VM(t, sim).StoreReads(), getV3VM(t, sim).StoreWrites(),
   153  				getV3VM(t, sim).StoreReadBytes(), getV3VM(t, sim).StoreWriteBytes())
   154  		}
   155  
   156  		cumulativeStats.MergeAllStats(sim.GetCallStats())
   157  	}
   158  }
   159  
   160  func TestCommitPowerAndCheckInvariants(t *testing.T) {
   161  	t.Skip("this is slow")
   162  	ctx := context.Background()
   163  	initialBalance := big.Mul(big.NewInt(1e9), big.NewInt(1e18))
   164  	minerCount := 1
   165  
   166  	rnd := rand.New(rand.NewSource(42))
   167  	sim := agent.NewSim(ctx, t, newBlockStore, agent.SimConfig{Seed: rnd.Int63()})
   168  	accounts := vm_test.CreateAccounts(ctx, t, getV3VM(t, sim), minerCount, initialBalance, rnd.Int63())
   169  	sim.AddAgent(agent.NewMinerGenerator(
   170  		accounts,
   171  		agent.MinerAgentConfig{
   172  			PrecommitRate:    0.1,
   173  			FaultRate:        0.00001,
   174  			RecoveryRate:     0.0001,
   175  			ProofType:        abi.RegisteredSealProof_StackedDrg32GiBV1_1,
   176  			StartingBalance:  initialBalance,
   177  			MinMarketBalance: big.Zero(),
   178  			MaxMarketBalance: big.Zero(),
   179  		},
   180  		1.0, // create miner probability of 1 means a new miner is created every tick
   181  		rnd.Int63(),
   182  	))
   183  
   184  	var pwrSt power.State
   185  	for i := 0; i < 100_000; i++ {
   186  		require.NoError(t, sim.Tick())
   187  
   188  		epoch := sim.GetVM().GetEpoch()
   189  		if epoch%100 == 0 {
   190  			stateTree, err := getV3VM(t, sim).GetStateTree()
   191  			require.NoError(t, err)
   192  
   193  			totalBalance, err := getV3VM(t, sim).GetTotalActorBalance()
   194  			require.NoError(t, err)
   195  
   196  			acc, err := states.CheckStateInvariants(stateTree, totalBalance, sim.GetVM().GetEpoch()-1)
   197  			require.NoError(t, err)
   198  			require.True(t, acc.IsEmpty(), strings.Join(acc.Messages(), "\n"))
   199  
   200  			require.NoError(t, sim.GetVM().GetState(builtin.StoragePowerActorAddr, &pwrSt))
   201  
   202  			// assume each sector is 32Gb
   203  			sectorCount := big.Div(pwrSt.TotalBytesCommitted, big.NewInt(32<<30))
   204  
   205  			fmt.Printf("Power at %d: raw: %v  cmtRaw: %v  cmtSecs: %d  cnsMnrs: %d avgWins: %.3f  msgs: %d\n",
   206  				epoch, pwrSt.TotalRawBytePower, pwrSt.TotalBytesCommitted, sectorCount.Uint64(),
   207  				pwrSt.MinerAboveMinPowerCount, float64(sim.WinCount)/float64(epoch), sim.MessageCount)
   208  		}
   209  	}
   210  }
   211  
   212  func TestMigration(t *testing.T) {
   213  	t.Skip("slow")
   214  	ctx, cancel := context.WithCancel(context.Background())
   215  	defer cancel()
   216  	initialBalance := big.Mul(big.NewInt(1e8), big.NewInt(1e18))
   217  	minerCount := 10
   218  	clientCount := 9
   219  
   220  	blkStore := newBlockStore()
   221  	v := vm_test2.NewVMWithSingletons(ctx, t, blkStore)
   222  	v2VMFactory := func(ctx context.Context, impl vm_test2.ActorImplLookup, store adt.Store, stateRoot cid.Cid, epoch abi.ChainEpoch) (agent.SimVM, error) {
   223  		return vm_test2.NewVMAtEpoch(ctx, impl, store, stateRoot, epoch)
   224  	}
   225  	v2MinerFactory := func(ctx context.Context, root cid.Cid) (agent.SimMinerState, error) {
   226  		return &agent.MinerStateV2{
   227  			Ctx:  ctx,
   228  			Root: root,
   229  		}, nil
   230  	}
   231  
   232  	// set up sim
   233  	rnd := rand.New(rand.NewSource(42))
   234  	sim := agent.NewSimWithVM(ctx, t, v, v2VMFactory, agent.ComputePowerTableV2, blkStore, newBlockStore, v2MinerFactory, agent.SimConfig{
   235  		Seed:             rnd.Int63(),
   236  		CheckpointEpochs: 1000,
   237  	}, agent.CreateMinerParamsV2)
   238  
   239  	// create miners
   240  	workerAccounts := vm_test2.CreateAccounts(ctx, t, v, minerCount, initialBalance, rnd.Int63())
   241  	sim.AddAgent(agent.NewMinerGenerator(
   242  		workerAccounts,
   243  		agent.MinerAgentConfig{
   244  			PrecommitRate:    2.0,
   245  			FaultRate:        0.00001,
   246  			RecoveryRate:     0.0001,
   247  			UpgradeSectors:   true,
   248  			ProofType:        abi.RegisteredSealProof_StackedDrg32GiBV1_1,
   249  			StartingBalance:  big.Div(initialBalance, big.NewInt(2)),
   250  			MinMarketBalance: big.NewInt(1e18),
   251  			MaxMarketBalance: big.NewInt(2e18),
   252  		},
   253  		1.0, // create miner probability of 1 means a new miner is created every tick
   254  		rnd.Int63(),
   255  	))
   256  
   257  	clientAccounts := vm_test2.CreateAccounts(ctx, t, v, clientCount, initialBalance, rnd.Int63())
   258  	agent.AddDealClientsForAccounts(sim, clientAccounts, rnd.Int63(), agent.DealClientConfig{
   259  		DealRate:         .05,
   260  		MinPieceSize:     1 << 29,
   261  		MaxPieceSize:     32 << 30,
   262  		MinStoragePrice:  big.Zero(),
   263  		MaxStoragePrice:  abi.NewTokenAmount(200_000_000),
   264  		MinMarketBalance: big.NewInt(1e18),
   265  		MaxMarketBalance: big.NewInt(2e18),
   266  	})
   267  
   268  	// Run v2 for 5000 epochs
   269  	var pwrSt power2.State
   270  	for i := 0; i < 5000; i++ {
   271  		require.NoError(t, sim.Tick())
   272  		epoch := sim.GetVM().GetEpoch()
   273  		if epoch%100 == 0 {
   274  			stateTree, err := states2.LoadTree(sim.GetVM().Store(), sim.GetVM().StateRoot())
   275  			require.NoError(t, err)
   276  
   277  			totalBalance, err := sim.GetVM().GetTotalActorBalance()
   278  			require.NoError(t, err)
   279  
   280  			acc, err := states2.CheckStateInvariants(stateTree, totalBalance, sim.GetVM().GetEpoch()-1)
   281  			require.NoError(t, err)
   282  			require.True(t, acc.IsEmpty(), strings.Join(acc.Messages(), "\n"))
   283  
   284  			require.NoError(t, sim.GetVM().GetState(builtin.StoragePowerActorAddr, &pwrSt))
   285  
   286  			// assume each sector is 32Gb
   287  			sectorCount := big.Div(pwrSt.TotalBytesCommitted, big.NewInt(32<<30))
   288  
   289  			fmt.Printf("Power at %d: raw: %v  cmtRaw: %v  cmtSecs: %d  cnsMnrs: %d avgWins: %.3f  msgs: %d\n",
   290  				epoch, pwrSt.TotalRawBytePower, pwrSt.TotalBytesCommitted, sectorCount.Uint64(),
   291  				pwrSt.MinerAboveMinPowerCount, float64(sim.WinCount)/float64(epoch), sim.MessageCount)
   292  		}
   293  	}
   294  
   295  	// Migrate
   296  	v2 := sim.GetVM()
   297  	log := nv10.TestLogger{TB: t}
   298  	priorEpoch := v2.GetEpoch() - 1 // on tick sim internally creates new vm with epoch set to the next one
   299  	nextRoot, err := nv10.MigrateStateTree(ctx, v2.Store(), v2.StateRoot(), priorEpoch, nv10.Config{MaxWorkers: 1}, log, nv10.NewMemMigrationCache())
   300  	require.NoError(t, err)
   301  
   302  	lookup := map[cid.Cid]rt.VMActor{}
   303  	for _, ba := range exported.BuiltinActors() {
   304  		lookup[ba.Code()] = ba
   305  	}
   306  
   307  	v3, err := vm_test3.NewVMAtEpoch(ctx, lookup, v2.Store(), nextRoot, priorEpoch+1)
   308  	require.NoError(t, err)
   309  
   310  	stateTree, err := v3.GetStateTree()
   311  	require.NoError(t, err)
   312  	totalBalance, err := v3.GetTotalActorBalance()
   313  	require.NoError(t, err)
   314  	msgs, err := states3.CheckStateInvariants(stateTree, totalBalance, priorEpoch)
   315  	require.NoError(t, err)
   316  	assert.Zero(t, len(msgs.Messages()), strings.Join(msgs.Messages(), "\n"))
   317  
   318  	v3VMFactory := func(ctx context.Context, impl vm_test2.ActorImplLookup, store adt.Store, stateRoot cid.Cid, epoch abi.ChainEpoch) (agent.SimVM, error) {
   319  		return vm_test.NewVMAtEpoch(ctx, vm_test.ActorImplLookup(impl), store, stateRoot, epoch)
   320  	}
   321  	v3MinerFactory := func(ctx context.Context, root cid.Cid) (agent.SimMinerState, error) {
   322  		return &agent.MinerStateV3{
   323  			Ctx:  ctx,
   324  			Root: root,
   325  		}, nil
   326  	}
   327  	sim.SwapVM(v3, agent.VMFactoryFunc(v3VMFactory), v3MinerFactory, agent.ComputePowerTableV3, agent.CreateMinerParamsV3)
   328  
   329  	// Run v3 for 5000 epochs
   330  	for i := 0; i < 5000; i++ {
   331  		require.NoError(t, sim.Tick())
   332  		epoch := sim.GetVM().GetEpoch()
   333  		if epoch%100 == 0 {
   334  			stateTree, err := states.LoadTree(sim.GetVM().Store(), sim.GetVM().StateRoot())
   335  			require.NoError(t, err)
   336  
   337  			totalBalance, err := sim.GetVM().GetTotalActorBalance()
   338  			require.NoError(t, err)
   339  
   340  			acc, err := states.CheckStateInvariants(stateTree, totalBalance, sim.GetVM().GetEpoch()-1)
   341  			require.NoError(t, err)
   342  			require.True(t, acc.IsEmpty(), strings.Join(acc.Messages(), "\n"))
   343  
   344  			require.NoError(t, sim.GetVM().GetState(builtin.StoragePowerActorAddr, &pwrSt))
   345  
   346  			// assume each sector is 32Gb
   347  			sectorCount := big.Div(pwrSt.TotalBytesCommitted, big.NewInt(32<<30))
   348  
   349  			fmt.Printf("Power at %d: raw: %v  cmtRaw: %v  cmtSecs: %d  cnsMnrs: %d avgWins: %.3f  msgs: %d\n",
   350  				epoch, pwrSt.TotalRawBytePower, pwrSt.TotalBytesCommitted, sectorCount.Uint64(),
   351  				pwrSt.MinerAboveMinPowerCount, float64(sim.WinCount)/float64(epoch), sim.MessageCount)
   352  		}
   353  	}
   354  
   355  }
   356  
   357  func TestCommitAndCheckReadWriteStats(t *testing.T) {
   358  	t.Skip("this is slow")
   359  	ctx := context.Background()
   360  	initialBalance := big.Mul(big.NewInt(1e8), big.NewInt(1e18))
   361  	cumulativeStats := make(vm_test.StatsByCall)
   362  	minerCount := 10
   363  	clientCount := 9
   364  
   365  	// set up sim
   366  	rnd := rand.New(rand.NewSource(42))
   367  	sim := agent.NewSim(ctx, t, newBlockStore, agent.SimConfig{
   368  		Seed:             rnd.Int63(),
   369  		CheckpointEpochs: 1000,
   370  	})
   371  
   372  	// create miners
   373  	workerAccounts := vm_test.CreateAccounts(ctx, t, getV3VM(t, sim), minerCount, initialBalance, rnd.Int63())
   374  	sim.AddAgent(agent.NewMinerGenerator(
   375  		workerAccounts,
   376  		agent.MinerAgentConfig{
   377  			PrecommitRate:    2.0,
   378  			FaultRate:        0.00001,
   379  			RecoveryRate:     0.0001,
   380  			UpgradeSectors:   true,
   381  			ProofType:        abi.RegisteredSealProof_StackedDrg32GiBV1_1,
   382  			StartingBalance:  big.Div(initialBalance, big.NewInt(2)),
   383  			MinMarketBalance: big.NewInt(1e18),
   384  			MaxMarketBalance: big.NewInt(2e18),
   385  		},
   386  		1.0, // create miner probability of 1 means a new miner is created every tick
   387  		rnd.Int63(),
   388  	))
   389  
   390  	clientAccounts := vm_test.CreateAccounts(ctx, t, getV3VM(t, sim), clientCount, initialBalance, rnd.Int63())
   391  	dealAgents := agent.AddDealClientsForAccounts(sim, clientAccounts, rnd.Int63(), agent.DealClientConfig{
   392  		DealRate:         .05,
   393  		MinPieceSize:     1 << 29,
   394  		MaxPieceSize:     32 << 30,
   395  		MinStoragePrice:  big.Zero(),
   396  		MaxStoragePrice:  abi.NewTokenAmount(200_000_000),
   397  		MinMarketBalance: big.NewInt(1e18),
   398  		MaxMarketBalance: big.NewInt(2e18),
   399  	})
   400  
   401  	var pwrSt power.State
   402  	for i := 0; i < 20_000; i++ {
   403  		require.NoError(t, sim.Tick())
   404  
   405  		epoch := sim.GetVM().GetEpoch()
   406  		if epoch%100 == 0 {
   407  			// compute number of deals
   408  			deals := 0
   409  			for _, da := range dealAgents {
   410  				deals += da.DealCount
   411  			}
   412  
   413  			require.NoError(t, sim.GetVM().GetState(builtin.StoragePowerActorAddr, &pwrSt))
   414  
   415  			// assume each sector is 32Gb
   416  			sectorCount := big.Div(pwrSt.TotalBytesCommitted, big.NewInt(32<<30))
   417  
   418  			fmt.Printf("Power at %d: raw: %v  cmtRaw: %v  cmtSecs: %d  msgs: %d  deals: %d  gets: %d  puts: %d  write bytes: %d  read bytes: %d\n",
   419  				epoch, pwrSt.TotalRawBytePower, pwrSt.TotalBytesCommitted, sectorCount.Uint64(),
   420  				sim.MessageCount, deals, getV3VM(t, sim).StoreReads(), getV3VM(t, sim).StoreWrites(),
   421  				getV3VM(t, sim).StoreReadBytes(), getV3VM(t, sim).StoreWriteBytes())
   422  		}
   423  
   424  		cumulativeStats.MergeAllStats(sim.GetCallStats())
   425  
   426  		if sim.GetVM().GetEpoch()%1000 == 0 {
   427  			for method, stats := range cumulativeStats {
   428  				printCallStats(method, stats, "")
   429  			}
   430  			cumulativeStats = make(vm_test.StatsByCall)
   431  		}
   432  	}
   433  }
   434  
   435  func TestCreateDeals(t *testing.T) {
   436  	t.Skip("this is slow")
   437  	ctx := context.Background()
   438  	initialBalance := big.Mul(big.NewInt(1e9), big.NewInt(1e18))
   439  	minerCount := 3
   440  	clientCount := 9
   441  
   442  	// set up sim
   443  	rnd := rand.New(rand.NewSource(42))
   444  	sim := agent.NewSim(ctx, t, newBlockStore, agent.SimConfig{Seed: rnd.Int63()})
   445  
   446  	// create miners
   447  	workerAccounts := vm_test.CreateAccounts(ctx, t, getV3VM(t, sim), minerCount, initialBalance, rnd.Int63())
   448  	sim.AddAgent(agent.NewMinerGenerator(
   449  		workerAccounts,
   450  		agent.MinerAgentConfig{
   451  			PrecommitRate:    0.1,
   452  			FaultRate:        0.0001,
   453  			RecoveryRate:     0.0001,
   454  			ProofType:        abi.RegisteredSealProof_StackedDrg32GiBV1_1,
   455  			StartingBalance:  big.Div(initialBalance, big.NewInt(2)),
   456  			MinMarketBalance: big.NewInt(1e18),
   457  			MaxMarketBalance: big.NewInt(2e18),
   458  		},
   459  		1.0, // create miner probability of 1 means a new miner is created every tick
   460  		rnd.Int63(),
   461  	))
   462  
   463  	clientAccounts := vm_test.CreateAccounts(ctx, t, getV3VM(t, sim), clientCount, initialBalance, rnd.Int63())
   464  	dealAgents := agent.AddDealClientsForAccounts(sim, clientAccounts, rnd.Int63(), agent.DealClientConfig{
   465  		DealRate:         .01,
   466  		MinPieceSize:     1 << 29,
   467  		MaxPieceSize:     32 << 30,
   468  		MinStoragePrice:  big.Zero(),
   469  		MaxStoragePrice:  abi.NewTokenAmount(200_000_000),
   470  		MinMarketBalance: big.NewInt(1e18),
   471  		MaxMarketBalance: big.NewInt(2e18),
   472  	})
   473  
   474  	var pwrSt power.State
   475  	for i := 0; i < 100_000; i++ {
   476  		require.NoError(t, sim.Tick())
   477  
   478  		epoch := sim.GetVM().GetEpoch()
   479  		if epoch%100 == 0 {
   480  			stateTree, err := getV3VM(t, sim).GetStateTree()
   481  			require.NoError(t, err)
   482  
   483  			totalBalance, err := getV3VM(t, sim).GetTotalActorBalance()
   484  			require.NoError(t, err)
   485  
   486  			acc, err := states.CheckStateInvariants(stateTree, totalBalance, sim.GetVM().GetEpoch()-1)
   487  			require.NoError(t, err)
   488  			require.True(t, acc.IsEmpty(), strings.Join(acc.Messages(), "\n"))
   489  
   490  			require.NoError(t, sim.GetVM().GetState(builtin.StoragePowerActorAddr, &pwrSt))
   491  
   492  			// assume each sector is 32Gb
   493  			sectorCount := big.Div(pwrSt.TotalBytesCommitted, big.NewInt(32<<30))
   494  
   495  			// compute number of deals
   496  			deals := 0
   497  			for _, da := range dealAgents {
   498  				deals += da.DealCount
   499  			}
   500  
   501  			fmt.Printf("Power at %d: raw: %v  cmtRaw: %v  cmtSecs: %d  cnsMnrs: %d avgWins: %.3f  msgs: %d  deals: %d\n",
   502  				epoch, pwrSt.TotalRawBytePower, pwrSt.TotalBytesCommitted, sectorCount.Uint64(),
   503  				pwrSt.MinerAboveMinPowerCount, float64(sim.WinCount)/float64(epoch), sim.MessageCount, deals)
   504  		}
   505  	}
   506  }
   507  
   508  func TestCCUpgrades(t *testing.T) {
   509  	t.Skip("this is slow")
   510  	ctx := context.Background()
   511  	initialBalance := big.Mul(big.NewInt(1e10), big.NewInt(1e18))
   512  	minerCount := 10
   513  	clientCount := 9
   514  
   515  	// set up sim
   516  	rnd := rand.New(rand.NewSource(42))
   517  	sim := agent.NewSim(ctx, t, newBlockStore, agent.SimConfig{Seed: rnd.Int63()})
   518  
   519  	// create miners
   520  	workerAccounts := vm_test.CreateAccounts(ctx, t, getV3VM(t, sim), minerCount, initialBalance, rnd.Int63())
   521  	sim.AddAgent(agent.NewMinerGenerator(
   522  		workerAccounts,
   523  		agent.MinerAgentConfig{
   524  			PrecommitRate:    2.0,
   525  			FaultRate:        0.00001,
   526  			RecoveryRate:     0.0001,
   527  			UpgradeSectors:   true,
   528  			ProofType:        abi.RegisteredSealProof_StackedDrg32GiBV1_1,
   529  			StartingBalance:  big.Div(initialBalance, big.NewInt(2)),
   530  			MinMarketBalance: big.NewInt(1e18),
   531  			MaxMarketBalance: big.NewInt(2e18),
   532  		},
   533  		1.0, // create miner probability of 1 means a new miner is created every tick
   534  		rnd.Int63(),
   535  	))
   536  
   537  	clientAccounts := vm_test.CreateAccounts(ctx, t, getV3VM(t, sim), clientCount, initialBalance, rnd.Int63())
   538  	agent.AddDealClientsForAccounts(sim, clientAccounts, rnd.Int63(), agent.DealClientConfig{
   539  		DealRate:         .01,
   540  		MinPieceSize:     1 << 29,
   541  		MaxPieceSize:     32 << 30,
   542  		MinStoragePrice:  big.Zero(),
   543  		MaxStoragePrice:  abi.NewTokenAmount(200_000_000),
   544  		MinMarketBalance: big.NewInt(1e18),
   545  		MaxMarketBalance: big.NewInt(2e18),
   546  	})
   547  
   548  	var pwrSt power.State
   549  	for i := 0; i < 100_000; i++ {
   550  		require.NoError(t, sim.Tick())
   551  
   552  		epoch := sim.GetVM().GetEpoch()
   553  		if epoch%100 == 0 {
   554  			stateTree, err := getV3VM(t, sim).GetStateTree()
   555  			require.NoError(t, err)
   556  
   557  			totalBalance, err := getV3VM(t, sim).GetTotalActorBalance()
   558  			require.NoError(t, err)
   559  
   560  			acc, err := states.CheckStateInvariants(stateTree, totalBalance, sim.GetVM().GetEpoch()-1)
   561  			require.NoError(t, err)
   562  			require.True(t, acc.IsEmpty(), strings.Join(acc.Messages(), "\n"))
   563  
   564  			require.NoError(t, sim.GetVM().GetState(builtin.StoragePowerActorAddr, &pwrSt))
   565  
   566  			// assume each sector is 32Gb
   567  			sectorCount := big.Div(pwrSt.TotalBytesCommitted, big.NewInt(32<<30))
   568  
   569  			// compute stats
   570  			deals := 0
   571  			upgrades := uint64(0)
   572  			for _, a := range sim.Agents {
   573  				switch agnt := a.(type) {
   574  				case *agent.MinerAgent:
   575  					upgrades += agnt.UpgradedSectors
   576  				case *agent.DealClientAgent:
   577  					deals += agnt.DealCount
   578  				}
   579  			}
   580  
   581  			// compute upgrades
   582  
   583  			fmt.Printf("Power at %d: raw: %v  cmtRaw: %v  cmtSecs: %d  msgs: %d  deals: %d  upgrades: %d\n",
   584  				epoch, pwrSt.TotalRawBytePower, pwrSt.TotalBytesCommitted, sectorCount.Uint64(),
   585  				sim.MessageCount, deals, upgrades)
   586  		}
   587  	}
   588  }
   589  
   590  func newBlockStore() cbor.IpldBlockstore {
   591  	return ipld.NewBlockStoreInMemory()
   592  }
   593  
   594  func printCallStats(method vm_test.MethodKey, stats *vm_test.CallStats, indent string) { // nolint:unused
   595  	fmt.Printf("%s%v:%d: calls: %d  gets: %d  puts: %d  read: %d  written: %d  avg gets: %.2f, avg puts: %.2f\n",
   596  		indent, builtin.ActorNameByCode(method.Code), method.Method, stats.Calls, stats.Reads, stats.Writes,
   597  		stats.ReadBytes, stats.WriteBytes, float32(stats.Reads)/float32(stats.Calls),
   598  		float32(stats.Writes)/float32(stats.Calls))
   599  
   600  	if stats.SubStats == nil {
   601  		return
   602  	}
   603  
   604  	for m, s := range stats.SubStats {
   605  		printCallStats(m, s, indent+"  ")
   606  	}
   607  }
   608  
   609  func getV3VM(t *testing.T, sim *agent.Sim) *vm_test.VM {
   610  	vm, ok := sim.GetVM().(*vm_test.VM)
   611  	require.True(t, ok)
   612  	return vm
   613  }