Skip to content

Commit 35d2006

Browse files
authored
Merge pull request #5519 from filecoin-project/feat/info-cmd
feat: add info command
2 parents 6507f0f + 1968089 commit 35d2006

File tree

14 files changed

+329
-14
lines changed

14 files changed

+329
-14
lines changed

app/node/builder.go

+3-2
Original file line numberDiff line numberDiff line change
@@ -162,7 +162,8 @@ func (b *Builder) build(ctx context.Context) (*Node, error) {
162162
}
163163
nd.market = market.NewMarketModule(nd.chain.API(), nd.syncer.Stmgr)
164164

165-
commonModule := common.NewCommonModule()
165+
blockDelay := b.repo.Config().NetworkParams.BlockDelay
166+
nd.common = common.NewCommonModule(nd.chain, nd.network, blockDelay)
166167

167168
apiBuilder := NewBuilder()
168169
apiBuilder.NameSpace("Filecoin")
@@ -179,7 +180,7 @@ func (b *Builder) build(ctx context.Context) (*Node, error) {
179180
nd.mpool,
180181
nd.paychan,
181182
nd.market,
182-
commonModule,
183+
nd.common,
183184
)
184185

185186
if err != nil {

app/node/env.go

+1
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ type Env struct {
2626
MultiSigAPI v0api.IMultiSig
2727
MarketAPI v1api.IMarket
2828
PaychAPI v1api.IPaychan
29+
CommonAPI v1api.ICommon
2930
}
3031

3132
var _ cmds.Environment = (*Env)(nil)

app/node/node.go

+4
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ import (
1414
"github.com/filecoin-project/venus-auth/jwtclient"
1515
"github.com/filecoin-project/venus/app/submodule/blockstore"
1616
chain2 "github.com/filecoin-project/venus/app/submodule/chain"
17+
"github.com/filecoin-project/venus/app/submodule/common"
1718
configModule "github.com/filecoin-project/venus/app/submodule/config"
1819
"github.com/filecoin-project/venus/app/submodule/dagservice"
1920
"github.com/filecoin-project/venus/app/submodule/market"
@@ -92,6 +93,8 @@ type Node struct {
9293
market *market.MarketSubmodule
9394
paychan *paych.PaychSubmodule
9495

96+
common *common.CommonModule
97+
9598
//
9699
// Jsonrpc
97100
//
@@ -354,6 +357,7 @@ func (node *Node) createServerEnv(ctx context.Context) *Env {
354357
PaychAPI: node.paychan.API(),
355358
MarketAPI: node.market.API(),
356359
MultiSigAPI: &apiwrapper.WrapperV1IMultiSig{IMultiSig: node.multiSig.API(), IMessagePool: node.mpool.API()},
360+
CommonAPI: node.common,
357361
}
358362

359363
return &env

app/submodule/common/common.go

+90-3
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,15 @@ package common
22

33
import (
44
"context"
5+
"time"
56

7+
"github.com/libp2p/go-libp2p/core/peer"
8+
9+
chain2 "github.com/filecoin-project/venus/app/submodule/chain"
610
apiwrapper "github.com/filecoin-project/venus/app/submodule/common/v0api"
11+
"github.com/filecoin-project/venus/app/submodule/network"
712
"github.com/filecoin-project/venus/pkg/constants"
13+
"github.com/filecoin-project/venus/pkg/net"
814
"github.com/filecoin-project/venus/venus-shared/api/chain"
915
v0api "github.com/filecoin-project/venus/venus-shared/api/chain/v0"
1016
v1api "github.com/filecoin-project/venus/venus-shared/api/chain/v1"
@@ -13,10 +19,18 @@ import (
1319

1420
var _ v1api.ICommon = (*CommonModule)(nil)
1521

16-
type CommonModule struct{} // nolint
22+
type CommonModule struct { // nolint
23+
chainModule *chain2.ChainSubmodule
24+
netModule *network.NetworkSubmodule
25+
blockDelaySecs uint64
26+
}
1727

18-
func NewCommonModule() *CommonModule {
19-
return new(CommonModule)
28+
func NewCommonModule(chainModule *chain2.ChainSubmodule, netModule *network.NetworkSubmodule, blockDelaySecs uint64) *CommonModule {
29+
return &CommonModule{
30+
chainModule: chainModule,
31+
netModule: netModule,
32+
blockDelaySecs: blockDelaySecs,
33+
}
2034
}
2135

2236
func (cm *CommonModule) Version(ctx context.Context) (types.Version, error) {
@@ -26,6 +40,79 @@ func (cm *CommonModule) Version(ctx context.Context) (types.Version, error) {
2640
}, nil
2741
}
2842

43+
func (cm *CommonModule) NodeStatus(ctx context.Context, inclChainStatus bool) (status types.NodeStatus, err error) {
44+
curTS, err := cm.chainModule.API().ChainHead(ctx)
45+
if err != nil {
46+
return status, err
47+
}
48+
49+
status.SyncStatus.Epoch = uint64(curTS.Height())
50+
timestamp := time.Unix(int64(curTS.MinTimestamp()), 0)
51+
delta := time.Since(timestamp).Seconds()
52+
status.SyncStatus.Behind = uint64(delta / float64(cm.blockDelaySecs))
53+
54+
// get peers in the messages and blocks topics
55+
peersMsgs := make(map[peer.ID]struct{})
56+
peersBlocks := make(map[peer.ID]struct{})
57+
58+
for _, p := range cm.netModule.Pubsub.ListPeers(types.MessageTopic(cm.netModule.NetworkName)) {
59+
peersMsgs[p] = struct{}{}
60+
}
61+
62+
for _, p := range cm.netModule.Pubsub.ListPeers(types.BlockTopic(cm.netModule.NetworkName)) {
63+
peersBlocks[p] = struct{}{}
64+
}
65+
66+
// get scores for all connected and recent peers
67+
scores, err := cm.netModule.API().NetPubsubScores(ctx)
68+
if err != nil {
69+
return status, err
70+
}
71+
72+
for _, score := range scores {
73+
if score.Score.Score > net.PublishScoreThreshold {
74+
_, inMsgs := peersMsgs[score.ID]
75+
if inMsgs {
76+
status.PeerStatus.PeersToPublishMsgs++
77+
}
78+
79+
_, inBlocks := peersBlocks[score.ID]
80+
if inBlocks {
81+
status.PeerStatus.PeersToPublishBlocks++
82+
}
83+
}
84+
}
85+
86+
if inclChainStatus && status.SyncStatus.Epoch > uint64(constants.Finality) {
87+
blockCnt := 0
88+
ts := curTS
89+
90+
for i := 0; i < 100; i++ {
91+
blockCnt += len(ts.Blocks())
92+
tsk := ts.Parents()
93+
ts, err = cm.chainModule.API().ChainGetTipSet(ctx, tsk)
94+
if err != nil {
95+
return status, err
96+
}
97+
}
98+
99+
status.ChainStatus.BlocksPerTipsetLast100 = float64(blockCnt) / 100
100+
101+
for i := 100; i < int(constants.Finality); i++ {
102+
blockCnt += len(ts.Blocks())
103+
tsk := ts.Parents()
104+
ts, err = cm.chainModule.API().ChainGetTipSet(ctx, tsk)
105+
if err != nil {
106+
return status, err
107+
}
108+
}
109+
110+
status.ChainStatus.BlocksPerTipsetLastFinality = float64(blockCnt) / float64(constants.Finality)
111+
}
112+
113+
return status, nil
114+
}
115+
29116
func (cm *CommonModule) API() v1api.ICommon {
30117
return cm
31118
}

cmd/info.go

+140
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,140 @@
1+
package cmd
2+
3+
import (
4+
"bytes"
5+
"context"
6+
"fmt"
7+
"strings"
8+
"text/tabwriter"
9+
"time"
10+
11+
"github.com/dustin/go-humanize"
12+
"github.com/filecoin-project/go-state-types/big"
13+
"github.com/filecoin-project/venus/app/node"
14+
v1 "github.com/filecoin-project/venus/venus-shared/api/chain/v1"
15+
"github.com/filecoin-project/venus/venus-shared/types"
16+
cmds "github.com/ipfs/go-ipfs-cmds"
17+
)
18+
19+
var infoCmd = &cmds.Command{
20+
Helptext: cmds.HelpText{
21+
Tagline: "Print node info",
22+
},
23+
Run: func(req *cmds.Request, re cmds.ResponseEmitter, env cmds.Environment) error {
24+
ctx := req.Context
25+
chainapi := env.(*node.Env).ChainAPI
26+
buf := new(bytes.Buffer)
27+
writer := NewSilentWriter(buf)
28+
29+
netParams, err := chainapi.StateGetNetworkParams(ctx)
30+
if err != nil {
31+
return err
32+
}
33+
writer.Printf("Network: %s\n", netParams.NetworkName)
34+
35+
if err := SyncBasefeeCheck(ctx, chainapi, int64(netParams.BlockDelaySecs), writer); err != nil {
36+
return err
37+
}
38+
status, err := env.(*node.Env).CommonAPI.NodeStatus(ctx, true)
39+
if err != nil {
40+
return err
41+
}
42+
writer.Printf("Peers to: [publish messages %d] [publish blocks %d]\n", status.PeerStatus.PeersToPublishMsgs,
43+
status.PeerStatus.PeersToPublishBlocks)
44+
45+
//Chain health calculated as percentage: amount of blocks in last finality / very healthy amount of blocks in a finality (900 epochs * 5 blocks per tipset)
46+
health := (100 * (900 * status.ChainStatus.BlocksPerTipsetLastFinality) / (900 * 5))
47+
switch {
48+
case health > 85:
49+
writer.Printf("Chain health: %.f%% [healthy]\n", health)
50+
case health < 85:
51+
writer.Printf("Chain health: %.f%% [unhealthy]\n", health)
52+
}
53+
writer.Println()
54+
55+
addr, err := env.(*node.Env).WalletAPI.WalletDefaultAddress(ctx)
56+
if err == nil && !addr.Empty() {
57+
fmt.Printf("Default address: \n")
58+
balance, err := env.(*node.Env).WalletAPI.WalletBalance(ctx, addr)
59+
if err != nil {
60+
return err
61+
}
62+
writer.Printf(" %s [%s]\n", addr.String(), types.FIL(balance).Short())
63+
} else {
64+
writer.Printf("Default address: address not set\n")
65+
}
66+
writer.Println()
67+
68+
addrs := env.(*node.Env).WalletAPI.WalletAddresses(ctx)
69+
totalBalance := big.Zero()
70+
for _, addr := range addrs {
71+
totbal, err := env.(*node.Env).WalletAPI.WalletBalance(ctx, addr)
72+
if err != nil {
73+
return err
74+
}
75+
totalBalance = big.Add(totalBalance, totbal)
76+
}
77+
writer.Printf("Wallet: %v address\n", len(addrs))
78+
writer.Printf(" Total balance: %s\n", types.FIL(totalBalance).Short())
79+
80+
mbLockedSum := big.Zero()
81+
mbAvailableSum := big.Zero()
82+
for _, addr := range addrs {
83+
mbal, err := env.(*node.Env).ChainAPI.StateMarketBalance(ctx, addr, types.EmptyTSK)
84+
if err != nil {
85+
if strings.Contains(err.Error(), "actor not found") {
86+
continue
87+
}
88+
return err
89+
}
90+
mbLockedSum = big.Add(mbLockedSum, mbal.Locked)
91+
mbAvailableSum = big.Add(mbAvailableSum, mbal.Escrow)
92+
}
93+
writer.Printf(" Market locked: %s\n", types.FIL(mbLockedSum).Short())
94+
writer.Printf(" Market available: %s\n", types.FIL(mbAvailableSum).Short())
95+
writer.Println()
96+
97+
chs, err := env.(*node.Env).PaychAPI.PaychList(ctx)
98+
if err != nil {
99+
return err
100+
}
101+
writer.Printf("Payment Channels: %v channels\n", len(chs))
102+
writer.Println()
103+
104+
s, err := env.(*node.Env).NetworkAPI.NetBandwidthStats(ctx)
105+
if err != nil {
106+
return err
107+
}
108+
tw := tabwriter.NewWriter(writer.w, 6, 6, 2, ' ', 0)
109+
writer.Printf("Bandwidth:\n")
110+
fmt.Fprintf(tw, "\tTotalIn\tTotalOut\tRateIn\tRateOut\n")
111+
fmt.Fprintf(tw, "\t%s\t%s\t%s/s\t%s/s\n", humanize.Bytes(uint64(s.TotalIn)), humanize.Bytes(uint64(s.TotalOut)), humanize.Bytes(uint64(s.RateIn)), humanize.Bytes(uint64(s.RateOut)))
112+
if err := tw.Flush(); err != nil {
113+
return err
114+
}
115+
116+
return re.Emit(buf)
117+
},
118+
}
119+
120+
func SyncBasefeeCheck(ctx context.Context, chainapi v1.IChain, blockDelaySecs int64, writer *SilentWriter) error {
121+
head, err := chainapi.ChainHead(ctx)
122+
if err != nil {
123+
return err
124+
}
125+
126+
var syncStatus string
127+
switch {
128+
case time.Now().Unix()-int64(head.MinTimestamp()) < blockDelaySecs*3/2: // within 1.5 epochs
129+
syncStatus = "[sync ok]"
130+
case time.Now().Unix()-int64(head.MinTimestamp()) < blockDelaySecs*5: // within 5 epochs
131+
syncStatus = fmt.Sprintf("[sync slow (%s behind)]", time.Since(time.Unix(int64(head.MinTimestamp()), 0)).Truncate(time.Second))
132+
default:
133+
syncStatus = fmt.Sprintf("[sync behind! (%s behind)]", time.Since(time.Unix(int64(head.MinTimestamp()), 0)).Truncate(time.Second))
134+
}
135+
basefee := head.MinTicketBlock().ParentBaseFee
136+
137+
writer.Printf("Chain: %s [basefee %s] [epoch %v]\n", syncStatus, types.FIL(basefee).Short(), head.Height())
138+
139+
return nil
140+
}

cmd/main.go

+6-1
Original file line numberDiff line numberDiff line change
@@ -99,6 +99,7 @@ START RUNNING VENUS
9999
daemon - Start a venus daemon process
100100
wallet - Manage wallet
101101
msig - Interact with a multisig wallet
102+
info - Print node info
102103
103104
VIEW DATA STRUCTURES
104105
chain - Inspect the filecoin blockchain
@@ -112,8 +113,11 @@ MESSAGE COMMANDS
112113
send - Send message
113114
mpool - Manage the message pool
114115
116+
MINER COMMANDS
117+
miner - Interact with actors
118+
115119
State COMMANDS
116-
state - query states of the filecoin network
120+
state - query states of the filecoin network
117121
118122
Paych COMMANDS
119123
paych - Manage payment channels
@@ -170,6 +174,7 @@ var rootSubcmdsDaemon = map[string]*cmds.Command{
170174
"miner": minerCmd,
171175
"paych": paychCmd,
172176
"msig": multisigCmd,
177+
"info": infoCmd,
173178
}
174179

175180
func init() {

venus-devtool/go.mod

+1-1
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ require (
99
github.com/filecoin-project/go-fil-markets v1.24.1-rc1
1010
github.com/filecoin-project/go-jsonrpc v0.1.8
1111
github.com/filecoin-project/go-state-types v0.9.8
12-
github.com/filecoin-project/lotus v1.18.0-rc3.0.20221019204926-84050170b922
12+
github.com/filecoin-project/lotus v1.18.0
1313
github.com/filecoin-project/venus v0.0.0-00010101000000-000000000000
1414
github.com/ipfs/go-block-format v0.0.3
1515
github.com/ipfs/go-cid v0.2.0

venus-devtool/go.sum

+2-2
Original file line numberDiff line numberDiff line change
@@ -333,8 +333,8 @@ github.com/filecoin-project/go-statemachine v1.0.2 h1:421SSWBk8GIoCoWYYTE/d+qCWc
333333
github.com/filecoin-project/go-statestore v0.2.0 h1:cRRO0aPLrxKQCZ2UOQbzFGn4WDNdofHZoGPjfNaAo5Q=
334334
github.com/filecoin-project/go-statestore v0.2.0/go.mod h1:8sjBYbS35HwPzct7iT4lIXjLlYyPor80aU7t7a/Kspo=
335335
github.com/filecoin-project/index-provider v0.8.1 h1:ggoBWvMSWR91HZQCWfv8SZjoTGNyJBwNMLuN9bJZrbU=
336-
github.com/filecoin-project/lotus v1.18.0-rc3.0.20221019204926-84050170b922 h1:kI8N7+iIqpfOjhImNaZJT6MHIB66NcK6qQteNF8E8t8=
337-
github.com/filecoin-project/lotus v1.18.0-rc3.0.20221019204926-84050170b922/go.mod h1:/kWfuN/hzqOvdzbYxaBrvN82HAQ85nRMli7KcnoSE6E=
336+
github.com/filecoin-project/lotus v1.18.0 h1:HxdShHMEZT703n9KlQTgPVoUF/ocidMC/d3TzwxzTP8=
337+
github.com/filecoin-project/lotus v1.18.0/go.mod h1:jJih5ApnJZssc/wWsLJm+IWnfy8YaCyaDbvs/wTIVDk=
338338
github.com/filecoin-project/pubsub v1.0.0 h1:ZTmT27U07e54qV1mMiQo4HDr0buo8I1LDHBYLXlsNXM=
339339
github.com/filecoin-project/pubsub v1.0.0/go.mod h1:GkpB33CcUtUNrLPhJgfdy4FDx4OMNR9k+46DHx/Lqrg=
340340
github.com/filecoin-project/specs-actors v0.9.13/go.mod h1:TS1AW/7LbG+615j4NsjMK1qlpAwaFsG9w0V2tg2gSao=

venus-shared/api/chain/v1/common.go

+8-1
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,14 @@
11
package v1
22

3-
import "github.com/filecoin-project/venus/venus-shared/api"
3+
import (
4+
"context"
5+
6+
"github.com/filecoin-project/venus/venus-shared/api"
7+
"github.com/filecoin-project/venus/venus-shared/types"
8+
)
49

510
type ICommon interface {
611
api.Version
12+
13+
NodeStatus(ctx context.Context, inclChainStatus bool) (types.NodeStatus, error) //perm:read
714
}

0 commit comments

Comments
 (0)