Skip to content

Commit

Permalink
Merge pull request #5214 from filecoin-project/feat/lt/expand_chain_s…
Browse files Browse the repository at this point in the history
…tate_api

feat: 扩展更多的 `State***` 接口 / expand state apis
  • Loading branch information
hunjixin authored Aug 25, 2022
2 parents 9511b7c + 3b7713b commit 4645125
Show file tree
Hide file tree
Showing 11 changed files with 543 additions and 10 deletions.
182 changes: 180 additions & 2 deletions app/submodule/chain/miner_api.go
Original file line number Diff line number Diff line change
@@ -1,20 +1,27 @@
package chain

import (
"bytes"
"context"
"encoding/json"
"errors"
"fmt"
"reflect"

"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"
"github.com/filecoin-project/go-state-types/cbor"
"github.com/filecoin-project/go-state-types/dline"
cbor "github.com/ipfs/go-ipld-cbor"
"github.com/ipfs/go-cid"
cbornode "github.com/ipfs/go-ipld-cbor"
"github.com/libp2p/go-libp2p-core/peer"
cbg "github.com/whyrusleeping/cbor-gen"

"github.com/filecoin-project/go-state-types/builtin/v8/miner"
"github.com/filecoin-project/venus/pkg/state/tree"
"github.com/filecoin-project/venus/pkg/vm/register"
"github.com/filecoin-project/venus/venus-shared/actors/adt"
"github.com/filecoin-project/venus/venus-shared/actors/builtin"
_init "github.com/filecoin-project/venus/venus-shared/actors/builtin/init"
Expand All @@ -25,6 +32,7 @@ import (
"github.com/filecoin-project/venus/venus-shared/actors/policy"
v1api "github.com/filecoin-project/venus/venus-shared/api/chain/v1"
"github.com/filecoin-project/venus/venus-shared/types"
"github.com/filecoin-project/venus/venus-shared/utils"
)

var _ v1api.IMinerState = &minerStateAPI{}
Expand Down Expand Up @@ -179,6 +187,10 @@ func (msa *minerStateAPI) StateMinerFaults(ctx context.Context, maddr address.Ad
return lminer.AllPartSectors(mas, lminer.Partition.FaultySectors)
}

func (msa *minerStateAPI) StateAllMinerFaults(ctx context.Context, lookback abi.ChainEpoch, endTsk types.TipSetKey) ([]*types.Fault, error) {
return nil, fmt.Errorf("fixme")
}

// StateMinerProvingDeadline calculates the deadline at some epoch for a proving period
// and returns the deadline-related calculations.
func (msa *minerStateAPI) StateMinerProvingDeadline(ctx context.Context, maddr address.Address, tsk types.TipSetKey) (*dline.Info, error) {
Expand Down Expand Up @@ -564,7 +576,7 @@ func (msa *minerStateAPI) StateLookupRobustAddress(ctx context.Context, idAddr a
return address.Undef, fmt.Errorf("failed to decode provided address as id addr: %w", err)
}

cst := cbor.NewCborStore(msa.ChainReader.Blockstore())
cst := cbornode.NewCborStore(msa.ChainReader.Blockstore())
wrapStore := adt.WrapStore(ctx, cst)

_, state, err := msa.Stmgr.ParentStateTsk(ctx, tsk)
Expand Down Expand Up @@ -840,3 +852,169 @@ func (msa *minerStateAPI) StateVerifiedClientStatus(ctx context.Context, addr ad

return &dcap, nil
}

func (msa *minerStateAPI) StateChangedActors(ctx context.Context, old cid.Cid, new cid.Cid) (map[string]types.Actor, error) {
store := msa.ChainReader.Store(ctx)

oldTree, err := tree.LoadState(ctx, store, old)
if err != nil {
return nil, fmt.Errorf("failed to load old state tree: %w", err)
}

newTree, err := tree.LoadState(ctx, store, new)
if err != nil {
return nil, fmt.Errorf("failed to load new state tree: %w", err)
}

return tree.Diff(oldTree, newTree)
}

func (msa *minerStateAPI) StateReadState(ctx context.Context, actor address.Address, tsk types.TipSetKey) (*types.ActorState, error) {
_, view, err := msa.Stmgr.ParentStateViewTsk(ctx, tsk)
if err != nil {
return nil, fmt.Errorf("loading tipset:%s parent state view: %v", tsk, err)
}

act, err := view.LoadActor(ctx, actor)
if err != nil {
return nil, err
}

blk, err := msa.ChainReader.Blockstore().Get(ctx, act.Head)
if err != nil {
return nil, fmt.Errorf("getting actor head: %w", err)
}

oif, err := register.DumpActorState(register.GetDefaultActros(), act, blk.RawData())
if err != nil {
return nil, fmt.Errorf("dumping actor state (a:%s): %w", actor, err)
}

return &types.ActorState{
Balance: act.Balance,
Code: act.Code,
State: oif,
}, nil
}

func (msa *minerStateAPI) StateDecodeParams(ctx context.Context, toAddr address.Address, method abi.MethodNum, params []byte, tsk types.TipSetKey) (interface{}, error) {
_, view, err := msa.Stmgr.ParentStateViewTsk(ctx, tsk)
if err != nil {
return nil, fmt.Errorf("loading tipset:%s parent state view: %v", tsk, err)
}

act, err := view.LoadActor(ctx, toAddr)
if err != nil {
return nil, err
}

methodMeta, found := utils.MethodsMap[act.Code][method]
if !found {
return nil, fmt.Errorf("method %d not found on actor %s", method, act.Code)
}

paramType := reflect.New(methodMeta.Params.Elem()).Interface().(cbg.CBORUnmarshaler)

if err = paramType.UnmarshalCBOR(bytes.NewReader(params)); err != nil {
return nil, err
}

return paramType, nil
}

func (msa *minerStateAPI) StateEncodeParams(ctx context.Context, toActCode cid.Cid, method abi.MethodNum, params json.RawMessage) ([]byte, error) {
methodMeta, found := utils.MethodsMap[toActCode][method]
if !found {
return nil, fmt.Errorf("method %d not found on actor %s", method, toActCode)
}

paramType := reflect.New(methodMeta.Params.Elem()).Interface().(cbg.CBORUnmarshaler)

if err := json.Unmarshal(params, &paramType); err != nil {
return nil, fmt.Errorf("json unmarshal: %w", err)
}

var cbb bytes.Buffer
if err := paramType.(cbor.Marshaler).MarshalCBOR(&cbb); err != nil {
return nil, fmt.Errorf("cbor marshal: %w", err)
}

return cbb.Bytes(), nil
}

func (msa *minerStateAPI) StateListMessages(ctx context.Context, match *types.MessageMatch, tsk types.TipSetKey, toheight abi.ChainEpoch) ([]cid.Cid, error) {
ts, err := msa.ChainReader.GetTipSet(ctx, tsk)
if err != nil {
return nil, fmt.Errorf("loading tipset %s: %w", tsk, err)
}

if ts == nil {
ts = msa.ChainReader.GetHead()
}

if match.To == address.Undef && match.From == address.Undef {
return nil, fmt.Errorf("must specify at least To or From in message filter")
} else if match.To != address.Undef {
_, err := msa.StateLookupID(ctx, match.To, tsk)

// if the recipient doesn't exist at the start point, we're not gonna find any matches
if errors.Is(err, types.ErrActorNotFound) {
return nil, nil
}

if err != nil {
return nil, fmt.Errorf("looking up match.To: %w", err)
}
} else if match.From != address.Undef {
_, err := msa.StateLookupID(ctx, match.From, tsk)

// if the sender doesn't exist at the start point, we're not gonna find any matches
if errors.Is(err, types.ErrActorNotFound) {
return nil, nil
}

if err != nil {
return nil, fmt.Errorf("looking up match.From: %w", err)
}
}

// TODO: This should probably match on both ID and robust address, no?
matchFunc := func(msg *types.Message) bool {
if match.From != address.Undef && match.From != msg.From {
return false
}

if match.To != address.Undef && match.To != msg.To {
return false
}

return true
}

var out []cid.Cid
for ts.Height() >= toheight {
msgs, err := msa.MessageStore.MessagesForTipset(ts)
if err != nil {
return nil, fmt.Errorf("failed to get messages for tipset (%s): %w", ts.Key(), err)
}

for _, msg := range msgs {
if matchFunc(msg.VMMessage()) {
out = append(out, msg.Cid())
}
}

if ts.Height() == 0 {
break
}

next, err := msa.ChainReader.GetTipSet(ctx, ts.Parents())
if err != nil {
return nil, fmt.Errorf("loading next tipset: %w", err)
}

ts = next
}

return out, nil
}
12 changes: 11 additions & 1 deletion pkg/vm/dispatch/loader.go
Original file line number Diff line number Diff line change
Expand Up @@ -44,11 +44,21 @@ func (cl CodeLoader) GetUnsafeActorImpl(code cid.Cid) (Dispatcher, error) {
//todo version check
actor, ok := cl.actors[code]
if !ok {
return nil, fmt.Errorf("unable to get actorv for code %s", code)
return nil, fmt.Errorf("unable to get actor for code %s", code)
}
return &actorDispatcher{code: code, actor: actor.vmActor}, nil
}

func (cl CodeLoader) GetVMActor(code cid.Cid) (rtt.VMActor, error) {
//todo version check
actor, ok := cl.actors[code]
if !ok {
return nil, fmt.Errorf("unable to get actor for code %s", code)
}

return actor.vmActor, nil
}

// CodeLoaderBuilder helps you build a CodeLoader.
type CodeLoaderBuilder struct {
actors map[cid.Cid]ActorInfo
Expand Down
22 changes: 22 additions & 0 deletions pkg/vm/register/default.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
package register

import (
"bytes"
"fmt"
"sync"

/* inline-gen template
Expand All @@ -21,6 +23,8 @@ import (

"github.com/filecoin-project/venus/pkg/vm/dispatch"
"github.com/filecoin-project/venus/venus-shared/actors"
"github.com/filecoin-project/venus/venus-shared/actors/builtin"
"github.com/filecoin-project/venus/venus-shared/types"
)

// defaultActors is list of all actors that ship with Filecoin.
Expand Down Expand Up @@ -52,3 +56,21 @@ func GetDefaultActros() *dispatch.CodeLoader {

return &defaultActors
}

func DumpActorState(codeLoader *dispatch.CodeLoader, act *types.Actor, b []byte) (interface{}, error) {
if builtin.IsAccountActor(act.Code) { // Account code special case
return nil, nil
}

vmActor, err := codeLoader.GetVMActor(act.Code)
if err != nil {
return nil, fmt.Errorf("state type for actor %s not found", act.Code)
}

um := vmActor.State()
if err := um.UnmarshalCBOR(bytes.NewReader(b)); err != nil {
return nil, fmt.Errorf("unmarshaling actor state: %w", err)
}

return um, nil
}
5 changes: 5 additions & 0 deletions venus-devtool/api-gen/example.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package main

import (
"encoding/json"
"fmt"
"go/token"
"os"
Expand Down Expand Up @@ -141,6 +142,10 @@ func init() {
Msg: ExampleValue("init", reflect.TypeOf(&types.Message{}), nil).(*types.Message),
MsgRct: ExampleValue("init", reflect.TypeOf(&types.MessageReceipt{}), nil).(*types.MessageReceipt),
})
addExample(map[string]types.Actor{
"t01236": ExampleValue("init", reflect.TypeOf(types.Actor{}), nil).(types.Actor),
})
addExample(json.RawMessage(`"json raw message"`))
addExample(map[address.Address]*types.Actor{
addr: {
Code: c,
Expand Down
4 changes: 4 additions & 0 deletions venus-devtool/api-gen/proxy.go
Original file line number Diff line number Diff line change
Expand Up @@ -251,6 +251,10 @@ func resolveDep(typ ast.Expr, ifaceMeta *util.InterfaceMeta, deps map[string]uti

return nil

case *ast.InterfaceType:

return nil

default:
return fmt.Errorf("found unexpected type: %T", typ)
}
Expand Down
9 changes: 8 additions & 1 deletion venus-shared/api/chain/v1/chain.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package v1

import (
"context"
"encoding/json"
"time"

"github.com/filecoin-project/go-address"
Expand Down Expand Up @@ -113,15 +114,20 @@ type IChainInfo interface {
}

type IMinerState interface {
StateReadState(ctx context.Context, actor address.Address, tsk types.TipSetKey) (*types.ActorState, error) //perm:read
StateListMessages(ctx context.Context, match *types.MessageMatch, tsk types.TipSetKey, toht abi.ChainEpoch) ([]cid.Cid, error) //perm:read
StateDecodeParams(ctx context.Context, toAddr address.Address, method abi.MethodNum, params []byte, tsk types.TipSetKey) (interface{}, error) //perm:read
StateEncodeParams(ctx context.Context, toActCode cid.Cid, method abi.MethodNum, params json.RawMessage) ([]byte, error) //perm:read
StateMinerSectorAllocated(ctx context.Context, maddr address.Address, s abi.SectorNumber, tsk types.TipSetKey) (bool, error) //perm:read
StateSectorPreCommitInfo(ctx context.Context, maddr address.Address, n abi.SectorNumber, tsk types.TipSetKey) (miner.SectorPreCommitOnChainInfo, error) //perm:read
StateSectorGetInfo(ctx context.Context, maddr address.Address, n abi.SectorNumber, tsk types.TipSetKey) (*miner.SectorOnChainInfo, error) //perm:read
StateSectorPartition(ctx context.Context, maddr address.Address, sectorNumber abi.SectorNumber, tsk types.TipSetKey) (*lminer.SectorLocation, error) //perm:read
StateMinerSectorSize(ctx context.Context, maddr address.Address, tsk types.TipSetKey) (abi.SectorSize, error) //perm:read
StateMinerInfo(ctx context.Context, maddr address.Address, tsk types.TipSetKey) (types.MinerInfo, error) //perm:read
StateMinerWorkerAddress(ctx context.Context, maddr address.Address, tsk types.TipSetKey) (address.Address, error) //perm:read
StateMinerRecoveries(ctx context.Context, maddr address.Address, tsk types.TipSetKey) (bitfield.BitField, error) //perm:read
StateMinerFaults(ctx context.Context, maddr address.Address, tsk types.TipSetKey) (bitfield.BitField, error) //perm:read
StateAllMinerFaults(ctx context.Context, lookback abi.ChainEpoch, ts types.TipSetKey) ([]*types.Fault, error) //perm:read
StateMinerRecoveries(ctx context.Context, maddr address.Address, tsk types.TipSetKey) (bitfield.BitField, error) //perm:read
StateMinerProvingDeadline(ctx context.Context, maddr address.Address, tsk types.TipSetKey) (*dline.Info, error) //perm:read
StateMinerPartitions(ctx context.Context, maddr address.Address, dlIdx uint64, tsk types.TipSetKey) ([]types.Partition, error) //perm:read
StateMinerDeadlines(ctx context.Context, maddr address.Address, tsk types.TipSetKey) ([]types.Deadline, error) //perm:read
Expand All @@ -141,6 +147,7 @@ type IMinerState interface {
StateMinerPower(ctx context.Context, addr address.Address, tsk types.TipSetKey) (*types.MinerPower, error) //perm:read
StateMinerAvailableBalance(ctx context.Context, maddr address.Address, tsk types.TipSetKey) (big.Int, error) //perm:read
StateSectorExpiration(ctx context.Context, maddr address.Address, sectorNumber abi.SectorNumber, tsk types.TipSetKey) (*lminer.SectorExpiration, error) //perm:read
StateChangedActors(context.Context, cid.Cid, cid.Cid) (map[string]types.Actor, error) //perm:read
StateMinerSectorCount(ctx context.Context, addr address.Address, tsk types.TipSetKey) (types.MinerSectors, error) //perm:read
StateMarketBalance(ctx context.Context, addr address.Address, tsk types.TipSetKey) (types.MarketBalance, error) //perm:read
StateDealProviderCollateralBounds(ctx context.Context, size abi.PaddedPieceSize, verified bool, tsk types.TipSetKey) (types.DealCollateralBounds, error) //perm:read
Expand Down
Loading

0 comments on commit 4645125

Please sign in to comment.