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