Merge remote-tracking branch 'origin/master' into feat/v1-api

This commit is contained in:
Łukasz Magiera 2021-03-25 14:13:21 +01:00
commit 759ea5b14f
33 changed files with 636 additions and 208 deletions

View File

@ -1,5 +1,15 @@
# Lotus changelog
# 1.5.3 / 2021-03-24
This is a patch release of Lotus that introduces small fixes to the Storage FSM.
## Changes
- storagefsm: Fix double unlock with ready WaitDeals sectors (https://github.com/filecoin-project/lotus/pull/5783)
- backupds: Allow larger values in write log (https://github.com/filecoin-project/lotus/pull/5776)
- storagefsm: Don't log the SectorRestart event (https://github.com/filecoin-project/lotus/pull/5779)
# 1.5.2 / 2021-03-11
This is an hotfix release of Lotus that fixes a critical bug introduced in v1.5.1 in the miner windowPoSt logic. This upgrade is only affecting miner nodes.

View File

@ -85,11 +85,11 @@ const (
// operation calls after Close() has returned, but it may not happen for
// operations in progress. Those are likely to fail with a different error.
type Blockstore struct {
DB *badger.DB
// state is guarded by atomic.
// state is accessed atomically
state int64
DB *badger.DB
prefixing bool
prefix []byte
prefixLen int

View File

@ -61,6 +61,7 @@ type State interface {
VerifyDealsForActivation(
minerAddr address.Address, deals []abi.DealID, currEpoch, sectorExpiry abi.ChainEpoch,
) (weight, verifiedWeight abi.DealWeight, err error)
NextID() (abi.DealID, error)
}
type BalanceTable interface {

View File

@ -105,6 +105,10 @@ func (s *state0) VerifyDealsForActivation(
return market0.ValidateDealsForActivation(&s.State, s.store, deals, minerAddr, sectorExpiry, currEpoch)
}
func (s *state0) NextID() (abi.DealID, error) {
return s.State.NextID, nil
}
type balanceTable0 struct {
*adt0.BalanceTable
}

View File

@ -106,6 +106,10 @@ func (s *state2) VerifyDealsForActivation(
return w, vw, err
}
func (s *state2) NextID() (abi.DealID, error) {
return s.State.NextID, nil
}
type balanceTable2 struct {
*adt2.BalanceTable
}

View File

@ -106,6 +106,10 @@ func (s *state3) VerifyDealsForActivation(
return w, vw, err
}
func (s *state3) NextID() (abi.DealID, error) {
return s.State.NextID, nil
}
type balanceTable3 struct {
*adt3.BalanceTable
}

View File

@ -255,7 +255,7 @@ func (sm *StateManager) Replay(ctx context.Context, ts *types.TipSet, mcid cid.C
}
return nil
})
if err != nil && err != errHaltExecution {
if err != nil && !xerrors.Is(err, errHaltExecution) {
return nil, nil, xerrors.Errorf("unexpected error during execution: %w", err)
}

View File

@ -13,16 +13,16 @@ import (
"github.com/filecoin-project/lotus/node/repo"
)
var authCmd = &cli.Command{
var AuthCmd = &cli.Command{
Name: "auth",
Usage: "Manage RPC permissions",
Subcommands: []*cli.Command{
authCreateAdminToken,
authApiInfoToken,
AuthCreateAdminToken,
AuthApiInfoToken,
},
}
var authCreateAdminToken = &cli.Command{
var AuthCreateAdminToken = &cli.Command{
Name: "create-token",
Usage: "Create token",
Flags: []cli.Flag{
@ -70,7 +70,7 @@ var authCreateAdminToken = &cli.Command{
},
}
var authApiInfoToken = &cli.Command{
var AuthApiInfoToken = &cli.Command{
Name: "api-info",
Usage: "Get token with API info required to connect to this node",
Flags: []cli.Flag{
@ -90,7 +90,7 @@ var authApiInfoToken = &cli.Command{
ctx := ReqContext(cctx)
if !cctx.IsSet("perm") {
return xerrors.New("--perm flag not set")
return xerrors.New("--perm flag not set, use with one of: read, write, sign, admin")
}
perm := cctx.String("perm")

View File

@ -38,31 +38,31 @@ import (
types "github.com/filecoin-project/lotus/chain/types"
)
var chainCmd = &cli.Command{
var ChainCmd = &cli.Command{
Name: "chain",
Usage: "Interact with filecoin blockchain",
Subcommands: []*cli.Command{
chainHeadCmd,
chainGetBlock,
chainReadObjCmd,
chainDeleteObjCmd,
chainStatObjCmd,
chainGetMsgCmd,
chainSetHeadCmd,
chainListCmd,
chainGetCmd,
chainBisectCmd,
chainExportCmd,
slashConsensusFault,
chainGasPriceCmd,
chainInspectUsage,
chainDecodeCmd,
chainEncodeCmd,
chainDisputeSetCmd,
ChainHeadCmd,
ChainGetBlock,
ChainReadObjCmd,
ChainDeleteObjCmd,
ChainStatObjCmd,
ChainGetMsgCmd,
ChainSetHeadCmd,
ChainListCmd,
ChainGetCmd,
ChainBisectCmd,
ChainExportCmd,
SlashConsensusFault,
ChainGasPriceCmd,
ChainInspectUsage,
ChainDecodeCmd,
ChainEncodeCmd,
ChainDisputeSetCmd,
},
}
var chainHeadCmd = &cli.Command{
var ChainHeadCmd = &cli.Command{
Name: "head",
Usage: "Print chain head",
Action: func(cctx *cli.Context) error {
@ -85,7 +85,7 @@ var chainHeadCmd = &cli.Command{
},
}
var chainGetBlock = &cli.Command{
var ChainGetBlock = &cli.Command{
Name: "getblock",
Usage: "Get a block and print its details",
ArgsUsage: "[blockCid]",
@ -176,7 +176,7 @@ func apiMsgCids(in []lapi.Message) []cid.Cid {
return out
}
var chainReadObjCmd = &cli.Command{
var ChainReadObjCmd = &cli.Command{
Name: "read-obj",
Usage: "Read the raw bytes of an object",
ArgsUsage: "[objectCid]",
@ -203,7 +203,7 @@ var chainReadObjCmd = &cli.Command{
},
}
var chainDeleteObjCmd = &cli.Command{
var ChainDeleteObjCmd = &cli.Command{
Name: "delete-obj",
Usage: "Delete an object from the chain blockstore",
Description: "WARNING: Removing wrong objects from the chain blockstore may lead to sync issues",
@ -240,7 +240,7 @@ var chainDeleteObjCmd = &cli.Command{
},
}
var chainStatObjCmd = &cli.Command{
var ChainStatObjCmd = &cli.Command{
Name: "stat-obj",
Usage: "Collect size and ipld link counts for objs",
ArgsUsage: "[cid]",
@ -287,7 +287,7 @@ var chainStatObjCmd = &cli.Command{
},
}
var chainGetMsgCmd = &cli.Command{
var ChainGetMsgCmd = &cli.Command{
Name: "getmessage",
Usage: "Get and print a message by its cid",
ArgsUsage: "[messageCid]",
@ -335,7 +335,7 @@ var chainGetMsgCmd = &cli.Command{
},
}
var chainSetHeadCmd = &cli.Command{
var ChainSetHeadCmd = &cli.Command{
Name: "sethead",
Usage: "manually set the local nodes head tipset (Caution: normally only used for recovery)",
ArgsUsage: "[tipsetkey]",
@ -384,7 +384,7 @@ var chainSetHeadCmd = &cli.Command{
},
}
var chainInspectUsage = &cli.Command{
var ChainInspectUsage = &cli.Command{
Name: "inspect-usage",
Usage: "Inspect block space usage of a given tipset",
Flags: []cli.Flag{
@ -529,7 +529,7 @@ var chainInspectUsage = &cli.Command{
},
}
var chainListCmd = &cli.Command{
var ChainListCmd = &cli.Command{
Name: "list",
Aliases: []string{"love"},
Usage: "View a segment of the chain",
@ -658,7 +658,7 @@ var chainListCmd = &cli.Command{
},
}
var chainGetCmd = &cli.Command{
var ChainGetCmd = &cli.Command{
Name: "get",
Usage: "Get chain DAG node by path",
ArgsUsage: "[path]",
@ -905,7 +905,7 @@ func printTipSet(format string, ts *types.TipSet) {
fmt.Println(format)
}
var chainBisectCmd = &cli.Command{
var ChainBisectCmd = &cli.Command{
Name: "bisect",
Usage: "bisect chain for an event",
ArgsUsage: "[minHeight maxHeight path shellCommand <shellCommandArgs (if any)>]",
@ -1028,7 +1028,7 @@ var chainBisectCmd = &cli.Command{
},
}
var chainExportCmd = &cli.Command{
var ChainExportCmd = &cli.Command{
Name: "export",
Usage: "export chain to a car file",
ArgsUsage: "[outputPath]",
@ -1106,7 +1106,7 @@ var chainExportCmd = &cli.Command{
},
}
var slashConsensusFault = &cli.Command{
var SlashConsensusFault = &cli.Command{
Name: "slash-consensus",
Usage: "Report consensus fault",
ArgsUsage: "[blockCid1 blockCid2]",
@ -1227,7 +1227,7 @@ var slashConsensusFault = &cli.Command{
},
}
var chainGasPriceCmd = &cli.Command{
var ChainGasPriceCmd = &cli.Command{
Name: "gas-price",
Usage: "Estimate gas prices",
Action: func(cctx *cli.Context) error {
@ -1254,7 +1254,7 @@ var chainGasPriceCmd = &cli.Command{
},
}
var chainDecodeCmd = &cli.Command{
var ChainDecodeCmd = &cli.Command{
Name: "decode",
Usage: "decode various types",
Subcommands: []*cli.Command{
@ -1334,7 +1334,7 @@ var chainDecodeParamsCmd = &cli.Command{
},
}
var chainEncodeCmd = &cli.Command{
var ChainEncodeCmd = &cli.Command{
Name: "encode",
Usage: "encode various types",
Subcommands: []*cli.Command{

View File

@ -498,9 +498,10 @@ func interactiveDeal(cctx *cli.Context) error {
var ds lapi.DataCIDSize
// find
var candidateAsks []*storagemarket.StorageAsk
var candidateAsks []QueriedAsk
var budget types.FIL
var dealCount int64
var medianPing, maxAcceptablePing time.Duration
var a address.Address
if from := cctx.String("from"); from != "" {
@ -660,6 +661,18 @@ uiLoop:
return err
}
if len(asks) == 0 {
printErr(xerrors.Errorf("no asks found"))
continue uiLoop
}
medianPing = asks[len(asks)/2].Ping
var avgPing time.Duration
for _, ask := range asks {
avgPing += ask.Ping
}
avgPing /= time.Duration(len(asks))
for _, ask := range asks {
if ask.Ask.MinPieceSize > ds.PieceSize {
continue
@ -667,10 +680,48 @@ uiLoop:
if ask.Ask.MaxPieceSize < ds.PieceSize {
continue
}
candidateAsks = append(candidateAsks, ask.Ask)
candidateAsks = append(candidateAsks, ask)
}
afmt.Printf("Found %d candidate asks\n", len(candidateAsks))
afmt.Printf("Average network latency: %s; Median latency: %s\n", avgPing.Truncate(time.Millisecond), medianPing.Truncate(time.Millisecond))
state = "max-ping"
case "max-ping":
maxAcceptablePing = medianPing
afmt.Printf("Maximum network latency (default: %s) (ms): ", maxAcceptablePing.Truncate(time.Millisecond))
_latStr, _, err := rl.ReadLine()
latStr := string(_latStr)
if err != nil {
printErr(xerrors.Errorf("reading maximum latency: %w", err))
continue
}
if latStr != "" {
maxMs, err := strconv.ParseInt(latStr, 10, 64)
if err != nil {
printErr(xerrors.Errorf("parsing FIL: %w", err))
continue uiLoop
}
maxAcceptablePing = time.Millisecond * time.Duration(maxMs)
}
var goodAsks []QueriedAsk
for _, candidateAsk := range candidateAsks {
if candidateAsk.Ping < maxAcceptablePing {
goodAsks = append(goodAsks, candidateAsk)
}
}
if len(goodAsks) == 0 {
afmt.Printf("no asks left after filtering for network latency\n")
continue uiLoop
}
afmt.Printf("%d asks left after filtering for network latency\n", len(goodAsks))
candidateAsks = goodAsks
state = "find-budget"
case "find-budget":
afmt.Printf("Proposing from %s, Current Balance: %s\n", a, types.FIL(fromBal))
@ -689,11 +740,11 @@ uiLoop:
continue uiLoop
}
var goodAsks []*storagemarket.StorageAsk
var goodAsks []QueriedAsk
for _, ask := range candidateAsks {
p := ask.Price
p := ask.Ask.Price
if verified {
p = ask.VerifiedPrice
p = ask.Ask.VerifiedPrice
}
epochPrice := types.BigDiv(types.BigMul(p, types.NewInt(uint64(ds.PieceSize))), gib)
@ -733,9 +784,9 @@ uiLoop:
pickedAsks = []*storagemarket.StorageAsk{}
for _, ask := range candidateAsks {
p := ask.Price
p := ask.Ask.Price
if verified {
p = ask.VerifiedPrice
p = ask.Ask.VerifiedPrice
}
epochPrice := types.BigDiv(types.BigMul(p, types.NewInt(uint64(ds.PieceSize))), gib)
@ -745,7 +796,7 @@ uiLoop:
continue
}
pickedAsks = append(pickedAsks, ask)
pickedAsks = append(pickedAsks, ask.Ask)
remainingBudget = big.Sub(remainingBudget, totalPrice)
if len(pickedAsks) == int(dealCount) {

View File

@ -56,12 +56,12 @@ var GetStorageMinerAPI = cliutil.GetStorageMinerAPI
var GetWorkerAPI = cliutil.GetWorkerAPI
var CommonCommands = []*cli.Command{
netCmd,
authCmd,
logCmd,
waitApiCmd,
fetchParamCmd,
pprofCmd,
NetCmd,
AuthCmd,
LogCmd,
WaitApiCmd,
FetchParamCmd,
PprofCmd,
VersionCmd,
}
@ -71,16 +71,16 @@ var Commands = []*cli.Command{
WithCategory("basic", clientCmd),
WithCategory("basic", multisigCmd),
WithCategory("basic", paychCmd),
WithCategory("developer", authCmd),
WithCategory("developer", mpoolCmd),
WithCategory("developer", stateCmd),
WithCategory("developer", chainCmd),
WithCategory("developer", logCmd),
WithCategory("developer", waitApiCmd),
WithCategory("developer", fetchParamCmd),
WithCategory("network", netCmd),
WithCategory("network", syncCmd),
pprofCmd,
WithCategory("developer", AuthCmd),
WithCategory("developer", MpoolCmd),
WithCategory("developer", StateCmd),
WithCategory("developer", ChainCmd),
WithCategory("developer", LogCmd),
WithCategory("developer", WaitApiCmd),
WithCategory("developer", FetchParamCmd),
WithCategory("network", NetCmd),
WithCategory("network", SyncCmd),
PprofCmd,
VersionCmd,
}

View File

@ -35,7 +35,7 @@ type minerDeadline struct {
index uint64
}
var chainDisputeSetCmd = &cli.Command{
var ChainDisputeSetCmd = &cli.Command{
Name: "disputer",
Usage: "interact with the window post disputer",
Flags: []cli.Flag{

View File

@ -7,16 +7,16 @@ import (
"golang.org/x/xerrors"
)
var logCmd = &cli.Command{
var LogCmd = &cli.Command{
Name: "log",
Usage: "Manage logging",
Subcommands: []*cli.Command{
logList,
logSetLevel,
LogList,
LogSetLevel,
},
}
var logList = &cli.Command{
var LogList = &cli.Command{
Name: "list",
Usage: "List log systems",
Action: func(cctx *cli.Context) error {
@ -41,7 +41,7 @@ var logList = &cli.Command{
},
}
var logSetLevel = &cli.Command{
var LogSetLevel = &cli.Command{
Name: "set-level",
Usage: "Set log level",
ArgsUsage: "[level]",

View File

@ -22,22 +22,22 @@ import (
"github.com/filecoin-project/lotus/node/config"
)
var mpoolCmd = &cli.Command{
var MpoolCmd = &cli.Command{
Name: "mpool",
Usage: "Manage message pool",
Subcommands: []*cli.Command{
mpoolPending,
mpoolClear,
mpoolSub,
mpoolStat,
mpoolReplaceCmd,
mpoolFindCmd,
mpoolConfig,
mpoolGasPerfCmd,
MpoolPending,
MpoolClear,
MpoolSub,
MpoolStat,
MpoolReplaceCmd,
MpoolFindCmd,
MpoolConfig,
MpoolGasPerfCmd,
},
}
var mpoolPending = &cli.Command{
var MpoolPending = &cli.Command{
Name: "pending",
Usage: "Get pending messages",
Flags: []cli.Flag{
@ -132,7 +132,7 @@ var mpoolPending = &cli.Command{
},
}
var mpoolClear = &cli.Command{
var MpoolClear = &cli.Command{
Name: "clear",
Usage: "Clear all pending messages from the mpool (USE WITH CARE)",
Flags: []cli.Flag{
@ -165,7 +165,7 @@ var mpoolClear = &cli.Command{
},
}
var mpoolSub = &cli.Command{
var MpoolSub = &cli.Command{
Name: "sub",
Usage: "Subscribe to mpool changes",
Action: func(cctx *cli.Context) error {
@ -197,7 +197,7 @@ var mpoolSub = &cli.Command{
},
}
var mpoolStat = &cli.Command{
var MpoolStat = &cli.Command{
Name: "stat",
Usage: "print mempool stats",
Flags: []cli.Flag{
@ -356,7 +356,7 @@ var mpoolStat = &cli.Command{
},
}
var mpoolReplaceCmd = &cli.Command{
var MpoolReplaceCmd = &cli.Command{
Name: "replace",
Usage: "replace a message in the mempool",
Flags: []cli.Flag{
@ -509,7 +509,7 @@ var mpoolReplaceCmd = &cli.Command{
},
}
var mpoolFindCmd = &cli.Command{
var MpoolFindCmd = &cli.Command{
Name: "find",
Usage: "find a message in the mempool",
Flags: []cli.Flag{
@ -592,7 +592,7 @@ var mpoolFindCmd = &cli.Command{
},
}
var mpoolConfig = &cli.Command{
var MpoolConfig = &cli.Command{
Name: "config",
Usage: "get or set current mpool configuration",
ArgsUsage: "[new-config]",
@ -637,7 +637,7 @@ var mpoolConfig = &cli.Command{
},
}
var mpoolGasPerfCmd = &cli.Command{
var MpoolGasPerfCmd = &cli.Command{
Name: "gas-perf",
Usage: "Check gas performance of messages in mempool",
Flags: []cli.Flag{

View File

@ -23,16 +23,16 @@ import (
"github.com/filecoin-project/lotus/lib/addrutil"
)
var netCmd = &cli.Command{
var NetCmd = &cli.Command{
Name: "net",
Usage: "Manage P2P Network",
Subcommands: []*cli.Command{
NetPeers,
netConnect,
NetConnect,
NetListen,
NetId,
netFindPeer,
netScores,
NetFindPeer,
NetScores,
NetReachability,
NetBandwidthCmd,
NetBlockCmd,
@ -112,7 +112,7 @@ var NetPeers = &cli.Command{
},
}
var netScores = &cli.Command{
var NetScores = &cli.Command{
Name: "scores",
Usage: "Print peers' pubsub scores",
Flags: []cli.Flag{
@ -175,7 +175,7 @@ var NetListen = &cli.Command{
},
}
var netConnect = &cli.Command{
var NetConnect = &cli.Command{
Name: "connect",
Usage: "Connect to a peer",
ArgsUsage: "[peerMultiaddr|minerActorAddress]",
@ -264,7 +264,7 @@ var NetId = &cli.Command{
},
}
var netFindPeer = &cli.Command{
var NetFindPeer = &cli.Command{
Name: "findpeer",
Usage: "Find the addresses of a given peerID",
ArgsUsage: "[peerId]",

View File

@ -9,7 +9,7 @@ import (
"github.com/filecoin-project/lotus/build"
)
var fetchParamCmd = &cli.Command{
var FetchParamCmd = &cli.Command{
Name: "fetch-params",
Usage: "Fetch proving parameters",
ArgsUsage: "[sectorSize]",

View File

@ -11,7 +11,7 @@ import (
"github.com/filecoin-project/lotus/node/repo"
)
var pprofCmd = &cli.Command{
var PprofCmd = &cli.Command{
Name: "pprof",
Hidden: true,
Subcommands: []*cli.Command{

View File

@ -41,7 +41,7 @@ import (
"github.com/filecoin-project/lotus/chain/types"
)
var stateCmd = &cli.Command{
var StateCmd = &cli.Command{
Name: "state",
Usage: "Interact with and query filecoin chain state",
Flags: []cli.Flag{
@ -51,32 +51,32 @@ var stateCmd = &cli.Command{
},
},
Subcommands: []*cli.Command{
statePowerCmd,
stateSectorsCmd,
stateActiveSectorsCmd,
stateListActorsCmd,
stateListMinersCmd,
stateCircSupplyCmd,
stateSectorCmd,
stateGetActorCmd,
stateLookupIDCmd,
stateReplayCmd,
stateSectorSizeCmd,
stateReadStateCmd,
stateListMessagesCmd,
stateComputeStateCmd,
stateCallCmd,
stateGetDealSetCmd,
stateWaitMsgCmd,
stateSearchMsgCmd,
stateMinerInfo,
stateMarketCmd,
stateExecTraceCmd,
stateNtwkVersionCmd,
StatePowerCmd,
StateSectorsCmd,
StateActiveSectorsCmd,
StateListActorsCmd,
StateListMinersCmd,
StateCircSupplyCmd,
StateSectorCmd,
StateGetActorCmd,
StateLookupIDCmd,
StateReplayCmd,
StateSectorSizeCmd,
StateReadStateCmd,
StateListMessagesCmd,
StateComputeStateCmd,
StateCallCmd,
StateGetDealSetCmd,
StateWaitMsgCmd,
StateSearchMsgCmd,
StateMinerInfo,
StateMarketCmd,
StateExecTraceCmd,
StateNtwkVersionCmd,
},
}
var stateMinerInfo = &cli.Command{
var StateMinerInfo = &cli.Command{
Name: "miner-info",
Usage: "Retrieve miner information",
ArgsUsage: "[minerAddress]",
@ -219,7 +219,7 @@ func ParseTipSetRef(ctx context.Context, api api.FullNode, tss string) (*types.T
return ts, nil
}
var statePowerCmd = &cli.Command{
var StatePowerCmd = &cli.Command{
Name: "power",
Usage: "Query network or miner power",
ArgsUsage: "[<minerAddress> (optional)]",
@ -263,7 +263,7 @@ var statePowerCmd = &cli.Command{
},
}
var stateSectorsCmd = &cli.Command{
var StateSectorsCmd = &cli.Command{
Name: "sectors",
Usage: "Query the sector set of a miner",
ArgsUsage: "[minerAddress]",
@ -303,7 +303,7 @@ var stateSectorsCmd = &cli.Command{
},
}
var stateActiveSectorsCmd = &cli.Command{
var StateActiveSectorsCmd = &cli.Command{
Name: "active-sectors",
Usage: "Query the active sector set of a miner",
ArgsUsage: "[minerAddress]",
@ -343,7 +343,7 @@ var stateActiveSectorsCmd = &cli.Command{
},
}
var stateExecTraceCmd = &cli.Command{
var StateExecTraceCmd = &cli.Command{
Name: "exec-trace",
Usage: "Get the execution trace of a given message",
ArgsUsage: "<messageCid>",
@ -411,7 +411,7 @@ var stateExecTraceCmd = &cli.Command{
},
}
var stateReplayCmd = &cli.Command{
var StateReplayCmd = &cli.Command{
Name: "replay",
Usage: "Replay a particular message",
ArgsUsage: "<messageCid>",
@ -476,7 +476,7 @@ var stateReplayCmd = &cli.Command{
},
}
var stateGetDealSetCmd = &cli.Command{
var StateGetDealSetCmd = &cli.Command{
Name: "get-deal",
Usage: "View on-chain deal info",
ArgsUsage: "[dealId]",
@ -518,7 +518,7 @@ var stateGetDealSetCmd = &cli.Command{
},
}
var stateListMinersCmd = &cli.Command{
var StateListMinersCmd = &cli.Command{
Name: "list-miners",
Usage: "list all miners in the network",
Flags: []cli.Flag{
@ -590,7 +590,7 @@ func getDealsCounts(ctx context.Context, lapi api.FullNode) (map[address.Address
return out, nil
}
var stateListActorsCmd = &cli.Command{
var StateListActorsCmd = &cli.Command{
Name: "list-actors",
Usage: "list all actors in the network",
Action: func(cctx *cli.Context) error {
@ -620,7 +620,7 @@ var stateListActorsCmd = &cli.Command{
},
}
var stateGetActorCmd = &cli.Command{
var StateGetActorCmd = &cli.Command{
Name: "get-actor",
Usage: "Print actor information",
ArgsUsage: "[actorrAddress]",
@ -664,7 +664,7 @@ var stateGetActorCmd = &cli.Command{
},
}
var stateLookupIDCmd = &cli.Command{
var StateLookupIDCmd = &cli.Command{
Name: "lookup",
Usage: "Find corresponding ID address",
ArgsUsage: "[address]",
@ -715,7 +715,7 @@ var stateLookupIDCmd = &cli.Command{
},
}
var stateSectorSizeCmd = &cli.Command{
var StateSectorSizeCmd = &cli.Command{
Name: "sector-size",
Usage: "Look up miners sector size",
ArgsUsage: "[minerAddress]",
@ -752,7 +752,7 @@ var stateSectorSizeCmd = &cli.Command{
},
}
var stateReadStateCmd = &cli.Command{
var StateReadStateCmd = &cli.Command{
Name: "read-state",
Usage: "View a json representation of an actors state",
ArgsUsage: "[actorAddress]",
@ -794,7 +794,7 @@ var stateReadStateCmd = &cli.Command{
},
}
var stateListMessagesCmd = &cli.Command{
var StateListMessagesCmd = &cli.Command{
Name: "list-messages",
Usage: "list messages on chain matching given criteria",
Flags: []cli.Flag{
@ -907,7 +907,7 @@ var stateListMessagesCmd = &cli.Command{
},
}
var stateComputeStateCmd = &cli.Command{
var StateComputeStateCmd = &cli.Command{
Name: "compute-state",
Usage: "Perform state computations",
Flags: []cli.Flag{
@ -1365,7 +1365,7 @@ func jsonReturn(code cid.Cid, method abi.MethodNum, ret []byte) (string, error)
return string(b), err
}
var stateWaitMsgCmd = &cli.Command{
var StateWaitMsgCmd = &cli.Command{
Name: "wait-msg",
Usage: "Wait for a message to appear on chain",
ArgsUsage: "[messageCid]",
@ -1407,7 +1407,7 @@ var stateWaitMsgCmd = &cli.Command{
},
}
var stateSearchMsgCmd = &cli.Command{
var StateSearchMsgCmd = &cli.Command{
Name: "search-msg",
Usage: "Search to see whether a message has appeared on chain",
ArgsUsage: "[messageCid]",
@ -1484,7 +1484,7 @@ func printMsg(ctx context.Context, api api.FullNode, msg cid.Cid, mw *lapi.MsgLo
return nil
}
var stateCallCmd = &cli.Command{
var StateCallCmd = &cli.Command{
Name: "call",
Usage: "Invoke a method on an actor locally",
ArgsUsage: "[toAddress methodId <param1 param2 ...> (optional)]",
@ -1692,7 +1692,7 @@ func parseParamsForMethod(act cid.Cid, method uint64, args []string) ([]byte, er
return buf.Bytes(), nil
}
var stateCircSupplyCmd = &cli.Command{
var StateCircSupplyCmd = &cli.Command{
Name: "circulating-supply",
Usage: "Get the exact current circulating supply of Filecoin",
Flags: []cli.Flag{
@ -1741,7 +1741,7 @@ var stateCircSupplyCmd = &cli.Command{
},
}
var stateSectorCmd = &cli.Command{
var StateSectorCmd = &cli.Command{
Name: "sector",
Usage: "Get miner sector info",
ArgsUsage: "[miner address] [sector number]",
@ -1815,7 +1815,7 @@ var stateSectorCmd = &cli.Command{
},
}
var stateMarketCmd = &cli.Command{
var StateMarketCmd = &cli.Command{
Name: "market",
Usage: "Inspect the storage market actor",
Subcommands: []*cli.Command{
@ -1861,7 +1861,7 @@ var stateMarketBalanceCmd = &cli.Command{
},
}
var stateNtwkVersionCmd = &cli.Command{
var StateNtwkVersionCmd = &cli.Command{
Name: "network-version",
Usage: "Returns the network version",
Action: func(cctx *cli.Context) error {

View File

@ -15,20 +15,20 @@ import (
"github.com/filecoin-project/lotus/build"
)
var syncCmd = &cli.Command{
var SyncCmd = &cli.Command{
Name: "sync",
Usage: "Inspect or interact with the chain syncer",
Subcommands: []*cli.Command{
syncStatusCmd,
syncWaitCmd,
syncMarkBadCmd,
syncUnmarkBadCmd,
syncCheckBadCmd,
syncCheckpointCmd,
SyncStatusCmd,
SyncWaitCmd,
SyncMarkBadCmd,
SyncUnmarkBadCmd,
SyncCheckBadCmd,
SyncCheckpointCmd,
},
}
var syncStatusCmd = &cli.Command{
var SyncStatusCmd = &cli.Command{
Name: "status",
Usage: "check sync status",
Action: func(cctx *cli.Context) error {
@ -81,7 +81,7 @@ var syncStatusCmd = &cli.Command{
},
}
var syncWaitCmd = &cli.Command{
var SyncWaitCmd = &cli.Command{
Name: "wait",
Usage: "Wait for sync to be complete",
Flags: []cli.Flag{
@ -102,7 +102,7 @@ var syncWaitCmd = &cli.Command{
},
}
var syncMarkBadCmd = &cli.Command{
var SyncMarkBadCmd = &cli.Command{
Name: "mark-bad",
Usage: "Mark the given block as bad, will prevent syncing to a chain that contains it",
ArgsUsage: "[blockCid]",
@ -127,7 +127,7 @@ var syncMarkBadCmd = &cli.Command{
},
}
var syncUnmarkBadCmd = &cli.Command{
var SyncUnmarkBadCmd = &cli.Command{
Name: "unmark-bad",
Usage: "Unmark the given block as bad, makes it possible to sync to a chain containing it",
Flags: []cli.Flag{
@ -162,7 +162,7 @@ var syncUnmarkBadCmd = &cli.Command{
},
}
var syncCheckBadCmd = &cli.Command{
var SyncCheckBadCmd = &cli.Command{
Name: "check-bad",
Usage: "check if the given block was marked bad, and for what reason",
ArgsUsage: "[blockCid]",
@ -198,7 +198,7 @@ var syncCheckBadCmd = &cli.Command{
},
}
var syncCheckpointCmd = &cli.Command{
var SyncCheckpointCmd = &cli.Command{
Name: "checkpoint",
Usage: "mark a certain tipset as checkpointed; the node will never fork away from this tipset",
ArgsUsage: "[tipsetKey]",

View File

@ -7,7 +7,7 @@ import (
"github.com/urfave/cli/v2"
)
var waitApiCmd = &cli.Command{
var WaitApiCmd = &cli.Command{
Name: "wait-api",
Usage: "Wait for lotus api to come online",
Action: func(cctx *cli.Context) error {

75
cmd/lotus-shed/base64.go Normal file
View File

@ -0,0 +1,75 @@
package main
import (
"encoding/base64"
"fmt"
"io"
"io/ioutil"
"os"
"strings"
"github.com/filecoin-project/go-state-types/abi"
"github.com/filecoin-project/go-address"
"github.com/urfave/cli/v2"
)
var base64Cmd = &cli.Command{
Name: "base64",
Description: "multiformats base64",
Flags: []cli.Flag{
&cli.BoolFlag{
Name: "decodeAddr",
Value: false,
Usage: "Decode a base64 addr",
},
&cli.BoolFlag{
Name: "decodeBig",
Value: false,
Usage: "Decode a base64 big",
},
},
Action: func(cctx *cli.Context) error {
var input io.Reader
if cctx.Args().Len() == 0 {
input = os.Stdin
} else {
input = strings.NewReader(cctx.Args().First())
}
bytes, err := ioutil.ReadAll(input)
if err != nil {
return nil
}
decoded, err := base64.RawStdEncoding.DecodeString(strings.TrimSpace(string(bytes)))
if err != nil {
return err
}
if cctx.Bool("decodeAddr") {
addr, err := address.NewFromBytes(decoded)
if err != nil {
return err
}
fmt.Println(addr)
return nil
}
if cctx.Bool("decodeBig") {
var val abi.TokenAmount
err = val.UnmarshalBinary(decoded)
if err != nil {
return err
}
fmt.Println(val)
}
return nil
},
}

View File

@ -180,8 +180,11 @@ var datastoreBackupStatCmd = &cli.Command{
}
defer f.Close() // nolint:errcheck
var keys, kbytes, vbytes uint64
err = backupds.ReadBackup(f, func(key datastore.Key, value []byte) error {
var keys, logs, kbytes, vbytes uint64
err = backupds.ReadBackup(f, func(key datastore.Key, value []byte, log bool) error {
if log {
logs++
}
keys++
kbytes += uint64(len(key.String()))
vbytes += uint64(len(value))
@ -192,6 +195,7 @@ var datastoreBackupStatCmd = &cli.Command{
}
fmt.Println("Keys: ", keys)
fmt.Println("Log values: ", log)
fmt.Println("Key bytes: ", units.BytesSize(float64(kbytes)))
fmt.Println("Value bytes: ", units.BytesSize(float64(vbytes)))
@ -225,7 +229,7 @@ var datastoreBackupListCmd = &cli.Command{
defer f.Close() // nolint:errcheck
printKv := kvPrinter(cctx.Bool("top-level"), cctx.String("get-enc"))
err = backupds.ReadBackup(f, func(key datastore.Key, value []byte) error {
err = backupds.ReadBackup(f, func(key datastore.Key, value []byte, _ bool) error {
return printKv(key.String(), value)
})
if err != nil {

View File

@ -16,6 +16,7 @@ func main() {
logging.SetLogLevel("*", "INFO")
local := []*cli.Command{
base64Cmd,
base32Cmd,
base16Cmd,
bitFieldCmd,
@ -52,6 +53,7 @@ func main() {
rpcCmd,
cidCmd,
blockmsgidCmd,
signaturesCmd,
}
app := &cli.App{

View File

@ -6,6 +6,7 @@ import (
"golang.org/x/xerrors"
"github.com/filecoin-project/go-address"
"github.com/filecoin-project/go-bitfield"
"github.com/filecoin-project/go-state-types/abi"
"github.com/filecoin-project/go-state-types/big"
@ -34,6 +35,10 @@ var terminateSectorCmd = &cli.Command{
Usage: "Forcefully terminate a sector (WARNING: This means losing power and pay a one-time termination penalty(including collateral) for the terminated sector)",
ArgsUsage: "[sectorNum1 sectorNum2 ...]",
Flags: []cli.Flag{
&cli.StringFlag{
Name: "actor",
Usage: "specify the address of miner actor",
},
&cli.BoolFlag{
Name: "really-do-it",
Usage: "pass this flag if you know what you are doing",
@ -44,6 +49,15 @@ var terminateSectorCmd = &cli.Command{
return fmt.Errorf("at least one sector must be specified")
}
var maddr address.Address
if act := cctx.String("actor"); act != "" {
var err error
maddr, err = address.NewFromString(act)
if err != nil {
return fmt.Errorf("parsing address %s: %w", act, err)
}
}
if !cctx.Bool("really-do-it") {
return fmt.Errorf("this is a command for advanced users, only use it if you are sure of what you are doing")
}
@ -54,17 +68,19 @@ var terminateSectorCmd = &cli.Command{
}
defer closer()
api, acloser, err := lcli.GetStorageMinerAPI(cctx)
if err != nil {
return err
}
defer acloser()
ctx := lcli.ReqContext(cctx)
maddr, err := api.ActorAddress(ctx)
if err != nil {
return err
if maddr.Empty() {
api, acloser, err := lcli.GetStorageMinerAPI(cctx)
if err != nil {
return err
}
defer acloser()
maddr, err = api.ActorAddress(ctx)
if err != nil {
return err
}
}
mi, err := nodeApi.StateMinerInfo(ctx, maddr, types.EmptyTSK)
@ -147,28 +163,45 @@ var terminateSectorPenaltyEstimationCmd = &cli.Command{
Name: "termination-estimate",
Usage: "Estimate the termination penalty",
ArgsUsage: "[sectorNum1 sectorNum2 ...]",
Flags: []cli.Flag{
&cli.StringFlag{
Name: "actor",
Usage: "specify the address of miner actor",
},
},
Action: func(cctx *cli.Context) error {
if cctx.Args().Len() < 1 {
return fmt.Errorf("at least one sector must be specified")
}
var maddr address.Address
if act := cctx.String("actor"); act != "" {
var err error
maddr, err = address.NewFromString(act)
if err != nil {
return fmt.Errorf("parsing address %s: %w", act, err)
}
}
nodeApi, closer, err := lcli.GetFullNodeAPI(cctx)
if err != nil {
return err
}
defer closer()
api, acloser, err := lcli.GetStorageMinerAPI(cctx)
if err != nil {
return err
}
defer acloser()
ctx := lcli.ReqContext(cctx)
maddr, err := api.ActorAddress(ctx)
if err != nil {
return err
if maddr.Empty() {
api, acloser, err := lcli.GetStorageMinerAPI(cctx)
if err != nil {
return err
}
defer acloser()
maddr, err = api.ActorAddress(ctx)
if err != nil {
return err
}
}
mi, err := nodeApi.StateMinerInfo(ctx, maddr, types.EmptyTSK)

View File

@ -0,0 +1,74 @@
package main
import (
"encoding/hex"
"fmt"
"strconv"
"github.com/filecoin-project/go-state-types/crypto"
"github.com/filecoin-project/lotus/lib/sigs"
"github.com/filecoin-project/go-address"
"github.com/urfave/cli/v2"
"golang.org/x/xerrors"
)
var signaturesCmd = &cli.Command{
Name: "signatures",
Usage: "tools involving signatures",
Subcommands: []*cli.Command{
sigsVerifyVoteCmd,
},
}
var sigsVerifyVoteCmd = &cli.Command{
Name: "verify-vote",
Description: "can be used to verify signed votes being submitted for FILPolls",
Usage: "<FIPnumber> <signingAddress> <signature>",
Action: func(cctx *cli.Context) error {
if cctx.Args().Len() != 3 {
return xerrors.Errorf("usage: verify-vote <FIPnumber> <signingAddress> <signature>")
}
fip, err := strconv.ParseInt(cctx.Args().First(), 10, 64)
if err != nil {
return xerrors.Errorf("couldn't parse FIP number: %w", err)
}
addr, err := address.NewFromString(cctx.Args().Get(1))
if err != nil {
return xerrors.Errorf("couldn't parse signing address: %w", err)
}
sigBytes, err := hex.DecodeString(cctx.Args().Get(2))
if err != nil {
return xerrors.Errorf("couldn't parse sig: %w", err)
}
var sig crypto.Signature
if err := sig.UnmarshalBinary(sigBytes); err != nil {
return xerrors.Errorf("couldn't unmarshal sig: %w", err)
}
switch fip {
case 14:
approve := []byte("7 - Approve")
if sigs.Verify(&sig, addr, approve) == nil {
fmt.Println("valid vote for approving FIP-0014")
return nil
}
reject := []byte("7 - Reject")
if sigs.Verify(&sig, addr, reject) == nil {
fmt.Println("valid vote for rejecting FIP-0014")
return nil
}
return xerrors.Errorf("invalid vote for FIP-0014!")
default:
return xerrors.Errorf("unrecognized FIP number")
}
},
}

View File

@ -55,7 +55,7 @@ func (d *Datastore) startLog(logdir string) error {
return xerrors.Errorf("creating log: %w", err)
}
} else {
l, err = d.openLog(filepath.Join(logdir, latest))
l, latest, err = d.openLog(filepath.Join(logdir, latest))
if err != nil {
return xerrors.Errorf("opening log: %w", err)
}
@ -97,6 +97,8 @@ type logfile struct {
file *os.File
}
var compactThresh = 2
func (d *Datastore) createLog(logdir string) (*logfile, string, error) {
p := filepath.Join(logdir, strconv.FormatInt(time.Now().Unix(), 10)+".log.cbor")
log.Infow("creating log", "file", p)
@ -119,32 +121,36 @@ func (d *Datastore) createLog(logdir string) (*logfile, string, error) {
}, filepath.Base(p), nil
}
func (d *Datastore) openLog(p string) (*logfile, error) {
func (d *Datastore) openLog(p string) (*logfile, string, error) {
log.Infow("opening log", "file", p)
lh, err := d.child.Get(loghead)
if err != nil {
return nil, xerrors.Errorf("checking log head (logfile '%s'): %w", p, err)
return nil, "", xerrors.Errorf("checking log head (logfile '%s'): %w", p, err)
}
lhp := strings.Split(string(lh), ";")
if len(lhp) != 3 {
return nil, xerrors.Errorf("expected loghead to have 3 parts")
return nil, "", xerrors.Errorf("expected loghead to have 3 parts")
}
if lhp[0] != filepath.Base(p) {
return nil, xerrors.Errorf("loghead log file doesn't match, opening %s, expected %s", p, lhp[0])
return nil, "", xerrors.Errorf("loghead log file doesn't match, opening %s, expected %s", p, lhp[0])
}
f, err := os.OpenFile(p, os.O_RDWR, 0644)
if err != nil {
return nil, err
return nil, "", err
}
var lastLogHead string
var openCount, logvals int64
var openCount, vals, logvals int64
// check file integrity
err = ReadBackup(f, func(k datastore.Key, v []byte) error {
logvals++
err = ReadBackup(f, func(k datastore.Key, v []byte, log bool) error {
if log {
logvals++
} else {
vals++
}
if k == loghead {
lastLogHead = string(v)
openCount++
@ -152,32 +158,53 @@ func (d *Datastore) openLog(p string) (*logfile, error) {
return nil
})
if err != nil {
return nil, xerrors.Errorf("reading backup part of the logfile: %w", err)
return nil, "", xerrors.Errorf("reading backup part of the logfile: %w", err)
}
if string(lh) != lastLogHead {
return nil, xerrors.Errorf("loghead didn't match, expected '%s', last in logfile '%s'", string(lh), lastLogHead)
return nil, "", xerrors.Errorf("loghead didn't match, expected '%s', last in logfile '%s'", string(lh), lastLogHead)
}
// make sure we're at the end of the file
at, err := f.Seek(0, io.SeekCurrent)
if err != nil {
return nil, xerrors.Errorf("get current logfile offset: %w", err)
return nil, "", xerrors.Errorf("get current logfile offset: %w", err)
}
end, err := f.Seek(0, io.SeekEnd)
if err != nil {
return nil, xerrors.Errorf("get current logfile offset: %w", err)
return nil, "", xerrors.Errorf("get current logfile offset: %w", err)
}
if at != end {
return nil, xerrors.Errorf("logfile %s validated %d bytes, but the file has %d bytes (%d more)", p, at, end, end-at)
return nil, "", xerrors.Errorf("logfile %s validated %d bytes, but the file has %d bytes (%d more)", p, at, end, end-at)
}
log.Infow("log opened", "file", p, "openCount", openCount, "logValues", logvals)
compact := logvals > vals*int64(compactThresh)
if compact {
log.Infow("compacting log", "current", p, "openCount", openCount, "baseValues", vals, "logValues", logvals)
if err := f.Close(); err != nil {
return nil, "", xerrors.Errorf("closing current log: %w", err)
}
l, latest, err := d.createLog(filepath.Dir(p))
if err != nil {
return nil, "", xerrors.Errorf("creating compacted log: %w", err)
}
log.Infow("compacted log created, cleaning up old", "old", p, "new", latest)
if err := os.Remove(p); err != nil {
l.Close() // nolint
return nil, "", xerrors.Errorf("cleaning up old logfile: %w", err)
}
return l, latest, nil
}
log.Infow("log opened", "file", p, "openCount", openCount, "baseValues", vals, "logValues", logvals)
// todo: maybe write a magic 'opened at' entry; pad the log to filesystem page to prevent more exotic types of corruption
return &logfile{
file: f,
}, nil
}, filepath.Base(p), nil
}
func (l *logfile) writeLogHead(logname string, ds datastore.Batching) error {

View File

@ -11,7 +11,7 @@ import (
"golang.org/x/xerrors"
)
func ReadBackup(r io.Reader, cb func(key datastore.Key, value []byte) error) error {
func ReadBackup(r io.Reader, cb func(key datastore.Key, value []byte, log bool) error) error {
scratch := make([]byte, 9)
// read array[2](
@ -61,7 +61,7 @@ func ReadBackup(r io.Reader, cb func(key datastore.Key, value []byte) error) err
return xerrors.Errorf("reading value: %w", err)
}
if err := cb(key, value); err != nil {
if err := cb(key, value, false); err != nil {
return err
}
}
@ -110,7 +110,7 @@ func ReadBackup(r io.Reader, cb func(key datastore.Key, value []byte) error) err
key := datastore.NewKey(string(ent.Key))
if err := cb(key, ent.Value); err != nil {
if err := cb(key, ent.Value, true); err != nil {
return err
}
}
@ -122,7 +122,7 @@ func RestoreInto(r io.Reader, dest datastore.Batching) error {
return xerrors.Errorf("creating batch: %w", err)
}
err = ReadBackup(r, func(key datastore.Key, value []byte) error {
err = ReadBackup(r, func(key datastore.Key, value []byte, _ bool) error {
if err := batch.Put(key, value); err != nil {
return xerrors.Errorf("put key: %w", err)
}

View File

@ -37,7 +37,13 @@ const (
evtTypeBlockMined = iota
)
// returns a callback reporting whether we mined a blocks in this round
// waitFunc is expected to pace block mining at the configured network rate.
//
// baseTime is the timestamp of the mining base, i.e. the timestamp
// of the tipset we're planning to construct upon.
//
// Upon each mining loop iteration, the returned callback is called reporting
// whether we mined a block in this round or not.
type waitFunc func(ctx context.Context, baseTime uint64) (func(bool, abi.ChainEpoch, error), abi.ChainEpoch, error)
func randTimeOffset(width time.Duration) time.Duration {
@ -48,6 +54,8 @@ func randTimeOffset(width time.Duration) time.Duration {
return val - (width / 2)
}
// NewMiner instantiates a miner with a concrete WinningPoStProver and a miner
// address (which can be different from the worker's address).
func NewMiner(api api.FullNode, epp gen.WinningPoStProver, addr address.Address, sf *slashfilter.SlashFilter, j journal.Journal) *Miner {
arc, err := lru.NewARC(10000)
if err != nil {
@ -59,7 +67,16 @@ func NewMiner(api api.FullNode, epp gen.WinningPoStProver, addr address.Address,
epp: epp,
address: addr,
waitFunc: func(ctx context.Context, baseTime uint64) (func(bool, abi.ChainEpoch, error), abi.ChainEpoch, error) {
// Wait around for half the block time in case other parents come in
// wait around for half the block time in case other parents come in
//
// if we're mining a block in the past via catch-up/rush mining,
// such as when recovering from a network halt, this sleep will be
// for a negative duration, and therefore **will return
// immediately**.
//
// the result is that we WILL NOT wait, therefore fast-forwarding
// and thus healing the chain by backfilling it with null rounds
// rapidly.
deadline := baseTime + build.PropagationDelaySecs
baseT := time.Unix(int64(deadline), 0)
@ -79,6 +96,9 @@ func NewMiner(api api.FullNode, epp gen.WinningPoStProver, addr address.Address,
}
}
// Miner encapsulates the mining processes of the system.
//
// Refer to the godocs on mineOne and mine methods for more detail.
type Miner struct {
api api.FullNode
@ -91,15 +111,20 @@ type Miner struct {
waitFunc waitFunc
// lastWork holds the last MiningBase we built upon.
lastWork *MiningBase
sf *slashfilter.SlashFilter
sf *slashfilter.SlashFilter
// minedBlockHeights is a safeguard that caches the last heights we mined.
// It is consulted before publishing a newly mined block, for a sanity check
// intended to avoid slashings in case of a bug.
minedBlockHeights *lru.ARCCache
evtTypes [1]journal.EventType
journal journal.Journal
}
// Address returns the address of the miner.
func (m *Miner) Address() address.Address {
m.lk.Lock()
defer m.lk.Unlock()
@ -107,7 +132,9 @@ func (m *Miner) Address() address.Address {
return m.address
}
func (m *Miner) Start(ctx context.Context) error {
// Start starts the mining operation. It spawns a goroutine and returns
// immediately. Start is not idempotent.
func (m *Miner) Start(_ context.Context) error {
m.lk.Lock()
defer m.lk.Unlock()
if m.stop != nil {
@ -118,6 +145,8 @@ func (m *Miner) Start(ctx context.Context) error {
return nil
}
// Stop stops the mining operation. It is not idempotent, and multiple adjacent
// calls to Stop will fail.
func (m *Miner) Stop(ctx context.Context) error {
m.lk.Lock()
@ -145,6 +174,28 @@ func (m *Miner) niceSleep(d time.Duration) bool {
}
}
// mine runs the mining loop. It performs the following:
//
// 1. Queries our current best currently-known mining candidate (tipset to
// build upon).
// 2. Waits until the propagation delay of the network has elapsed (currently
// 6 seconds). The waiting is done relative to the timestamp of the best
// candidate, which means that if it's way in the past, we won't wait at
// all (e.g. in catch-up or rush mining).
// 3. After the wait, we query our best mining candidate. This will be the one
// we'll work with.
// 4. Sanity check that we _actually_ have a new mining base to mine on. If
// not, wait one epoch + propagation delay, and go back to the top.
// 5. We attempt to mine a block, by calling mineOne (refer to godocs). This
// method will either return a block if we were eligible to mine, or nil
// if we weren't.
// 6a. If we mined a block, we update our state and push it out to the network
// via gossipsub.
// 6b. If we didn't mine a block, we consider this to be a nil round on top of
// the mining base we selected. If other miner or miners on the network
// were eligible to mine, we will receive their blocks via gossipsub and
// we will select that tipset on the next iteration of the loop, thus
// discarding our null round.
func (m *Miner) mine(ctx context.Context) {
ctx, span := trace.StartSpan(ctx, "/mine")
defer span.End()
@ -305,11 +356,19 @@ minerLoop:
}
}
// MiningBase is the tipset on top of which we plan to construct our next block.
// Refer to godocs on GetBestMiningCandidate.
type MiningBase struct {
TipSet *types.TipSet
NullRounds abi.ChainEpoch
}
// GetBestMiningCandidate implements the fork choice rule from a miner's
// perspective.
//
// It obtains the current chain head (HEAD), and compares it to the last tipset
// we selected as our mining base (LAST). If HEAD's weight is larger than
// LAST's weight, it selects HEAD to build on. Else, it selects LAST.
func (m *Miner) GetBestMiningCandidate(ctx context.Context) (*MiningBase, error) {
m.lk.Lock()
defer m.lk.Unlock()

View File

@ -52,6 +52,13 @@ You only need to do this once, after which, you can enable and start the miner.
Do you want to access your lotus daemon remotely? Learn how to setup token authentication
and use client libraries from lotus docs.
https://docs.filecoin.io/build/lotus/enable-remote-api-access/
For more information, see https://docs.filecoin.io/
Found a bug? let us know! https://github.com/filecoin-project/lotus
Chat with us on slack! https://filecoinproject.slack.com/archives/CEGN061C5

View File

@ -1,5 +1,12 @@
PS1="[\h \w] ⨎ "
export PROMT_DIRTRIM=1
# Where to find the lotus repo
export LOTUS_PATH=/var/lib/lotus
export LOTUS_MINER_PATH=/var/lib/lotus-miner
# The miner is not running in this image by default.
# export LOTUS_MINER_PATH=/var/lib/lotus-miner
# To access the lotus node remotely, the following environment variable may be used.
# export FULLNODE_API_INFO=<token>:/ip4/<public-ip>/tcp/1234/http

View File

@ -20,7 +20,23 @@ locals {
source "amazon-ebs" "lotus" {
ami_name = "lotus-${var.lotus_network}-${var.git_tag}-${local.timestamp}"
ami_regions = [
"ap-east-1",
"ap-northeast-1",
"ap-northeast-2",
"ap-northeast-3",
"ap-south-1",
"ap-southeast-1",
"ap-southeast-2",
"ca-central-1",
"eu-central-1",
"eu-north-1",
"eu-west-1",
"eu-west-2",
"eu-west-3",
"sa-east-1",
"us-east-1",
"us-east-2",
"us-west-1",
"us-west-2",
]
ami_groups = [
@ -37,7 +53,7 @@ source "amazon-ebs" "lotus" {
instance_type = "t2.micro"
source_ami_filter {
filters = {
name = "ubuntu-minimal/images/*ubuntu-focal-20.04-amd64-minimal*"
name = "ubuntu/images/*ubuntu-focal-20.04-amd64-server-*"
root-device-type = "ebs"
virtualization-type = "hvm"
}
@ -85,6 +101,10 @@ build {
source = "./tools/packer/systemd/lotus-miner.service"
destination = "lotus-miner.service"
}
provisioner "file" {
source = "./tools/packer/repo/config.toml"
destination = "config.toml"
}
provisioner "file" {
source = "./tools/packer/etc/motd"
destination = "motd"

View File

@ -0,0 +1,36 @@
[API]
ListenAddress = "/ip4/0.0.0.0/tcp/1234/http"
# RemoteListenAddress = ""
# Timeout = "30s"
#
[Libp2p]
ListenAddresses = ["/ip4/0.0.0.0/tcp/5678", "/ip6/::/tcp/5678"]
# AnnounceAddresses = []
# NoAnnounceAddresses = []
# ConnMgrLow = 150
# ConnMgrHigh = 180
# ConnMgrGrace = "20s"
#
[Pubsub]
# Bootstrapper = false
# RemoteTracer = "/dns4/pubsub-tracer.filecoin.io/tcp/4001/p2p/QmTd6UvR47vUidRNZ1ZKXHrAFhqTJAD27rKL9XYghEKgKX"
#
[Client]
# UseIpfs = false
# IpfsOnlineMode = false
# IpfsMAddr = ""
# IpfsUseForRetrieval = false
# SimultaneousTransfers = 20
#
[Metrics]
# Nickname = ""
# HeadNotifs = false
#
[Wallet]
# RemoteBackend = ""
# EnableLedger = false
# DisableLocal = false
#
[Fees]
# DefaultMaxFee = "0.007 FIL"
#

View File

@ -22,11 +22,14 @@ MANAGED_FILES=(
/lib/systemd/system/lotus-daemon.service
/lib/systemd/system/lotus-miner.service
/etc/motd
/var/lib/lotus/config.toml
)
# install libs.
apt update
apt -y install libhwloc15 ocl-icd-libopencl1
export DEBIAN_FRONTEND=noninteractive
apt-get update
apt-get -y install libhwloc15 ocl-icd-libopencl1 ufw
apt-get -y upgrade -q -y -u -o Dpkg::Options::="--force-confold"
ln -s /usr/lib/x86_64-linux-gnu/libhwloc.so.15 /usr/lib/x86_64-linux-gnu/libhwloc.so.5
# Create lotus user
@ -55,3 +58,10 @@ done
# Enable services
systemctl daemon-reload
systemctl enable lotus-daemon
# Setup firewall
ufw enable
ufw default deny incoming
ufw default allow outgoing
ufw allow ssh
ufw allow 5678 #libp2p