Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: 扩展更多的 State*** 接口 / expand state apis #5214

Merged
merged 2 commits into from
Aug 25, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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