github.com/filecoin-project/specs-actors/v4@v4.0.2/support/agent/miner_generator.go (about) 1 package agent 2 3 import ( 4 "math/rand" 5 6 "github.com/filecoin-project/go-address" 7 "github.com/filecoin-project/go-state-types/cbor" 8 "github.com/pkg/errors" 9 10 power2 "github.com/filecoin-project/specs-actors/v2/actors/builtin/power" 11 "github.com/filecoin-project/specs-actors/v4/actors/builtin" 12 "github.com/filecoin-project/specs-actors/v4/actors/builtin/power" 13 power3 "github.com/filecoin-project/specs-actors/v4/actors/builtin/power" 14 ) 15 16 // MinerGenerator adds miner agents to the simulation at a configured rate. 17 // When triggered to add a new miner, it: 18 // * Selects the next owner address from the accounts it has been given. 19 // * Sends a createMiner message from that account 20 // * Handles the response by creating a MinerAgent with MinerAgentConfig and registering it in the sim. 21 type MinerGenerator struct { 22 config MinerAgentConfig // eventually this should become a set of probabilities to support miner differentiation 23 createMinerEvents *RateIterator 24 minersCreated int 25 accounts []address.Address 26 rnd *rand.Rand 27 } 28 29 func NewMinerGenerator(accounts []address.Address, config MinerAgentConfig, createMinerRate float64, rndSeed int64) *MinerGenerator { 30 rnd := rand.New(rand.NewSource(rndSeed)) 31 return &MinerGenerator{ 32 config: config, 33 createMinerEvents: NewRateIterator(createMinerRate, rnd.Int63()), 34 accounts: accounts, 35 rnd: rnd, 36 } 37 } 38 39 func (mg *MinerGenerator) Tick(s SimState) ([]message, error) { 40 var msgs []message 41 if mg.minersCreated >= len(mg.accounts) { 42 return msgs, nil 43 } 44 45 err := mg.createMinerEvents.Tick(func() error { 46 if mg.minersCreated < len(mg.accounts) { 47 addr := mg.accounts[mg.minersCreated] 48 mg.minersCreated++ 49 msg, err := mg.createMiner(addr, mg.config, s) 50 if err != nil { 51 return err 52 } 53 msgs = append(msgs, msg) 54 } 55 return nil 56 }) 57 return msgs, err 58 } 59 60 func (mg *MinerGenerator) createMiner(owner address.Address, cfg MinerAgentConfig, s SimState) (message, error) { 61 params, err := s.CreateMinerParams(owner, owner, cfg.ProofType) 62 if err != nil { 63 return message{}, err 64 } 65 return message{ 66 From: owner, 67 To: builtin.StoragePowerActorAddr, 68 Value: mg.config.StartingBalance, // miner gets all account funds 69 Method: builtin.MethodsPower.CreateMiner, 70 Params: params, 71 ReturnHandler: func(s SimState, msg message, ret cbor.Marshaler) error { 72 createMinerRet, ok := ret.(*power.CreateMinerReturn) 73 if !ok { 74 return errors.Errorf("create miner return has wrong type: %v", ret) 75 } 76 77 var worker, owner address.Address 78 params, okV3 := msg.Params.(*power3.CreateMinerParams) 79 if !okV3 { 80 params, okV2 := msg.Params.(*power2.CreateMinerParams) 81 if !okV2 { 82 return errors.Errorf("create miner params has wrong type: %v", msg.Params) 83 } 84 worker = params.Worker 85 owner = params.Owner 86 } else { 87 worker = params.Worker 88 owner = params.Owner 89 } 90 91 // register agent as both a miner and deal provider 92 minerAgent := NewMinerAgent(owner, worker, createMinerRet.IDAddress, createMinerRet.RobustAddress, mg.rnd.Int63(), cfg) 93 s.AddAgent(minerAgent) 94 s.AddDealProvider(minerAgent) 95 return nil 96 }, 97 }, nil 98 }