pond: Miner state viewer

This commit is contained in:
Łukasz Magiera 2019-10-27 11:27:21 +01:00
parent c1076a0c7d
commit 53cbe3446d
6 changed files with 74 additions and 11 deletions

View File

@ -123,7 +123,7 @@ type FullNode interface {
StateGetActor(ctx context.Context, actor address.Address, ts *types.TipSet) (*types.Actor, error) StateGetActor(ctx context.Context, actor address.Address, ts *types.TipSet) (*types.Actor, error)
StateReadState(ctx context.Context, act *types.Actor, ts *types.TipSet) (*ActorState, error) StateReadState(ctx context.Context, act *types.Actor, ts *types.TipSet) (*ActorState, error)
StateMinerSectors(context.Context, address.Address) ([]*SectorInfo, error) StateMinerSectors(context.Context, address.Address, *types.TipSet) ([]*SectorInfo, error)
StateMinerProvingSet(context.Context, address.Address, *types.TipSet) ([]*SectorInfo, error) StateMinerProvingSet(context.Context, address.Address, *types.TipSet) ([]*SectorInfo, error)
StateMinerPower(context.Context, address.Address, *types.TipSet) (MinerPower, error) StateMinerPower(context.Context, address.Address, *types.TipSet) (MinerPower, error)
StateMinerWorker(context.Context, address.Address, *types.TipSet) (address.Address, error) StateMinerWorker(context.Context, address.Address, *types.TipSet) (address.Address, error)

View File

@ -86,7 +86,7 @@ type FullNodeStruct struct {
ClientRetrieve func(ctx context.Context, order RetrievalOrder, path string) error `perm:"admin"` ClientRetrieve func(ctx context.Context, order RetrievalOrder, path string) error `perm:"admin"`
ClientQueryAsk func(ctx context.Context, p peer.ID, miner address.Address) (*types.SignedStorageAsk, error) `perm:"read"` ClientQueryAsk func(ctx context.Context, p peer.ID, miner address.Address) (*types.SignedStorageAsk, error) `perm:"read"`
StateMinerSectors func(context.Context, address.Address) ([]*SectorInfo, error) `perm:"read"` StateMinerSectors func(context.Context, address.Address, *types.TipSet) ([]*SectorInfo, error) `perm:"read"`
StateMinerProvingSet func(context.Context, address.Address, *types.TipSet) ([]*SectorInfo, error) `perm:"read"` StateMinerProvingSet func(context.Context, address.Address, *types.TipSet) ([]*SectorInfo, error) `perm:"read"`
StateMinerPower func(context.Context, address.Address, *types.TipSet) (MinerPower, error) `perm:"read"` StateMinerPower func(context.Context, address.Address, *types.TipSet) (MinerPower, error) `perm:"read"`
StateMinerWorker func(context.Context, address.Address, *types.TipSet) (address.Address, error) `perm:"read"` StateMinerWorker func(context.Context, address.Address, *types.TipSet) (address.Address, error) `perm:"read"`
@ -338,8 +338,8 @@ func (c *FullNodeStruct) SyncSubmitBlock(ctx context.Context, blk *types.BlockMs
return c.Internal.SyncSubmitBlock(ctx, blk) return c.Internal.SyncSubmitBlock(ctx, blk)
} }
func (c *FullNodeStruct) StateMinerSectors(ctx context.Context, addr address.Address) ([]*SectorInfo, error) { func (c *FullNodeStruct) StateMinerSectors(ctx context.Context, addr address.Address, ts *types.TipSet) ([]*SectorInfo, error) {
return c.Internal.StateMinerSectors(ctx, addr) return c.Internal.StateMinerSectors(ctx, addr, ts)
} }
func (c *FullNodeStruct) StateMinerProvingSet(ctx context.Context, addr address.Address, ts *types.TipSet) ([]*SectorInfo, error) { func (c *FullNodeStruct) StateMinerProvingSet(ctx context.Context, addr address.Address, ts *types.TipSet) ([]*SectorInfo, error) {

View File

@ -78,7 +78,7 @@ var stateSectorsCmd = &cli.Command{
return err return err
} }
sectors, err := api.StateMinerSectors(ctx, maddr) sectors, err := api.StateMinerSectors(ctx, maddr, nil)
if err != nil { if err != nil {
return err return err
} }

View File

@ -78,7 +78,7 @@ class Block extends React.Component {
) )
} }
return (<Window className="CristalScroll" initialSize={{width: 950, height: 400}} onClose={this.props.onClose} title={`Block ${this.props.cid['/']}`}> return (<Window className="CristalScroll" initialSize={{width: 1050, height: 400}} onClose={this.props.onClose} title={`Block ${this.props.cid['/']}`}>
{content} {content}
</Window>) </Window>)
} }

View File

