Merge remote-tracking branch 'origin/next' into feat/actors-miner-refactor
This commit is contained in:
@@ -11,6 +11,7 @@ import (
|
||||
|
||||
"github.com/filecoin-project/go-address"
|
||||
"github.com/filecoin-project/lotus/api"
|
||||
"github.com/filecoin-project/lotus/build"
|
||||
"github.com/filecoin-project/lotus/chain/types"
|
||||
lcli "github.com/filecoin-project/lotus/cli"
|
||||
|
||||
@@ -68,7 +69,7 @@ func sendSmallFundsTxs(ctx context.Context, api api.FullNode, from address.Addre
|
||||
sendSet = append(sendSet, naddr)
|
||||
}
|
||||
|
||||
tick := time.NewTicker(time.Second / time.Duration(rate))
|
||||
tick := build.Clock.Ticker(time.Second / time.Duration(rate))
|
||||
for {
|
||||
select {
|
||||
case <-tick.C:
|
||||
@@ -76,7 +77,7 @@ func sendSmallFundsTxs(ctx context.Context, api api.FullNode, from address.Addre
|
||||
From: from,
|
||||
To: sendSet[rand.Intn(20)],
|
||||
Value: types.NewInt(1),
|
||||
GasLimit: 100000,
|
||||
GasLimit: 100_000_000,
|
||||
GasPrice: types.NewInt(0),
|
||||
}
|
||||
|
||||
|
||||
@@ -405,16 +405,19 @@ func getExtras(ex interface{}) (*string, *float64) {
|
||||
func tallyGasCharges(charges map[string]*stats, et types.ExecutionTrace) {
|
||||
for i, gc := range et.GasCharges {
|
||||
name := gc.Name
|
||||
if name == "OnIpldGetStart" {
|
||||
if name == "OnIpldGetEnd" {
|
||||
continue
|
||||
}
|
||||
tt := float64(gc.TimeTaken.Nanoseconds())
|
||||
if name == "OnIpldGet" {
|
||||
prev := et.GasCharges[i-1]
|
||||
if prev.Name != "OnIpldGetStart" {
|
||||
log.Warn("OnIpldGet without OnIpldGetStart")
|
||||
next := &types.GasTrace{}
|
||||
if i+1 < len(et.GasCharges) {
|
||||
next = et.GasCharges[i+1]
|
||||
}
|
||||
tt += float64(prev.TimeTaken.Nanoseconds())
|
||||
if next.Name != "OnIpldGetEnd" {
|
||||
log.Warn("OnIpldGet without OnIpldGetEnd")
|
||||
}
|
||||
tt += float64(next.TimeTaken.Nanoseconds())
|
||||
}
|
||||
eType, eSize := getExtras(gc.Extra)
|
||||
if eType != nil {
|
||||
@@ -604,7 +607,7 @@ var importAnalyzeCmd = &cli.Command{
|
||||
timeInActors := actorExec.timeTaken.Mean() * actorExec.timeTaken.n
|
||||
fmt.Printf("Avarage time per epoch in actors: %s (%.1f%%)\n", time.Duration(timeInActors)/time.Duration(totalTipsets), timeInActors/float64(totalTime)*100)
|
||||
}
|
||||
if actorExecDone, ok := charges["OnActorExecDone"]; ok {
|
||||
if actorExecDone, ok := charges["OnMethodInvocationDone"]; ok {
|
||||
timeInActors := actorExecDone.timeTaken.Mean() * actorExecDone.timeTaken.n
|
||||
fmt.Printf("Avarage time per epoch in OnActorExecDone %s (%.1f%%)\n", time.Duration(timeInActors)/time.Duration(totalTipsets), timeInActors/float64(totalTime)*100)
|
||||
}
|
||||
|
||||
@@ -3,6 +3,7 @@ package main
|
||||
import (
|
||||
"context"
|
||||
"database/sql"
|
||||
"strconv"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
@@ -330,8 +331,15 @@ create table if not exists miner_sectors_heads
|
||||
primary key (miner_id,miner_sectors_cid)
|
||||
|
||||
);
|
||||
|
||||
create type miner_sector_event_type as enum ('ADDED', 'EXTENDED', 'EXPIRED', 'TERMINATED');
|
||||
DO $$
|
||||
BEGIN
|
||||
IF NOT EXISTS (SELECT 1 FROM pg_type WHERE typname = 'miner_sector_event_type') THEN
|
||||
CREATE TYPE miner_sector_event_type AS ENUM
|
||||
(
|
||||
'ADDED','EXTENDED', 'EXPIRED', 'TERMINATED'
|
||||
);
|
||||
END IF;
|
||||
END$$;
|
||||
|
||||
create table if not exists miner_sector_events
|
||||
(
|
||||
@@ -342,7 +350,50 @@ create table if not exists miner_sector_events
|
||||
|
||||
constraint miner_sector_events_pk
|
||||
primary key (sector_id, event, miner_id, state_root)
|
||||
)
|
||||
);
|
||||
|
||||
create table if not exists market_deal_proposals
|
||||
(
|
||||
deal_id bigint not null,
|
||||
|
||||
state_root text not null,
|
||||
|
||||
piece_cid text not null,
|
||||
padded_piece_size bigint not null,
|
||||
unpadded_piece_size bigint not null,
|
||||
is_verified bool not null,
|
||||
|
||||
client_id text not null,
|
||||
provider_id text not null,
|
||||
|
||||
start_epoch bigint not null,
|
||||
end_epoch bigint not null,
|
||||
slashed_epoch bigint,
|
||||
storage_price_per_epoch text not null,
|
||||
|
||||
provider_collateral text not null,
|
||||
client_collateral text not null,
|
||||
|
||||
constraint market_deal_proposal_pk
|
||||
primary key (deal_id)
|
||||
);
|
||||
|
||||
create table if not exists market_deal_states
|
||||
(
|
||||
deal_id bigint not null,
|
||||
|
||||
sector_start_epoch bigint not null,
|
||||
last_update_epoch bigint not null,
|
||||
slash_epoch bigint not null,
|
||||
|
||||
state_root text not null,
|
||||
|
||||
unique (deal_id, sector_start_epoch, last_update_epoch, slash_epoch),
|
||||
|
||||
constraint market_deal_states_pk
|
||||
primary key (deal_id, state_root)
|
||||
|
||||
);
|
||||
|
||||
/*
|
||||
create or replace function miner_tips(epoch bigint)
|
||||
@@ -854,7 +905,7 @@ func (st *storage) updateMinerSectors(minerTips map[types.TipSetKey][]*minerStat
|
||||
}
|
||||
|
||||
for _, added := range changes.Added {
|
||||
if _, err := eventStmt.Exec(miner.addr.String(), added.SectorNumber, miner.stateroot.String(), "ADDED"); err != nil {
|
||||
if _, err := eventStmt.Exec(added.SectorNumber, "ADDED", miner.addr.String(), miner.stateroot.String()); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
@@ -902,6 +953,172 @@ func (st *storage) updateMinerSectors(minerTips map[types.TipSetKey][]*minerStat
|
||||
return updateTx.Commit()
|
||||
}
|
||||
|
||||
func (st *storage) storeMarketActorDealStates(marketTips map[types.TipSetKey]*marketStateInfo, tipHeights []tipsetKeyHeight, api api.FullNode) error {
|
||||
start := time.Now()
|
||||
defer func() {
|
||||
log.Infow("Stored Market Deal States", "duration", time.Since(start).String())
|
||||
}()
|
||||
tx, err := st.db.Begin()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if _, err := tx.Exec(`create temp table mds (like market_deal_states excluding constraints) on commit drop;`); err != nil {
|
||||
return err
|
||||
}
|
||||
stmt, err := tx.Prepare(`copy mds (deal_id, sector_start_epoch, last_update_epoch, slash_epoch, state_root) from STDIN`)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
for _, th := range tipHeights {
|
||||
mt := marketTips[th.tsKey]
|
||||
dealStates, err := api.StateMarketDeals(context.TODO(), mt.tsKey)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
for dealID, ds := range dealStates {
|
||||
id, err := strconv.ParseUint(dealID, 10, 64)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if _, err := stmt.Exec(
|
||||
id,
|
||||
ds.State.SectorStartEpoch,
|
||||
ds.State.LastUpdatedEpoch,
|
||||
ds.State.SlashEpoch,
|
||||
mt.stateroot.String(),
|
||||
); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
if err := stmt.Close(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if _, err := tx.Exec(`insert into market_deal_states select * from mds on conflict do nothing`); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return tx.Commit()
|
||||
}
|
||||
|
||||
func (st *storage) storeMarketActorDealProposals(marketTips map[types.TipSetKey]*marketStateInfo, tipHeights []tipsetKeyHeight, api api.FullNode) error {
|
||||
start := time.Now()
|
||||
defer func() {
|
||||
log.Infow("Stored Market Deal Proposals", "duration", time.Since(start).String())
|
||||
}()
|
||||
tx, err := st.db.Begin()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if _, err := tx.Exec(`create temp table mdp (like market_deal_proposals excluding constraints) on commit drop;`); err != nil {
|
||||
return xerrors.Errorf("prep temp: %w", err)
|
||||
}
|
||||
|
||||
stmt, err := tx.Prepare(`copy mdp (deal_id, state_root, piece_cid, padded_piece_size, unpadded_piece_size, is_verified, client_id, provider_id, start_epoch, end_epoch, slashed_epoch, storage_price_per_epoch, provider_collateral, client_collateral) from STDIN`)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// insert in sorted order (lowest height -> highest height) since dealid is pk of table.
|
||||
for _, th := range tipHeights {
|
||||
mt := marketTips[th.tsKey]
|
||||
dealStates, err := api.StateMarketDeals(context.TODO(), mt.tsKey)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
for dealID, ds := range dealStates {
|
||||
id, err := strconv.ParseUint(dealID, 10, 64)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if _, err := stmt.Exec(
|
||||
id,
|
||||
mt.stateroot.String(),
|
||||
ds.Proposal.PieceCID.String(),
|
||||
ds.Proposal.PieceSize,
|
||||
ds.Proposal.PieceSize.Unpadded(),
|
||||
ds.Proposal.VerifiedDeal,
|
||||
ds.Proposal.Client.String(),
|
||||
ds.Proposal.Provider.String(),
|
||||
ds.Proposal.StartEpoch,
|
||||
ds.Proposal.EndEpoch,
|
||||
nil, // slashed_epoch
|
||||
ds.Proposal.StoragePricePerEpoch.String(),
|
||||
ds.Proposal.ProviderCollateral.String(),
|
||||
ds.Proposal.ClientCollateral.String(),
|
||||
); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
if err := stmt.Close(); err != nil {
|
||||
return err
|
||||
}
|
||||
if _, err := tx.Exec(`insert into market_deal_proposals select * from mdp on conflict do nothing`); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return tx.Commit()
|
||||
|
||||
}
|
||||
|
||||
func (st *storage) updateMarketActorDealProposals(marketTip map[types.TipSetKey]*marketStateInfo, tipHeights []tipsetKeyHeight, api api.FullNode) error {
|
||||
start := time.Now()
|
||||
defer func() {
|
||||
log.Infow("Updated Market Deal Proposals", "duration", time.Since(start).String())
|
||||
}()
|
||||
pred := state.NewStatePredicates(api)
|
||||
|
||||
tx, err := st.db.Begin()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
stmt, err := tx.Prepare(`update market_deal_proposals set slashed_epoch=$1 where deal_id=$2`)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
for _, th := range tipHeights {
|
||||
mt := marketTip[th.tsKey]
|
||||
stateDiff := pred.OnStorageMarketActorChanged(pred.OnDealStateChanged(pred.OnDealStateAmtChanged()))
|
||||
|
||||
changed, val, err := stateDiff(context.TODO(), mt.parentTsKey, mt.tsKey)
|
||||
if err != nil {
|
||||
log.Warnw("error getting market deal state diff", "error", err)
|
||||
}
|
||||
if !changed {
|
||||
continue
|
||||
}
|
||||
changes, ok := val.(*state.MarketDealStateChanges)
|
||||
if !ok {
|
||||
return xerrors.Errorf("Unknown type returned by Deal State AMT predicate: %T", val)
|
||||
}
|
||||
|
||||
for _, modified := range changes.Modified {
|
||||
if modified.From.SlashEpoch != modified.To.SlashEpoch {
|
||||
if _, err := stmt.Exec(modified.To.SlashEpoch, modified.ID); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if err := stmt.Close(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return tx.Commit()
|
||||
}
|
||||
|
||||
func (st *storage) storeHeaders(bhs map[cid.Cid]*types.BlockHeader, sync bool) error {
|
||||
st.headerLk.Lock()
|
||||
defer st.headerLk.Unlock()
|
||||
|
||||
@@ -7,6 +7,7 @@ import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"math"
|
||||
"sort"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
@@ -18,6 +19,7 @@ import (
|
||||
"github.com/filecoin-project/specs-actors/actors/abi"
|
||||
"github.com/filecoin-project/specs-actors/actors/abi/big"
|
||||
"github.com/filecoin-project/specs-actors/actors/builtin"
|
||||
"github.com/filecoin-project/specs-actors/actors/builtin/market"
|
||||
"github.com/filecoin-project/specs-actors/actors/builtin/miner"
|
||||
"github.com/filecoin-project/specs-actors/actors/builtin/power"
|
||||
"github.com/filecoin-project/specs-actors/actors/builtin/reward"
|
||||
@@ -81,6 +83,20 @@ type minerStateInfo struct {
|
||||
psize uint64
|
||||
}
|
||||
|
||||
type marketStateInfo struct {
|
||||
// common
|
||||
act types.Actor
|
||||
stateroot cid.Cid
|
||||
|
||||
// calculating changes
|
||||
// calculating changes
|
||||
tsKey types.TipSetKey
|
||||
parentTsKey types.TipSetKey
|
||||
|
||||
// market actor specific
|
||||
state market.State
|
||||
}
|
||||
|
||||
type actorInfo struct {
|
||||
stateroot cid.Cid
|
||||
tsKey types.TipSetKey
|
||||
@@ -88,6 +104,11 @@ type actorInfo struct {
|
||||
state string
|
||||
}
|
||||
|
||||
type tipsetKeyHeight struct {
|
||||
height abi.ChainEpoch
|
||||
tsKey types.TipSetKey
|
||||
}
|
||||
|
||||
func syncHead(ctx context.Context, api api.FullNode, st *storage, headTs *types.TipSet, maxBatch int) {
|
||||
var alk sync.Mutex
|
||||
|
||||
@@ -169,6 +190,9 @@ func syncHead(ctx context.Context, api api.FullNode, st *storage, headTs *types.
|
||||
|
||||
log.Infow("Starting Sync", "height", minH, "numBlocks", len(toSync), "maxBatch", maxBatch)
|
||||
|
||||
// relate tipset keys to height so they may be processed in ascending order.
|
||||
var tipHeights []tipsetKeyHeight
|
||||
tipsSeen := make(map[types.TipSetKey]struct{})
|
||||
// map of addresses to changed actors
|
||||
var changes map[string]types.Actor
|
||||
// collect all actor state that has changes between block headers
|
||||
@@ -276,9 +300,20 @@ func syncHead(ctx context.Context, api api.FullNode, st *storage, headTs *types.
|
||||
parentTsKey: pts.Parents(),
|
||||
}
|
||||
addressToID[addr] = address.Undef
|
||||
if _, ok := tipsSeen[pts.Key()]; !ok {
|
||||
tipHeights = append(tipHeights, tipsetKeyHeight{
|
||||
height: pts.Height(),
|
||||
tsKey: pts.Key(),
|
||||
})
|
||||
}
|
||||
tipsSeen[pts.Key()] = struct{}{}
|
||||
alk.Unlock()
|
||||
}
|
||||
})
|
||||
// sort tipHeights in ascending order.
|
||||
sort.Slice(tipHeights, func(i, j int) bool {
|
||||
return tipHeights[i].height < tipHeights[j].height
|
||||
})
|
||||
|
||||
// map of tipset to reward state
|
||||
rewardTips := make(map[types.TipSetKey]*rewardStateInfo, len(changes))
|
||||
@@ -313,23 +348,28 @@ func syncHead(ctx context.Context, api api.FullNode, st *storage, headTs *types.
|
||||
|
||||
log.Infof("Getting actor change info")
|
||||
|
||||
// highly likely that the market actor will change at every epoch
|
||||
marketActorChanges := make(map[types.TipSetKey]*marketStateInfo, len(changes))
|
||||
|
||||
minerChanges := 0
|
||||
for addr, m := range actors {
|
||||
for actor, c := range m {
|
||||
// reward actor
|
||||
if actor.Code == builtin.RewardActorCodeID {
|
||||
rewardTips[c.tsKey] = &rewardStateInfo{
|
||||
stateroot: c.stateroot,
|
||||
baselinePower: big.Zero(),
|
||||
}
|
||||
// only want actors with head change events
|
||||
if _, found := headsSeen[actor.Head]; found {
|
||||
continue
|
||||
}
|
||||
headsSeen[actor.Head] = struct{}{}
|
||||
|
||||
// miner actors with head change events
|
||||
if actor.Code == builtin.StorageMinerActorCodeID {
|
||||
if _, found := headsSeen[actor.Head]; found {
|
||||
continue
|
||||
switch actor.Code {
|
||||
case builtin.StorageMarketActorCodeID:
|
||||
marketActorChanges[c.tsKey] = &marketStateInfo{
|
||||
act: actor,
|
||||
stateroot: c.stateroot,
|
||||
tsKey: c.tsKey,
|
||||
parentTsKey: c.parentTsKey,
|
||||
state: market.State{},
|
||||
}
|
||||
case builtin.StorageMinerActorCodeID:
|
||||
minerChanges++
|
||||
|
||||
minerTips[c.tsKey] = append(minerTips[c.tsKey], &minerStateInfo{
|
||||
@@ -346,10 +386,14 @@ func syncHead(ctx context.Context, api api.FullNode, st *storage, headTs *types.
|
||||
rawPower: big.Zero(),
|
||||
qalPower: big.Zero(),
|
||||
})
|
||||
|
||||
headsSeen[actor.Head] = struct{}{}
|
||||
// reward actor
|
||||
case builtin.RewardActorCodeID:
|
||||
rewardTips[c.tsKey] = &rewardStateInfo{
|
||||
stateroot: c.stateroot,
|
||||
baselinePower: big.Zero(),
|
||||
}
|
||||
}
|
||||
continue
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -440,6 +484,21 @@ func syncHead(ctx context.Context, api api.FullNode, st *storage, headTs *types.
|
||||
})
|
||||
log.Infow("Completed Miner Processing", "duration", time.Since(minerProcessingStartedAt).String(), "processed", minerChanges)
|
||||
|
||||
log.Info("Getting market actor info")
|
||||
// TODO: consider taking the min of the array length and using that for concurrency param, e.g:
|
||||
// concurrency := math.Min(len(marketActorChanges), 50)
|
||||
parmap.Par(50, parmap.MapArr(marketActorChanges), func(mrktInfo *marketStateInfo) {
|
||||
astb, err := api.ChainReadObj(ctx, mrktInfo.act.Head)
|
||||
if err != nil {
|
||||
log.Error(err)
|
||||
return
|
||||
}
|
||||
if err := mrktInfo.state.UnmarshalCBOR(bytes.NewReader(astb)); err != nil {
|
||||
log.Error(err)
|
||||
return
|
||||
}
|
||||
})
|
||||
|
||||
log.Info("Getting receipts")
|
||||
|
||||
receipts := fetchParentReceipts(ctx, api, toSync)
|
||||
@@ -501,6 +560,24 @@ func syncHead(ctx context.Context, api api.FullNode, st *storage, headTs *types.
|
||||
return
|
||||
}
|
||||
|
||||
log.Info("Storing market actor deal proposal info")
|
||||
if err := st.storeMarketActorDealProposals(marketActorChanges, tipHeights, api); err != nil {
|
||||
log.Error(err)
|
||||
return
|
||||
}
|
||||
|
||||
log.Info("Storing market actor deal state info")
|
||||
if err := st.storeMarketActorDealStates(marketActorChanges, tipHeights, api); err != nil {
|
||||
log.Error(err)
|
||||
return
|
||||
}
|
||||
|
||||
log.Info("Updating market actor deal proposal info")
|
||||
if err := st.updateMarketActorDealProposals(marketActorChanges, tipHeights, api); err != nil {
|
||||
log.Error(err)
|
||||
return
|
||||
}
|
||||
|
||||
log.Infof("Storing messages")
|
||||
|
||||
if err := st.storeMessages(msgs); err != nil {
|
||||
|
||||
@@ -281,7 +281,7 @@ func (h *handler) send(w http.ResponseWriter, r *http.Request) {
|
||||
To: to,
|
||||
|
||||
GasPrice: types.NewInt(0),
|
||||
GasLimit: 10000,
|
||||
GasLimit: 100_000_000,
|
||||
})
|
||||
if err != nil {
|
||||
w.WriteHeader(400)
|
||||
@@ -355,7 +355,7 @@ func (h *handler) mkminer(w http.ResponseWriter, r *http.Request) {
|
||||
To: owner,
|
||||
|
||||
GasPrice: types.NewInt(0),
|
||||
GasLimit: 10000,
|
||||
GasLimit: 100_000_000,
|
||||
})
|
||||
if err != nil {
|
||||
w.WriteHeader(400)
|
||||
@@ -391,7 +391,7 @@ func (h *handler) mkminer(w http.ResponseWriter, r *http.Request) {
|
||||
Method: builtin.MethodsPower.CreateMiner,
|
||||
Params: params,
|
||||
|
||||
GasLimit: 10000000,
|
||||
GasLimit: 100_000_000,
|
||||
GasPrice: types.NewInt(0),
|
||||
}
|
||||
|
||||
@@ -424,7 +424,7 @@ func (h *handler) msgwait(w http.ResponseWriter, r *http.Request) {
|
||||
|
||||
if mw.Receipt.ExitCode != 0 {
|
||||
w.WriteHeader(400)
|
||||
w.Write([]byte(xerrors.Errorf("create storage miner failed: exit code %d", mw.Receipt.ExitCode).Error()))
|
||||
w.Write([]byte(xerrors.Errorf("create miner failed: exit code %d", mw.Receipt.ExitCode).Error()))
|
||||
return
|
||||
}
|
||||
w.WriteHeader(200)
|
||||
@@ -447,7 +447,7 @@ func (h *handler) msgwaitaddr(w http.ResponseWriter, r *http.Request) {
|
||||
|
||||
if mw.Receipt.ExitCode != 0 {
|
||||
w.WriteHeader(400)
|
||||
w.Write([]byte(xerrors.Errorf("create storage miner failed: exit code %d", mw.Receipt.ExitCode).Error()))
|
||||
w.Write([]byte(xerrors.Errorf("create miner failed: exit code %d", mw.Receipt.ExitCode).Error()))
|
||||
return
|
||||
}
|
||||
w.WriteHeader(200)
|
||||
|
||||
@@ -1,14 +1,14 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<title>Creating Storage Miner - Lotus Fountain</title>
|
||||
<title>Creating Miner - Lotus Fountain</title>
|
||||
<link rel="stylesheet" type="text/css" href="main.css">
|
||||
</head>
|
||||
<body>
|
||||
<div class="Index">
|
||||
<div class="Index-nodes">
|
||||
<div class="Index-node">
|
||||
[CREATING STORAGE MINER]
|
||||
[CREATING MINER]
|
||||
</div>
|
||||
<div class="Index-node" id="formnd">
|
||||
<form id="f" action='/mkminer' method='POST'>
|
||||
@@ -26,7 +26,7 @@
|
||||
<b>Waiting for transaction on chain..</b>
|
||||
</div>
|
||||
<div class="Index-node">
|
||||
<span>When creating storage miner, DO NOT REFRESH THE PAGE, wait for it to load. This can take more than 5min.</span>
|
||||
<span>When creating miner, DO NOT REFRESH THE PAGE, wait for it to load. This can take more than 5min.</span>
|
||||
</div>
|
||||
<div class="Index-node">
|
||||
<span>If you don't have an owner/worker address, you can create it by following <a target="_blank" href="https://docs.lotu.sh/en+mining#get-started-22083">these instructions</a>.</span>
|
||||
|
||||
@@ -1,14 +1,14 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<title>Creating Storage Miner (wait) - Lotus Fountain</title>
|
||||
<title>Creating Miner (wait) - Lotus Fountain</title>
|
||||
<link rel="stylesheet" type="text/css" href="main.css">
|
||||
</head>
|
||||
<body>
|
||||
<div class="Index">
|
||||
<div class="Index-nodes">
|
||||
<div class="Index-node">
|
||||
[CREATING STORAGE MINER]
|
||||
[CREATING MINER]
|
||||
</div>
|
||||
<div class="Index-node">
|
||||
Gas Funds: <span id="fcid"></span> - <span id="fstate">WAIT</span>
|
||||
@@ -17,12 +17,12 @@
|
||||
Miner Actor: <span id="mcid"></span> - <span id="mstate">WAIT</span>
|
||||
</div>
|
||||
<div class="Index-node" style="display: none" id="fwait">
|
||||
New storage miners address is: <b id="actaddr">t</b>
|
||||
New miners address is: <b id="actaddr">t</b>
|
||||
</div>
|
||||
<div class="Index-node" style="display: none" id="mwait">
|
||||
<div style="padding-bottom: 1em">To initialize the storage miner run the following command:</div>
|
||||
<div style="padding-bottom: 1em">To initialize the miner run the following command:</div>
|
||||
<div style="overflow-x: visible; white-space: nowrap; background: #353500">
|
||||
<code>lotus-storage-miner init --actor=<span id="actaddr2">t</span> --owner=<span id="owner">t3</span></code>
|
||||
<code>lotus-miner init --actor=<span id="actaddr2">t</span> --owner=<span id="owner">t3</span></code>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -36,7 +36,9 @@ import (
|
||||
|
||||
var log = logging.Logger("main")
|
||||
|
||||
const FlagStorageRepo = "workerrepo"
|
||||
const FlagWorkerRepo = "worker-repo"
|
||||
// TODO remove after deprecation period
|
||||
const FlagWorkerRepoDeprecation = "workerrepo"
|
||||
|
||||
func main() {
|
||||
lotuslog.SetupLogLevels()
|
||||
@@ -48,19 +50,23 @@ func main() {
|
||||
}
|
||||
|
||||
app := &cli.App{
|
||||
Name: "lotus-seal-worker",
|
||||
Usage: "Remote storage miner worker",
|
||||
Name: "lotus-worker",
|
||||
Usage: "Remote miner worker",
|
||||
Version: build.UserVersion(),
|
||||
Flags: []cli.Flag{
|
||||
&cli.StringFlag{
|
||||
Name: FlagStorageRepo,
|
||||
EnvVars: []string{"WORKER_PATH"},
|
||||
Name: FlagWorkerRepo,
|
||||
Aliases: []string{FlagWorkerRepoDeprecation},
|
||||
EnvVars: []string{"LOTUS_WORKER_PATH", "WORKER_PATH"},
|
||||
Value: "~/.lotusworker", // TODO: Consider XDG_DATA_HOME
|
||||
Usage: fmt.Sprintf("Specify worker repo path. flag %s and env WORKER_PATH are DEPRECATION, will REMOVE SOON", FlagWorkerRepoDeprecation),
|
||||
},
|
||||
&cli.StringFlag{
|
||||
Name: "storagerepo",
|
||||
EnvVars: []string{"LOTUS_STORAGE_PATH"},
|
||||
Value: "~/.lotusstorage", // TODO: Consider XDG_DATA_HOME
|
||||
Name: "miner-repo",
|
||||
Aliases: []string{"storagerepo"},
|
||||
EnvVars: []string{"LOTUS_MINER_PATH", "LOTUS_STORAGE_PATH"},
|
||||
Value: "~/.lotusminer", // TODO: Consider XDG_DATA_HOME
|
||||
Usage: fmt.Sprintf("Specify miner repo path. flag storagerepo and env LOTUS_STORAGE_PATH are DEPRECATION, will REMOVE SOON"),
|
||||
},
|
||||
&cli.BoolFlag{
|
||||
Name: "enable-gpu-proving",
|
||||
@@ -143,7 +149,7 @@ var runCmd = &cli.Command{
|
||||
return err
|
||||
}
|
||||
if v.APIVersion != build.APIVersion {
|
||||
return xerrors.Errorf("lotus-storage-miner API version doesn't match: local: ", api.Version{APIVersion: build.APIVersion})
|
||||
return xerrors.Errorf("lotus-miner API version doesn't match: local: ", api.Version{APIVersion: build.APIVersion})
|
||||
}
|
||||
log.Infof("Remote version %s", v)
|
||||
|
||||
@@ -186,7 +192,7 @@ var runCmd = &cli.Command{
|
||||
|
||||
// Open repo
|
||||
|
||||
repoPath := cctx.String(FlagStorageRepo)
|
||||
repoPath := cctx.String(FlagWorkerRepo)
|
||||
r, err := repo.NewFS(repoPath)
|
||||
if err != nil {
|
||||
return err
|
||||
|
||||
@@ -89,7 +89,7 @@ var noncefix = &cli.Command{
|
||||
From: addr,
|
||||
To: addr,
|
||||
Value: types.NewInt(1),
|
||||
GasLimit: 10000,
|
||||
GasLimit: 100_000_000,
|
||||
GasPrice: types.NewInt(1),
|
||||
Nonce: i,
|
||||
}
|
||||
|
||||
@@ -76,7 +76,7 @@ var verifRegAddVerifierCmd = &cli.Command{
|
||||
From: fromk,
|
||||
Method: builtin.MethodsVerifiedRegistry.AddVerifier,
|
||||
GasPrice: types.NewInt(1),
|
||||
GasLimit: 300000,
|
||||
GasLimit: 100_000_000,
|
||||
Params: params,
|
||||
}
|
||||
|
||||
@@ -152,7 +152,7 @@ var verifRegVerifyClientCmd = &cli.Command{
|
||||
From: fromk,
|
||||
Method: builtin.MethodsVerifiedRegistry.AddVerifiedClient,
|
||||
GasPrice: types.NewInt(1),
|
||||
GasLimit: 300000,
|
||||
GasLimit: 100_000_000,
|
||||
Params: params,
|
||||
}
|
||||
|
||||
|
||||
@@ -23,7 +23,7 @@ import (
|
||||
|
||||
var infoCmd = &cli.Command{
|
||||
Name: "info",
|
||||
Usage: "Print storage miner info",
|
||||
Usage: "Print miner info",
|
||||
Flags: []cli.Flag{
|
||||
&cli.BoolFlag{Name: "color"},
|
||||
},
|
||||
|
||||
@@ -50,7 +50,7 @@ import (
|
||||
|
||||
var initCmd = &cli.Command{
|
||||
Name: "init",
|
||||
Usage: "Initialize a lotus storage miner repo",
|
||||
Usage: "Initialize a lotus miner repo",
|
||||
Flags: []cli.Flag{
|
||||
&cli.StringFlag{
|
||||
Name: "actor",
|
||||
@@ -107,7 +107,7 @@ var initCmd = &cli.Command{
|
||||
},
|
||||
},
|
||||
Action: func(cctx *cli.Context) error {
|
||||
log.Info("Initializing lotus storage miner")
|
||||
log.Info("Initializing lotus miner")
|
||||
|
||||
sectorSizeInt, err := units.RAMInBytes(cctx.String("sector-size"))
|
||||
if err != nil {
|
||||
@@ -151,7 +151,7 @@ var initCmd = &cli.Command{
|
||||
|
||||
log.Info("Checking if repo exists")
|
||||
|
||||
repoPath := cctx.String(FlagStorageRepo)
|
||||
repoPath := cctx.String(FlagMinerRepo)
|
||||
r, err := repo.NewFS(repoPath)
|
||||
if err != nil {
|
||||
return err
|
||||
@@ -162,7 +162,7 @@ var initCmd = &cli.Command{
|
||||
return err
|
||||
}
|
||||
if ok {
|
||||
return xerrors.Errorf("repo at '%s' is already initialized", cctx.String(FlagStorageRepo))
|
||||
return xerrors.Errorf("repo at '%s' is already initialized", cctx.String(FlagMinerRepo))
|
||||
}
|
||||
|
||||
log.Info("Checking full node version")
|
||||
@@ -236,7 +236,7 @@ var initCmd = &cli.Command{
|
||||
}
|
||||
|
||||
if err := storageMinerInit(ctx, cctx, api, r, ssize, gasPrice); err != nil {
|
||||
log.Errorf("Failed to initialize lotus-storage-miner: %+v", err)
|
||||
log.Errorf("Failed to initialize lotus-miner: %+v", err)
|
||||
path, err := homedir.Expand(repoPath)
|
||||
if err != nil {
|
||||
return err
|
||||
@@ -249,7 +249,7 @@ var initCmd = &cli.Command{
|
||||
}
|
||||
|
||||
// TODO: Point to setting storage price, maybe do it interactively or something
|
||||
log.Info("Storage miner successfully created, you can now start it with 'lotus-storage-miner run'")
|
||||
log.Info("Miner successfully created, you can now start it with 'lotus-miner run'")
|
||||
|
||||
return nil
|
||||
},
|
||||
@@ -454,11 +454,11 @@ func storageMinerInit(ctx context.Context, cctx *cli.Context, api lapi.FullNode,
|
||||
cerr := configureStorageMiner(ctx, api, a, peerid, gasPrice)
|
||||
|
||||
if err := m.Stop(ctx); err != nil {
|
||||
log.Error("failed to shut down storage miner: ", err)
|
||||
log.Error("failed to shut down miner: ", err)
|
||||
}
|
||||
|
||||
if cerr != nil {
|
||||
return xerrors.Errorf("failed to configure storage miner: %w", cerr)
|
||||
return xerrors.Errorf("failed to configure miner: %w", cerr)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -492,7 +492,7 @@ func storageMinerInit(ctx context.Context, cctx *cli.Context, api lapi.FullNode,
|
||||
}
|
||||
|
||||
if err := configureStorageMiner(ctx, api, a, peerid, gasPrice); err != nil {
|
||||
return xerrors.Errorf("failed to configure storage miner: %w", err)
|
||||
return xerrors.Errorf("failed to configure miner: %w", err)
|
||||
}
|
||||
|
||||
addr = a
|
||||
@@ -505,7 +505,7 @@ func storageMinerInit(ctx context.Context, cctx *cli.Context, api lapi.FullNode,
|
||||
addr = a
|
||||
}
|
||||
|
||||
log.Infof("Created new storage miner: %s", addr)
|
||||
log.Infof("Created new miner: %s", addr)
|
||||
if err := mds.Put(datastore.NewKey("miner-address"), addr.Bytes()); err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -557,7 +557,7 @@ func configureStorageMiner(ctx context.Context, api lapi.FullNode, addr address.
|
||||
Params: enc,
|
||||
Value: types.NewInt(0),
|
||||
GasPrice: gasPrice,
|
||||
GasLimit: 99999999,
|
||||
GasLimit: 100_000_000,
|
||||
}
|
||||
|
||||
smsg, err := api.MpoolPushMessage(ctx, msg)
|
||||
@@ -636,7 +636,7 @@ func createStorageMiner(ctx context.Context, api lapi.FullNode, peerid peer.ID,
|
||||
Method: builtin.MethodsPower.CreateMiner,
|
||||
Params: params,
|
||||
|
||||
GasLimit: 10000000,
|
||||
GasLimit: 100_000_000,
|
||||
GasPrice: gasPrice,
|
||||
}
|
||||
|
||||
@@ -654,7 +654,7 @@ func createStorageMiner(ctx context.Context, api lapi.FullNode, peerid peer.ID,
|
||||
}
|
||||
|
||||
if mw.Receipt.ExitCode != 0 {
|
||||
return address.Undef, xerrors.Errorf("create storage miner failed: exit code %d", mw.Receipt.ExitCode)
|
||||
return address.Undef, xerrors.Errorf("create miner failed: exit code %d", mw.Receipt.ExitCode)
|
||||
}
|
||||
|
||||
var retval power.CreateMinerReturn
|
||||
@@ -662,6 +662,6 @@ func createStorageMiner(ctx context.Context, api lapi.FullNode, peerid peer.ID,
|
||||
return address.Undef, err
|
||||
}
|
||||
|
||||
log.Infof("New storage miners address is: %s (%s)", retval.IDAddress, retval.RobustAddress)
|
||||
log.Infof("New miners address is: %s (%s)", retval.IDAddress, retval.RobustAddress)
|
||||
return retval.IDAddress, nil
|
||||
}
|
||||
|
||||
@@ -2,6 +2,7 @@ package main
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"os"
|
||||
|
||||
logging "github.com/ipfs/go-log/v2"
|
||||
@@ -20,7 +21,9 @@ import (
|
||||
|
||||
var log = logging.Logger("main")
|
||||
|
||||
const FlagStorageRepo = "storagerepo"
|
||||
const FlagMinerRepo = "miner-repo"
|
||||
// TODO remove after deprecation period
|
||||
const FlagMinerRepoDeprecation = "storagerepo"
|
||||
|
||||
func main() {
|
||||
lotuslog.SetupLogLevels()
|
||||
@@ -61,8 +64,8 @@ func main() {
|
||||
}
|
||||
|
||||
app := &cli.App{
|
||||
Name: "lotus-storage-miner",
|
||||
Usage: "Filecoin decentralized storage network storage miner",
|
||||
Name: "lotus-miner",
|
||||
Usage: "Filecoin decentralized storage network miner",
|
||||
Version: build.UserVersion(),
|
||||
EnableBashCompletion: true,
|
||||
Flags: []cli.Flag{
|
||||
@@ -79,9 +82,11 @@ func main() {
|
||||
Value: "~/.lotus", // TODO: Consider XDG_DATA_HOME
|
||||
},
|
||||
&cli.StringFlag{
|
||||
Name: FlagStorageRepo,
|
||||
EnvVars: []string{"LOTUS_STORAGE_PATH"},
|
||||
Value: "~/.lotusstorage", // TODO: Consider XDG_DATA_HOME
|
||||
Name: FlagMinerRepo,
|
||||
Aliases: []string{FlagMinerRepoDeprecation},
|
||||
EnvVars: []string{"LOTUS_MINER_PATH", "LOTUS_STORAGE_PATH"},
|
||||
Value: "~/.lotusminer", // TODO: Consider XDG_DATA_HOME
|
||||
Usage: fmt.Sprintf("Specify miner repo path. flag(%s) and env(LOTUS_STORAGE_PATH) are DEPRECATION, will REMOVE SOON", FlagMinerRepoDeprecation),
|
||||
},
|
||||
},
|
||||
|
||||
|
||||
@@ -6,6 +6,7 @@ import (
|
||||
"fmt"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strconv"
|
||||
"text/tabwriter"
|
||||
"time"
|
||||
|
||||
@@ -296,6 +297,7 @@ var storageDealsCmd = &cli.Command{
|
||||
setBlocklistCmd,
|
||||
getBlocklistCmd,
|
||||
resetBlocklistCmd,
|
||||
setSealDurationCmd,
|
||||
},
|
||||
}
|
||||
|
||||
@@ -357,7 +359,7 @@ var dealsListCmd = &cli.Command{
|
||||
|
||||
var getBlocklistCmd = &cli.Command{
|
||||
Name: "get-blocklist",
|
||||
Usage: "List the contents of the storage miner's piece CID blocklist",
|
||||
Usage: "List the contents of the miner's piece CID blocklist",
|
||||
Flags: []cli.Flag{
|
||||
&CidBaseFlag,
|
||||
},
|
||||
@@ -388,7 +390,7 @@ var getBlocklistCmd = &cli.Command{
|
||||
|
||||
var setBlocklistCmd = &cli.Command{
|
||||
Name: "set-blocklist",
|
||||
Usage: "Set the storage miner's list of blocklisted piece CIDs",
|
||||
Usage: "Set the miner's list of blocklisted piece CIDs",
|
||||
ArgsUsage: "[<path-of-file-containing-newline-delimited-piece-CIDs> (optional, will read from stdin if omitted)]",
|
||||
Flags: []cli.Flag{},
|
||||
Action: func(cctx *cli.Context) error {
|
||||
@@ -435,7 +437,7 @@ var setBlocklistCmd = &cli.Command{
|
||||
|
||||
var resetBlocklistCmd = &cli.Command{
|
||||
Name: "reset-blocklist",
|
||||
Usage: "Remove all entries from the storage miner's piece CID blocklist",
|
||||
Usage: "Remove all entries from the miner's piece CID blocklist",
|
||||
Flags: []cli.Flag{},
|
||||
Action: func(cctx *cli.Context) error {
|
||||
api, closer, err := lcli.GetStorageMinerAPI(cctx)
|
||||
@@ -447,3 +449,29 @@ var resetBlocklistCmd = &cli.Command{
|
||||
return api.DealsSetPieceCidBlocklist(lcli.DaemonContext(cctx), []cid.Cid{})
|
||||
},
|
||||
}
|
||||
|
||||
var setSealDurationCmd = &cli.Command{
|
||||
Name: "set-seal-duration",
|
||||
Usage: "Set the expected time, in minutes, that you expect sealing sectors to take. Deals that start before this duration will be rejected.",
|
||||
ArgsUsage: "<minutes>",
|
||||
Action: func(cctx *cli.Context) error {
|
||||
nodeApi, closer, err := lcli.GetStorageMinerAPI(cctx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer closer()
|
||||
ctx := lcli.ReqContext(cctx)
|
||||
if cctx.Args().Len() != 1 {
|
||||
return xerrors.Errorf("must pass duration in minutes")
|
||||
}
|
||||
|
||||
hs, err := strconv.ParseUint(cctx.Args().Get(0), 10, 64)
|
||||
if err != nil {
|
||||
return xerrors.Errorf("could not parse duration: %w", err)
|
||||
}
|
||||
|
||||
delay := hs * uint64(time.Minute)
|
||||
|
||||
return nodeApi.SectorSetExpectedSealDuration(ctx, time.Duration(delay))
|
||||
},
|
||||
}
|
||||
|
||||
@@ -30,7 +30,7 @@ import (
|
||||
|
||||
var runCmd = &cli.Command{
|
||||
Name: "run",
|
||||
Usage: "Start a lotus storage miner process",
|
||||
Usage: "Start a lotus miner process",
|
||||
Flags: []cli.Flag{
|
||||
&cli.StringFlag{
|
||||
Name: "api",
|
||||
@@ -86,8 +86,8 @@ var runCmd = &cli.Command{
|
||||
}
|
||||
}
|
||||
|
||||
storageRepoPath := cctx.String(FlagStorageRepo)
|
||||
r, err := repo.NewFS(storageRepoPath)
|
||||
minerRepoPath := cctx.String(FlagMinerRepo)
|
||||
r, err := repo.NewFS(minerRepoPath)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -97,7 +97,7 @@ var runCmd = &cli.Command{
|
||||
return err
|
||||
}
|
||||
if !ok {
|
||||
return xerrors.Errorf("repo at '%s' is not initialized, run 'lotus-storage-miner init' to set it up", storageRepoPath)
|
||||
return xerrors.Errorf("repo at '%s' is not initialized, run 'lotus-miner init' to set it up", minerRepoPath)
|
||||
}
|
||||
|
||||
shutdownChan := make(chan struct{})
|
||||
|
||||
@@ -10,7 +10,7 @@ import (
|
||||
|
||||
var stopCmd = &cli.Command{
|
||||
Name: "stop",
|
||||
Usage: "Stop a running lotus storage miner",
|
||||
Usage: "Stop a running lotus miner",
|
||||
Flags: []cli.Flag{},
|
||||
Action: func(cctx *cli.Context) error {
|
||||
api, closer, err := lcli.GetAPI(cctx)
|
||||
|
||||
@@ -278,7 +278,7 @@ var storageFindCmd = &cli.Command{
|
||||
}
|
||||
|
||||
if !cctx.Args().Present() {
|
||||
return xerrors.New("Usage: lotus-storage-miner storage find [sector number]")
|
||||
return xerrors.New("Usage: lotus-miner storage find [sector number]")
|
||||
}
|
||||
|
||||
snum, err := strconv.ParseUint(cctx.Args().First(), 10, 64)
|
||||
|
||||
Reference in New Issue
Block a user