pond: basic state inspection
This commit is contained in:
parent
e430f86b69
commit
2229fae79d
@ -52,6 +52,11 @@ type SectorInfo struct {
|
||||
CommR []byte
|
||||
}
|
||||
|
||||
type ActorState struct {
|
||||
Balance types.BigInt
|
||||
State interface{}
|
||||
}
|
||||
|
||||
type Common interface {
|
||||
// Auth
|
||||
AuthVerify(ctx context.Context, token string) ([]string, error)
|
||||
@ -85,6 +90,8 @@ type FullNode interface {
|
||||
ChainGetBlock(context.Context, cid.Cid) (*types.BlockHeader, error)
|
||||
ChainGetBlockMessages(context.Context, cid.Cid) (*BlockMessages, error)
|
||||
ChainGetBlockReceipts(context.Context, cid.Cid) ([]*types.MessageReceipt, error)
|
||||
ChainGetActor(ctx context.Context, actor address.Address, ts *types.TipSet) (*types.Actor, error)
|
||||
ChainReadState(ctx context.Context, act *types.Actor, ts *types.TipSet) (*ActorState, error)
|
||||
|
||||
// if tipset is nil, we'll use heaviest
|
||||
ChainCall(context.Context, *types.Message, *types.TipSet) (*types.MessageReceipt, error)
|
||||
@ -136,6 +143,8 @@ type FullNode interface {
|
||||
type StorageMiner interface {
|
||||
Common
|
||||
|
||||
ActorAddresses(context.Context) ([]address.Address, error)
|
||||
|
||||
// Temp api for testing
|
||||
StoreGarbageData(context.Context) (uint64, error)
|
||||
|
||||
|
@ -48,6 +48,8 @@ type FullNodeStruct struct {
|
||||
ChainGetBlockMessages func(context.Context, cid.Cid) (*BlockMessages, error) `perm:"read"`
|
||||
ChainGetBlockReceipts func(context.Context, cid.Cid) ([]*types.MessageReceipt, error) `perm:"read"`
|
||||
ChainCall func(context.Context, *types.Message, *types.TipSet) (*types.MessageReceipt, error) `perm:"read"`
|
||||
ChainGetActor func(context.Context, address.Address, *types.TipSet) (*types.Actor, error) `perm:"read"`
|
||||
ChainReadState func(context.Context, *types.Actor, *types.TipSet) (*ActorState, error) `perm:"read"`
|
||||
|
||||
MpoolPending func(context.Context, *types.TipSet) ([]*types.SignedMessage, error) `perm:"read"`
|
||||
MpoolPush func(context.Context, *types.SignedMessage) error `perm:"write"`
|
||||
@ -77,6 +79,8 @@ type StorageMinerStruct struct {
|
||||
CommonStruct
|
||||
|
||||
Internal struct {
|
||||
ActorAddresses func(context.Context) ([]address.Address, error) `perm:"read"`
|
||||
|
||||
StoreGarbageData func(context.Context) (uint64, error) `perm:"write"`
|
||||
|
||||
SectorsStatus func(context.Context, uint64) (sectorbuilder.SectorSealingStatus, error) `perm:"read"`
|
||||
@ -171,6 +175,14 @@ func (c *FullNodeStruct) ChainCall(ctx context.Context, msg *types.Message, ts *
|
||||
return c.Internal.ChainCall(ctx, msg, ts)
|
||||
}
|
||||
|
||||
func (c *FullNodeStruct) ChainGetActor(ctx context.Context, actor address.Address, ts *types.TipSet) (*types.Actor, error) {
|
||||
return c.Internal.ChainGetActor(ctx, actor, ts)
|
||||
}
|
||||
|
||||
func (c *FullNodeStruct) ChainReadState(ctx context.Context, act *types.Actor, ts *types.TipSet) (*ActorState, error) {
|
||||
return c.Internal.ChainReadState(ctx, act, ts)
|
||||
}
|
||||
|
||||
func (c *FullNodeStruct) WalletNew(ctx context.Context, typ string) (address.Address, error) {
|
||||
return c.Internal.WalletNew(ctx, typ)
|
||||
}
|
||||
@ -227,6 +239,10 @@ func (c *FullNodeStruct) StateMinerProvingSet(ctx context.Context, addr address.
|
||||
return c.Internal.StateMinerProvingSet(ctx, addr)
|
||||
}
|
||||
|
||||
func (c *StorageMinerStruct) ActorAddresses(ctx context.Context) ([]address.Address, error) {
|
||||
return c.Internal.ActorAddresses(ctx)
|
||||
}
|
||||
|
||||
func (c *StorageMinerStruct) StoreGarbageData(ctx context.Context) (uint64, error) {
|
||||
return c.Internal.StoreGarbageData(ctx)
|
||||
}
|
||||
|
@ -4,8 +4,10 @@
|
||||
"private": true,
|
||||
"dependencies": {
|
||||
"borc": "^2.1.1",
|
||||
"cids": "^0.7.1",
|
||||
"ipld-dag-cbor": "^0.15.0",
|
||||
"jsonrpc-websocket-client": "^0.5.0",
|
||||
"multihashes": "^0.4.15",
|
||||
"react": "^16.8.6",
|
||||
"react-cristal": "^0.0.12",
|
||||
"react-dom": "^16.8.6",
|
||||
|
66
lotuspond/front/src/Address.js
Normal file
66
lotuspond/front/src/Address.js
Normal file
@ -0,0 +1,66 @@
|
||||
import React from 'react'
|
||||
import CID from 'cids'
|
||||
import * as multihash from "multihashes";
|
||||
import State from "./State";
|
||||
|
||||
function truncAddr(addr) {
|
||||
if (addr.length > 21) {
|
||||
return <abbr title={addr}>{addr.substr(0, 18) + '..'}</abbr>
|
||||
}
|
||||
return addr
|
||||
}
|
||||
|
||||
class Address extends React.Component {
|
||||
constructor(props) {
|
||||
super(props)
|
||||
|
||||
this.openState = this.openState.bind(this)
|
||||
|
||||
this.state = {balance: -2}
|
||||
this.refresh = this.refresh.bind(this)
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
this.refresh()
|
||||
if(!this.props.ts)
|
||||
setInterval(this.refresh, 2050)
|
||||
}
|
||||
|
||||
async refresh() {
|
||||
let balance = 0
|
||||
let actor = {}
|
||||
|
||||
try {
|
||||
balance = await this.props.client.call('Filecoin.WalletBalance', [this.props.addr])
|
||||
actor = await this.props.client.call('Filecoin.ChainGetActor', [this.props.addr, this.props.ts || null])
|
||||
} catch (err) {
|
||||
balance = -1
|
||||
}
|
||||
this.setState({balance, actor})
|
||||
}
|
||||
|
||||
openState() {
|
||||
this.props.mountWindow((onClose) => <State addr={this.props.addr} actor={this.state.actor} client={this.props.client} onClose={onClose}/>)
|
||||
}
|
||||
|
||||
render() {
|
||||
let add1k = <span/>
|
||||
if(this.props.add1k) {
|
||||
add1k = <a href="#" onClick={() => this.props.add1k(this.props.addr)}>[+1k]</a>
|
||||
}
|
||||
let addr = truncAddr(this.props.addr)
|
||||
|
||||
let actInfo = <span>(?)</span>
|
||||
if(this.state.balance >= 0) {
|
||||
const c = new CID(this.state.actor.Code['/'])
|
||||
const mh = multihash.decode(c.multihash) // TODO: check identity
|
||||
|
||||
actInfo = <span>({mh.digest.toString()})</span>
|
||||
addr = <a href="#" onClick={this.openState}>{addr}</a>
|
||||
}
|
||||
|
||||
return <span>{addr}: {this.state.balance} {actInfo} {add1k}</span>
|
||||
}
|
||||
}
|
||||
|
||||
export default Address
|
@ -1,6 +1,7 @@
|
||||
import React from 'react';
|
||||
import {Cristal} from "react-cristal";
|
||||
import {BlockLinks} from "./BlockLink";
|
||||
import Address from "./Address";
|
||||
|
||||
class Block extends React.Component {
|
||||
constructor(props) {
|
||||
@ -30,7 +31,9 @@ class Block extends React.Component {
|
||||
...(this.state.messages.SecpkMessages.map(m => ({...(m.Message), type: 'Secpk'})))
|
||||
].map(m => (
|
||||
<div>
|
||||
{m.From}<b> => </b>{m.To} {m.Value}FIL M{m.Method}
|
||||
<Address client={this.props.conn} addr={m.From} mountWindow={this.props.mountWindow}/><b>=> </b>
|
||||
<Address client={this.props.conn} addr={m.To} mountWindow={this.props.mountWindow}/>
|
||||
{m.Value}FIL M{m.Method}
|
||||
</div>
|
||||
))
|
||||
|
||||
@ -39,7 +42,7 @@ class Block extends React.Component {
|
||||
<div>Height: {head.Height}</div>
|
||||
<div>Parents: <BlockLinks cids={head.Parents} conn={this.props.conn} mountWindow={this.props.mountWindow}/></div>
|
||||
<div>Weight: {head.ParentWeight}</div>
|
||||
<div>Miner: {head.Miner}</div>
|
||||
<div>Miner: {<Address client={this.props.conn} addr={head.Miner} mountWindow={this.props.mountWindow}/>}</div>
|
||||
<div>Messages: {head.Messages['/']} {/*TODO: link to message explorer */}</div>
|
||||
<div>Receipts: {head.MessageReceipts['/']}</div>
|
||||
<div>State Root: {head.StateRoot['/']}</div>
|
||||
|
@ -3,18 +3,12 @@ import { Client } from 'rpc-websockets'
|
||||
import Cristal from 'react-cristal'
|
||||
import { BlockLinks } from "./BlockLink";
|
||||
import StorageNodeInit from "./StorageNodeInit";
|
||||
import Address from "./Address";
|
||||
|
||||
async function awaitListReducer(prev, c) {
|
||||
return [...await prev, await c]
|
||||
}
|
||||
|
||||
function truncAddr(addr) {
|
||||
if (addr.length > 41) {
|
||||
return <abbr title={addr}>{addr.substr(0, 38) + '...'}</abbr>
|
||||
}
|
||||
return addr
|
||||
}
|
||||
|
||||
class FullNode extends React.Component {
|
||||
constructor(props) {
|
||||
super(props)
|
||||
@ -42,13 +36,13 @@ class FullNode extends React.Component {
|
||||
|
||||
const tipset = await this.props.client.call("Filecoin.ChainHead", [])
|
||||
|
||||
const addrss = await this.props.client.call('Filecoin.WalletList', [])
|
||||
const addrs = await this.props.client.call('Filecoin.WalletList', [])
|
||||
let defaultAddr = ""
|
||||
if (addrss.length > 0) {
|
||||
if (addrs.length > 0) {
|
||||
defaultAddr = await this.props.client.call('Filecoin.WalletDefaultAddress', [])
|
||||
}
|
||||
|
||||
const balances = await addrss.map(async addr => {
|
||||
/* const balances = await addrss.map(async addr => {
|
||||
let balance = 0
|
||||
try {
|
||||
balance = await this.props.client.call('Filecoin.WalletBalance', [addr])
|
||||
@ -56,7 +50,7 @@ class FullNode extends React.Component {
|
||||
balance = -1
|
||||
}
|
||||
return [addr, balance]
|
||||
}).reduce(awaitListReducer, Promise.resolve([]))
|
||||
}).reduce(awaitListReducer, Promise.resolve([]))*/
|
||||
|
||||
this.setState(() => ({
|
||||
id: id,
|
||||
@ -64,7 +58,7 @@ class FullNode extends React.Component {
|
||||
peers: peers.length,
|
||||
tipset: tipset,
|
||||
|
||||
balances: balances,
|
||||
addrs: addrs,
|
||||
defaultAddr: defaultAddr}))
|
||||
}
|
||||
|
||||
@ -117,10 +111,8 @@ class FullNode extends React.Component {
|
||||
|
||||
let storageMine = <a href="#" onClick={this.startStorageMiner}>[Spawn Storage Miner]</a>
|
||||
|
||||
let balances = this.state.balances.map(([addr, balance]) => {
|
||||
let add1k = <a href="#" onClick={() => this.add1k(addr)}>[+1k]</a>
|
||||
|
||||
let line = <span>{truncAddr(addr)}: {balance} (ActTyp) {add1k}</span>
|
||||
let addresses = this.state.addrs.map((addr) => {
|
||||
let line = <Address client={this.props.client} add1k={this.add1k} addr={addr} mountWindow={this.props.mountWindow}/>
|
||||
if (this.state.defaultAddr === addr) {
|
||||
line = <b>{line}</b>
|
||||
}
|
||||
@ -137,7 +129,7 @@ class FullNode extends React.Component {
|
||||
</div>
|
||||
<div>
|
||||
<div>Balances: [New <a href="#" onClick={this.newScepAddr}>[Secp256k1]</a>]</div>
|
||||
<div>{balances}</div>
|
||||
<div>{addresses}</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
30
lotuspond/front/src/State.js
Normal file
30
lotuspond/front/src/State.js
Normal file
@ -0,0 +1,30 @@
|
||||
import React from 'react'
|
||||
import {Cristal} from "react-cristal";
|
||||
|
||||
class State extends React.Component {
|
||||
constructor(props) {
|
||||
super(props)
|
||||
|
||||
this.state = {Balance: -2, State: {}}
|
||||
}
|
||||
|
||||
async componentDidMount() {
|
||||
const tipset = await this.props.client.call("Filecoin.ChainHead", []) // TODO: from props
|
||||
const actstate = await this.props.client.call('Filecoin.ChainReadState', [this.props.actor, tipset])
|
||||
this.setState(actstate)
|
||||
}
|
||||
|
||||
render() {
|
||||
const content = <div>
|
||||
<div>Balance: {this.state.Balance}</div>
|
||||
<div>---</div>
|
||||
<div>{Object.keys(this.state.State).map(k => <div key={k}>{k}: <span>{JSON.stringify(this.state.State[k])}</span></div>)}</div>
|
||||
</div>
|
||||
|
||||
return <Cristal onClose={this.props.onClose} title={`Actor ${this.props.addr} @{this.props.ts.Height}`}>
|
||||
{content}
|
||||
</Cristal>
|
||||
}
|
||||
}
|
||||
|
||||
export default State
|
@ -1,6 +1,7 @@
|
||||
import React from 'react';
|
||||
import {Cristal} from "react-cristal";
|
||||
import { Client } from 'rpc-websockets'
|
||||
import Address from "./Address";
|
||||
|
||||
const stateConnected = 'connected'
|
||||
const stateConnecting = 'connecting'
|
||||
@ -66,20 +67,10 @@ class StorageNode extends React.Component {
|
||||
|
||||
async loadInfo() {
|
||||
const version = await this.state.client.call("Filecoin.Version", [])
|
||||
this.setState(() => ({version: version}))
|
||||
|
||||
const peers = await this.state.client.call("Filecoin.NetPeers", [])
|
||||
this.setState(() => ({peers: peers.length}))
|
||||
|
||||
/*const addrss = await this.state.client.call('Filecoin.WalletList', [])
|
||||
let defaultAddr = ""
|
||||
if (addrss.length > 0) {
|
||||
defaultAddr = await this.state.client.call('Filecoin.WalletDefaultAddress', [])
|
||||
}
|
||||
|
||||
this.setState(() => ({defaultAddr: defaultAddr}))
|
||||
*/
|
||||
const [actor] = await this.state.client.call("Filecoin.ActorAddresses", [])
|
||||
|
||||
this.setState({version: version, peers: peers.length, actor: actor})
|
||||
await this.stagedList()
|
||||
}
|
||||
|
||||
@ -100,7 +91,7 @@ class StorageNode extends React.Component {
|
||||
|
||||
render() {
|
||||
let runtime = <div></div>
|
||||
if (this.state.state === stateConnected) {
|
||||
if (this.state.actor) {
|
||||
const sealGarbage = <a href="#" onClick={this.sealGarbage}>[Seal Garbage]</a>
|
||||
|
||||
runtime = (
|
||||
@ -110,6 +101,9 @@ class StorageNode extends React.Component {
|
||||
<div>
|
||||
{sealGarbage}
|
||||
</div>
|
||||
<div>
|
||||
<Address client={this.props.fullConn} addr={this.state.actor} mountWindow={this.props.mountWindow}/>
|
||||
</div>
|
||||
<div>{this.state.statusCounts.map((c, i) => <span>{sealCodes[i]}: {c} | </span>)}</div>
|
||||
<div>
|
||||
{this.state.staged ? this.state.staged.map(s => (
|
||||
|
@ -3,6 +3,7 @@ package impl
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"github.com/filecoin-project/go-lotus/lib/bufbstore"
|
||||
"strconv"
|
||||
|
||||
"github.com/filecoin-project/go-lotus/api"
|
||||
@ -20,7 +21,7 @@ import (
|
||||
"github.com/filecoin-project/go-lotus/node/client"
|
||||
|
||||
"github.com/ipfs/go-cid"
|
||||
hamt "github.com/ipfs/go-hamt-ipld"
|
||||
"github.com/ipfs/go-hamt-ipld"
|
||||
cbor "github.com/ipfs/go-ipld-cbor"
|
||||
logging "github.com/ipfs/go-log"
|
||||
"github.com/libp2p/go-libp2p-core/peer"
|
||||
@ -191,6 +192,47 @@ func (a *FullNodeAPI) ChainCall(ctx context.Context, msg *types.Message, ts *typ
|
||||
return &ret.MessageReceipt, err
|
||||
}
|
||||
|
||||
func (a *FullNodeAPI) stateForTs(ts *types.TipSet) (*state.StateTree, error) {
|
||||
if ts == nil {
|
||||
ts = a.Chain.GetHeaviestTipSet()
|
||||
}
|
||||
|
||||
st, err := a.Chain.TipSetState(ts.Cids())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
buf := bufbstore.NewBufferedBstore(a.Chain.Blockstore())
|
||||
cst := hamt.CSTFromBstore(buf)
|
||||
return state.LoadStateTree(cst, st)
|
||||
}
|
||||
|
||||
func (a *FullNodeAPI) ChainGetActor(ctx context.Context, actor address.Address, ts *types.TipSet) (*types.Actor, error) {
|
||||
state, err := a.stateForTs(ts)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return state.GetActor(actor)
|
||||
}
|
||||
|
||||
func (a *FullNodeAPI) ChainReadState(ctx context.Context, act *types.Actor, ts *types.TipSet) (*api.ActorState, error) {
|
||||
state, err := a.stateForTs(ts)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var oif interface{}
|
||||
if err := state.Store.Get(context.TODO(), act.Head, &oif); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &api.ActorState{
|
||||
Balance: act.Balance,
|
||||
State: oif,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (a *FullNodeAPI) MpoolPending(ctx context.Context, ts *types.TipSet) ([]*types.SignedMessage, error) {
|
||||
// TODO: need to make sure we don't return messages that were already included in the referenced chain
|
||||
// also need to accept ts == nil just fine, assume nil == chain.Head()
|
||||
|
@ -3,6 +3,7 @@ package impl
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"github.com/filecoin-project/go-lotus/chain/address"
|
||||
"io/ioutil"
|
||||
"math/rand"
|
||||
|
||||
@ -14,11 +15,16 @@ import (
|
||||
type StorageMinerAPI struct {
|
||||
CommonAPI
|
||||
|
||||
SectorBuilder *sectorbuilder.SectorBuilder
|
||||
SectorBuilderConfig *sectorbuilder.SectorBuilderConfig
|
||||
SectorBuilder *sectorbuilder.SectorBuilder
|
||||
|
||||
Miner *storage.Miner
|
||||
}
|
||||
|
||||
func (sm *StorageMinerAPI) ActorAddresses(context.Context) ([]address.Address, error) {
|
||||
return []address.Address{sm.SectorBuilderConfig.Miner}, nil
|
||||
}
|
||||
|
||||
func (sm *StorageMinerAPI) StoreGarbageData(ctx context.Context) (uint64, error) {
|
||||
maxSize := uint64(1016) // this is the most data we can fit in a 1024 byte sector
|
||||
data := make([]byte, maxSize)
|
||||
|
Loading…
Reference in New Issue
Block a user