@ -4,12 +4,14 @@ import CID from "cids";
import * as multihash from "multihashes"; import * as multihash from "multihashes";
import code from "./chain/code"; import code from "./chain/code";
import Address from "./Address"; import Address from "./Address";
import Fil from "./Fil";
class State extends React.Component { class State extends React.Component {
byCode = { byCode = {
[code.init]: InitState, [code.init]: InitState,
[code.power]: PowerState, [code.power]: PowerState,
[code.market]: MarketState, [code.market]: MarketState,
[code.miner]: MinerState,
} }
constructor(props) { constructor(props) {
@ -33,17 +35,17 @@ class State extends React.Component {
let state let state
if(this.byCode[this.state.code]) { if(this.byCode[this.state.code]) {
const Stelem = this.byCode[this.state.code] const Stelem = this.byCode[this.state.code]
state = <Stelem client={this.props.client} mountWindow={this.props.mountWindow} tipset={this.props.tipset}/> state = <Stelem addr={this.props.addr} actor={this.props.actor} client={this.props.client} mountWindow={this.props.mountWindow} tipset={this.props.tipset}/>
} else { } else {
state = <div>{Object.keys(this.state.State).map(k => <div key={k}>{k}: <span>{JSON.stringify(this.state.State[k])}</span></div>)}</div> state = <div>{Object.keys(this.state.State).map(k => <div key={k}>{k}: <span>{JSON.stringify(this.state.State[k])}</span></div>)}</div>
} }
const content = <div className="State"> const content = <div className="State">
<div>Balance: {this.state.Balance}</div> <div>Balance: <Fil>{this.state.Balance}</Fil></div>
<div>---</div> <div>---</div>
{state} {state}
</div> </div>
return <Window initialSize={{width: 700, height: 400}} onClose={this.props.onClose} title={`Actor ${this.props.addr} ${this.props.tipset && this.props.tipset.Height || ''} ${this.state.code}`}> return <Window initialSize={{width: 850, height: 400}} onClose={this.props.onClose} title={`Actor ${this.props.addr} ${this.props.tipset && this.props.tipset.Height || ''} ${this.state.code}`}>
{content} {content}
</Window> </Window>
} }
@ -133,4 +135,65 @@ class MarketState extends React.Component {
} }
} }
class MinerState extends React.Component {
constructor(props) {
super(props)
this.state = {state: {}, sectorSize: -1, worker: "", networkPower: 0, sectors: {}}
}
async componentDidMount() {
const tipset = await this.props.client.call("Filecoin.ChainHead", []) // TODO: from props
const state = await this.props.client.call('Filecoin.StateReadState', [this.props.actor, tipset])
const sectorSize = await this.props.client.call("Filecoin.StateMinerSectorSize", [this.props.addr, tipset])
const worker = await this.props.client.call("Filecoin.StateMinerWorker", [this.props.addr, tipset])
const tpow = await this.props.client.call("Filecoin.StateMinerPower", [this.props.addr, tipset])
const networkPower = tpow.TotalPower
let sectors = {}
const sset = await this.props.client.call("Filecoin.StateMinerSectors", [this.props.addr, tipset]) || []
const pset = await this.props.client.call("Filecoin.StateMinerProvingSet", [this.props.addr, tipset]) || []
sset.forEach(s => sectors[s.SectorID] = {...s, sectorSet: true})
pset.forEach(s => sectors[s.SectorID] = {...(sectors[s.SectorID] || s), provingSet: true})
this.setState({state, sectorSize, worker, networkPower, sectors})
}
render() {
if (!this.state.worker) {
return <span>(...)</span>
}
let state = this.state.state.State
return <div>
<div>Worker: <Address addr={this.state.worker} client={this.props.client} mountWindow={this.props.mountWindow}/></div>
<div>Sector Size: <b>{this.state.sectorSize/1024}</b> KiB</div>
<div>Power: <b>{state.Power}</b> (<b>{state.Power/this.state.networkPower*100}</b>%)</div>
<div>Proving Period End: <b>{state.ProvingPeriodEnd}</b></div>
<div>
<div>----</div>
<div>Sectors:</div>
<table style={{overflowY: "scroll"}}>
<thead>
<tr><td>ID</td><td>CommD</td><td>CommR</td><td>SectorSet</td><td>Proving</td></tr>
</thead>
<tbody>
{Object.keys(this.state.sectors).map(sid => <tr key={sid} style={{whiteSpace: 'nowrap'}}>
<td>{sid}</td>
<td>{this.state.sectors[sid].CommD}</td>
<td>{this.state.sectors[sid].CommR}</td>
<td>{this.state.sectors[sid].sectorSet ? 'X' : ' '}</td>
<td>{this.state.sectors[sid].provingSet ? 'X' : ' '}</td>
</tr>)}
</tbody>
</table>
</div>
</div>
}
}
export default State export default State

View File

@ -37,8 +37,8 @@ type StateAPI struct {
Chain *store.ChainStore Chain *store.ChainStore
} }
func (a *StateAPI) StateMinerSectors(ctx context.Context, addr address.Address) ([]*api.SectorInfo, error) { func (a *StateAPI) StateMinerSectors(ctx context.Context, addr address.Address, ts *types.TipSet) ([]*api.SectorInfo, error) {
return stmgr.GetMinerSectorSet(ctx, a.StateManager, nil, addr) return stmgr.GetMinerSectorSet(ctx, a.StateManager, ts, addr)
} }
func (a *StateAPI) StateMinerProvingSet(ctx context.Context, addr address.Address, ts *types.TipSet) ([]*api.SectorInfo, error) { func (a *StateAPI) StateMinerProvingSet(ctx context.Context, addr address.Address, ts *types.TipSet) ([]*api.SectorInfo, error) {