2021-06-18 18:45:29 +00:00
|
|
|
package kit
|
2021-06-11 17:26:25 +00:00
|
|
|
|
|
|
|
import (
|
|
|
|
"github.com/filecoin-project/go-state-types/abi"
|
|
|
|
"github.com/filecoin-project/go-state-types/big"
|
2022-06-14 15:00:51 +00:00
|
|
|
|
|
|
|
"github.com/filecoin-project/lotus/build"
|
|
|
|
"github.com/filecoin-project/lotus/chain/types"
|
2022-06-14 17:21:34 +00:00
|
|
|
"github.com/filecoin-project/lotus/chain/wallet/key"
|
2022-06-14 15:00:51 +00:00
|
|
|
"github.com/filecoin-project/lotus/node"
|
2022-03-17 20:13:18 +00:00
|
|
|
"github.com/filecoin-project/lotus/node/config"
|
|
|
|
"github.com/filecoin-project/lotus/node/modules"
|
|
|
|
"github.com/filecoin-project/lotus/node/modules/dtypes"
|
|
|
|
"github.com/filecoin-project/lotus/node/repo"
|
2022-06-14 18:25:52 +00:00
|
|
|
"github.com/filecoin-project/lotus/storage/paths"
|
2022-06-14 17:41:59 +00:00
|
|
|
"github.com/filecoin-project/lotus/storage/pipeline/sealiface"
|
2022-06-14 18:03:38 +00:00
|
|
|
"github.com/filecoin-project/lotus/storage/sealer/sealtasks"
|
2021-06-11 17:26:25 +00:00
|
|
|
)
|
|
|
|
|
|
|
|
// DefaultPresealsPerBootstrapMiner is the number of preseals that every
|
|
|
|
// bootstrap miner has by default. It can be overridden through the
|
|
|
|
// PresealSectors option.
|
|
|
|
const DefaultPresealsPerBootstrapMiner = 2
|
|
|
|
|
2021-06-17 12:58:35 +00:00
|
|
|
const TestSpt = abi.RegisteredSealProof_StackedDrg2KiBV1_1
|
|
|
|
|
2021-06-11 17:26:25 +00:00
|
|
|
// nodeOpts is an options accumulating struct, where functional options are
|
|
|
|
// merged into.
|
|
|
|
type nodeOpts struct {
|
|
|
|
balance abi.TokenAmount
|
|
|
|
lite bool
|
|
|
|
sectors int
|
|
|
|
rpc bool
|
2022-06-14 17:21:34 +00:00
|
|
|
ownerKey *key.Key
|
2021-06-11 17:26:25 +00:00
|
|
|
extraNodeOpts []node.Option
|
2022-08-05 20:34:16 +00:00
|
|
|
cfgOpts []CfgOption
|
|
|
|
fsrepo bool
|
2021-06-18 16:40:33 +00:00
|
|
|
|
2022-05-23 23:13:30 +00:00
|
|
|
subsystems MinerSubsystem
|
|
|
|
mainMiner *TestMiner
|
|
|
|
disableLibp2p bool
|
|
|
|
optBuilders []OptBuilder
|
|
|
|
sectorSize abi.SectorSize
|
|
|
|
maxStagingDealsBytes int64
|
|
|
|
minerNoLocalSealing bool // use worker
|
|
|
|
minerAssigner string
|
|
|
|
disallowRemoteFinalize bool
|
2022-07-12 10:42:08 +00:00
|
|
|
noStorage bool
|
2022-01-14 13:11:04 +00:00
|
|
|
|
2022-03-18 11:32:16 +00:00
|
|
|
workerTasks []sealtasks.TaskType
|
2022-06-14 18:25:52 +00:00
|
|
|
workerStorageOpt func(paths.Store) paths.Store
|
2022-08-03 11:05:30 +00:00
|
|
|
workerName string
|
2021-06-11 17:26:25 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// DefaultNodeOpts are the default options that will be applied to test nodes.
|
|
|
|
var DefaultNodeOpts = nodeOpts{
|
2021-08-20 14:53:24 +00:00
|
|
|
balance: big.Mul(big.NewInt(100000000), types.NewInt(build.FilecoinPrecision)),
|
|
|
|
sectors: DefaultPresealsPerBootstrapMiner,
|
|
|
|
sectorSize: abi.SectorSize(2 << 10), // 2KiB.
|
2022-01-14 13:11:04 +00:00
|
|
|
|
2022-03-18 11:32:16 +00:00
|
|
|
workerTasks: []sealtasks.TaskType{sealtasks.TTFetch, sealtasks.TTCommit1, sealtasks.TTFinalize},
|
2022-06-14 18:25:52 +00:00
|
|
|
workerStorageOpt: func(store paths.Store) paths.Store { return store },
|
2021-06-11 17:26:25 +00:00
|
|
|
}
|
|
|
|
|
2021-06-15 09:46:32 +00:00
|
|
|
// OptBuilder is used to create an option after some other node is already
|
|
|
|
// active. Takes all active nodes as a parameter.
|
|
|
|
type OptBuilder func(activeNodes []*TestFullNode) node.Option
|
|
|
|
|
2021-06-11 17:26:25 +00:00
|
|
|
// NodeOpt is a functional option for test nodes.
|
|
|
|
type NodeOpt func(opts *nodeOpts) error
|
|
|
|
|
2021-06-18 16:40:33 +00:00
|
|
|
func WithAllSubsystems() NodeOpt {
|
|
|
|
return func(opts *nodeOpts) error {
|
2021-07-12 10:12:29 +00:00
|
|
|
opts.subsystems = opts.subsystems.Add(SMarkets)
|
2021-06-18 16:40:33 +00:00
|
|
|
opts.subsystems = opts.subsystems.Add(SMining)
|
|
|
|
opts.subsystems = opts.subsystems.Add(SSealing)
|
|
|
|
opts.subsystems = opts.subsystems.Add(SSectorStorage)
|
|
|
|
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-07-07 11:35:40 +00:00
|
|
|
func WithSubsystems(systems ...MinerSubsystem) NodeOpt {
|
2021-06-18 16:40:33 +00:00
|
|
|
return func(opts *nodeOpts) error {
|
2021-07-07 11:35:40 +00:00
|
|
|
for _, s := range systems {
|
|
|
|
opts.subsystems = opts.subsystems.Add(s)
|
|
|
|
}
|
2021-06-18 16:40:33 +00:00
|
|
|
return nil
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-09-06 15:39:35 +00:00
|
|
|
func WithMaxStagingDealsBytes(size int64) NodeOpt {
|
|
|
|
return func(opts *nodeOpts) error {
|
|
|
|
opts.maxStagingDealsBytes = size
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-01-14 13:11:04 +00:00
|
|
|
func WithNoLocalSealing(nope bool) NodeOpt {
|
|
|
|
return func(opts *nodeOpts) error {
|
|
|
|
opts.minerNoLocalSealing = nope
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-05-23 20:31:06 +00:00
|
|
|
func WithAssigner(a string) NodeOpt {
|
|
|
|
return func(opts *nodeOpts) error {
|
|
|
|
opts.minerAssigner = a
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-05-23 23:13:30 +00:00
|
|
|
func WithDisallowRemoteFinalize(d bool) NodeOpt {
|
|
|
|
return func(opts *nodeOpts) error {
|
|
|
|
opts.disallowRemoteFinalize = d
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-06-24 14:02:51 +00:00
|
|
|
func DisableLibp2p() NodeOpt {
|
|
|
|
return func(opts *nodeOpts) error {
|
|
|
|
opts.disableLibp2p = true
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-06-18 16:40:33 +00:00
|
|
|
func MainMiner(m *TestMiner) NodeOpt {
|
|
|
|
return func(opts *nodeOpts) error {
|
|
|
|
opts.mainMiner = m
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-06-11 17:26:25 +00:00
|
|
|
// OwnerBalance specifies the balance to be attributed to a miner's owner
|
|
|
|
// account. Only relevant when creating a miner.
|
|
|
|
func OwnerBalance(balance abi.TokenAmount) NodeOpt {
|
|
|
|
return func(opts *nodeOpts) error {
|
|
|
|
opts.balance = balance
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// LiteNode specifies that this node will be a lite node. Only relevant when
|
|
|
|
// creating a fullnode.
|
|
|
|
func LiteNode() NodeOpt {
|
|
|
|
return func(opts *nodeOpts) error {
|
|
|
|
opts.lite = true
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// PresealSectors specifies the amount of preseal sectors to give to a miner
|
|
|
|
// at genesis. Only relevant when creating a miner.
|
|
|
|
func PresealSectors(sectors int) NodeOpt {
|
|
|
|
return func(opts *nodeOpts) error {
|
|
|
|
opts.sectors = sectors
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-07-12 10:42:08 +00:00
|
|
|
// NoStorage initializes miners with no writable storage paths (just read-only preseal paths)
|
|
|
|
func NoStorage() NodeOpt {
|
2022-07-11 21:00:50 +00:00
|
|
|
return func(opts *nodeOpts) error {
|
2022-07-12 10:42:08 +00:00
|
|
|
opts.noStorage = true
|
2022-07-11 21:00:50 +00:00
|
|
|
return nil
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-06-11 17:26:25 +00:00
|
|
|
// ThroughRPC makes interactions with this node throughout the test flow through
|
|
|
|
// the JSON-RPC API.
|
|
|
|
func ThroughRPC() NodeOpt {
|
|
|
|
return func(opts *nodeOpts) error {
|
|
|
|
opts.rpc = true
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// OwnerAddr sets the owner address of a miner. Only relevant when creating
|
|
|
|
// a miner.
|
2022-06-14 17:21:34 +00:00
|
|
|
func OwnerAddr(wk *key.Key) NodeOpt {
|
2021-06-11 17:26:25 +00:00
|
|
|
return func(opts *nodeOpts) error {
|
|
|
|
opts.ownerKey = wk
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// ConstructorOpts are Lotus node constructor options that are passed as-is to
|
|
|
|
// the node.
|
|
|
|
func ConstructorOpts(extra ...node.Option) NodeOpt {
|
|
|
|
return func(opts *nodeOpts) error {
|
|
|
|
opts.extraNodeOpts = extra
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
}
|
2021-06-15 09:46:32 +00:00
|
|
|
|
2022-03-17 20:13:18 +00:00
|
|
|
func MutateSealingConfig(mut func(sc *config.SealingConfig)) NodeOpt {
|
|
|
|
return ConstructorOpts(
|
|
|
|
node.ApplyIf(node.IsType(repo.StorageMiner), node.Override(new(dtypes.GetSealingConfigFunc), func() (dtypes.GetSealingConfigFunc, error) {
|
|
|
|
return func() (sealiface.Config, error) {
|
|
|
|
cf := config.DefaultStorageMiner()
|
|
|
|
mut(&cf.Sealing)
|
|
|
|
return modules.ToSealingConfig(cf.Dealmaking, cf.Sealing), nil
|
|
|
|
}, nil
|
|
|
|
})))
|
|
|
|
}
|
|
|
|
|
2021-08-20 14:53:24 +00:00
|
|
|
// SectorSize sets the sector size for this miner. Start() will populate the
|
|
|
|
// corresponding proof type depending on the network version (genesis network
|
|
|
|
// version if the Ensemble is unstarted, or the current network version
|
|
|
|
// if started).
|
|
|
|
func SectorSize(sectorSize abi.SectorSize) NodeOpt {
|
2021-06-15 09:46:32 +00:00
|
|
|
return func(opts *nodeOpts) error {
|
2021-08-20 14:53:24 +00:00
|
|
|
opts.sectorSize = sectorSize
|
2021-06-15 09:46:32 +00:00
|
|
|
return nil
|
|
|
|
}
|
|
|
|
}
|
2022-01-14 13:11:04 +00:00
|
|
|
|
|
|
|
func WithTaskTypes(tt []sealtasks.TaskType) NodeOpt {
|
|
|
|
return func(opts *nodeOpts) error {
|
|
|
|
opts.workerTasks = tt
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
}
|
2022-03-18 11:32:16 +00:00
|
|
|
|
2022-08-03 11:05:30 +00:00
|
|
|
func WithWorkerName(n string) NodeOpt {
|
|
|
|
return func(opts *nodeOpts) error {
|
|
|
|
opts.workerName = n
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-07-11 21:00:50 +00:00
|
|
|
var WithSealWorkerTasks = WithTaskTypes([]sealtasks.TaskType{sealtasks.TTFetch, sealtasks.TTCommit1, sealtasks.TTFinalize, sealtasks.TTAddPiece, sealtasks.TTPreCommit1, sealtasks.TTPreCommit2, sealtasks.TTCommit2, sealtasks.TTUnseal})
|
|
|
|
|
2022-06-14 18:25:52 +00:00
|
|
|
func WithWorkerStorage(transform func(paths.Store) paths.Store) NodeOpt {
|
2022-03-18 11:32:16 +00:00
|
|
|
return func(opts *nodeOpts) error {
|
|
|
|
opts.workerStorageOpt = transform
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
}
|
2022-08-05 20:34:16 +00:00
|
|
|
|
|
|
|
func FsRepo() NodeOpt {
|
|
|
|
return func(opts *nodeOpts) error {
|
|
|
|
opts.fsrepo = true
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func WithCfgOpt(opt CfgOption) NodeOpt {
|
|
|
|
return func(opts *nodeOpts) error {
|
|
|
|
opts.cfgOpts = append(opts.cfgOpts, opt)
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
type CfgOption func(cfg *config.FullNode) error
|
|
|
|
|
|
|
|
func SplitstoreDiscard() NodeOpt {
|
|
|
|
return WithCfgOpt(func(cfg *config.FullNode) error {
|
|
|
|
cfg.Chainstore.EnableSplitstore = true
|
|
|
|
cfg.Chainstore.Splitstore.HotStoreFullGCFrequency = 0 // turn off full gc
|
|
|
|
cfg.Chainstore.Splitstore.ColdStoreType = "discard" // no cold store
|
|
|
|
return nil
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
|
|
|
func SplitstoreUniversal() NodeOpt {
|
|
|
|
return WithCfgOpt(func(cfg *config.FullNode) error {
|
|
|
|
cfg.Chainstore.EnableSplitstore = true
|
|
|
|
cfg.Chainstore.Splitstore.HotStoreFullGCFrequency = 0 // turn off full gc
|
|
|
|
cfg.Chainstore.Splitstore.ColdStoreType = "universal" // universal bs is coldstore
|
|
|
|
return nil
|
|
|
|
})
|
|
|
|
}
|
2022-08-08 20:06:32 +00:00
|
|
|
|
2022-11-07 21:31:12 +00:00
|
|
|
func SplitstoreMessges() NodeOpt {
|
2022-08-08 20:06:32 +00:00
|
|
|
return WithCfgOpt(func(cfg *config.FullNode) error {
|
2022-11-07 21:31:12 +00:00
|
|
|
cfg.Chainstore.EnableSplitstore = true
|
|
|
|
cfg.Chainstore.Splitstore.HotStoreFullGCFrequency = 0 // turn off full gc
|
|
|
|
cfg.Chainstore.Splitstore.ColdStoreType = "messages" // universal bs is coldstore, and it accepts messages
|
2022-08-08 20:06:32 +00:00
|
|
|
return nil
|
|
|
|
})
|
|
|
|
}
|
2022-11-15 17:28:26 +00:00
|
|
|
|
|
|
|
func RealTimeFilterAPI() NodeOpt {
|
|
|
|
return WithCfgOpt(func(cfg *config.FullNode) error {
|
|
|
|
cfg.ActorEvent.EnableRealTimeFilterAPI = true
|
|
|
|
return nil
|
|
|
|
})
|
|
|
|
}
|
2022-11-16 11:22:30 +00:00
|
|
|
|
|
|
|
func HistoricFilterAPI(dbpath string) NodeOpt {
|
|
|
|
return WithCfgOpt(func(cfg *config.FullNode) error {
|
|
|
|
cfg.ActorEvent.EnableRealTimeFilterAPI = true
|
|
|
|
cfg.ActorEvent.EnableHistoricFilterAPI = true
|
|
|
|
cfg.ActorEvent.ActorEventDatabasePath = dbpath
|
|
|
|
return nil
|
|
|
|
})
|
|
|
|
}
|