feat: lotus-lite - replace wallet StateManager with thin client to gateway

This commit is contained in:
Dirk McCormick 2020-09-29 17:25:45 +02:00
parent bacac245c7
commit e19cd9ed01
10 changed files with 163 additions and 15 deletions

17
api/api_gateway.go Normal file
View File

@ -0,0 +1,17 @@
package api
import (
"context"
"github.com/filecoin-project/go-address"
"github.com/filecoin-project/lotus/chain/types"
"github.com/ipfs/go-cid"
)
type GatewayAPI interface {
StateGetActor(ctx context.Context, actor address.Address, ts types.TipSetKey) (*types.Actor, error)
ChainHead(ctx context.Context) (*types.TipSet, error)
ChainGetTipSet(ctx context.Context, tsk types.TipSetKey) (*types.TipSet, error)
MpoolPush(ctx context.Context, sm *types.SignedMessage) (cid.Cid, error)
StateAccountKey(ctx context.Context, addr address.Address, tsk types.TipSetKey) (address.Address, error)
}

View File

@ -361,6 +361,17 @@ type WorkerStruct struct {
}
}
type GatewayStruct struct {
Internal struct {
// TODO: does the gateway need perms?
StateGetActor func(ctx context.Context, actor address.Address, ts types.TipSetKey) (*types.Actor, error)
ChainHead func(ctx context.Context) (*types.TipSet, error)
ChainGetTipSet func(ctx context.Context, tsk types.TipSetKey) (*types.TipSet, error)
MpoolPush func(ctx context.Context, sm *types.SignedMessage) (cid.Cid, error)
StateAccountKey func(ctx context.Context, addr address.Address, tsk types.TipSetKey) (address.Address, error)
}
}
// CommonStruct
func (c *CommonStruct) AuthVerify(ctx context.Context, token string) ([]auth.Permission, error) {
@ -1372,7 +1383,28 @@ func (w *WorkerStruct) Closing(ctx context.Context) (<-chan struct{}, error) {
return w.Internal.Closing(ctx)
}
func (g GatewayStruct) StateGetActor(ctx context.Context, actor address.Address, ts types.TipSetKey) (*types.Actor, error) {
return g.Internal.StateGetActor(ctx, actor, ts)
}
func (g GatewayStruct) ChainHead(ctx context.Context) (*types.TipSet, error) {
return g.Internal.ChainHead(ctx)
}
func (g GatewayStruct) ChainGetTipSet(ctx context.Context, tsk types.TipSetKey) (*types.TipSet, error) {
return g.Internal.ChainGetTipSet(ctx, tsk)
}
func (g GatewayStruct) MpoolPush(ctx context.Context, sm *types.SignedMessage) (cid.Cid, error) {
return g.Internal.MpoolPush(ctx, sm)
}
func (g GatewayStruct) StateAccountKey(ctx context.Context, addr address.Address, tsk types.TipSetKey) (address.Address, error) {
return g.Internal.StateAccountKey(ctx, addr, tsk)
}
var _ api.Common = &CommonStruct{}
var _ api.FullNode = &FullNodeStruct{}
var _ api.StorageMiner = &StorageMinerStruct{}
var _ api.WorkerAPI = &WorkerStruct{}
var _ api.GatewayAPI = &GatewayStruct{}

View File

@ -82,3 +82,17 @@ func NewWorkerRPC(ctx context.Context, addr string, requestHeader http.Header) (
return &res, closer, err
}
// NewGatewayRPC creates a new http jsonrpc client for a gateway node.
func NewGatewayRPC(ctx context.Context, addr string, requestHeader http.Header, opts ...jsonrpc.Option) (api.GatewayAPI, jsonrpc.ClientCloser, error) {
var res apistruct.GatewayStruct
closer, err := jsonrpc.NewMergeClient(ctx, addr, "Filecoin",
[]interface{}{
&res.Internal,
},
requestHeader,
opts...,
)
return &res, closer, err
}

View File

@ -40,6 +40,11 @@ import (
var log = logging.Logger("statemgr")
type StateManagerAPI interface {
LoadActorTsk(ctx context.Context, addr address.Address, tsk types.TipSetKey) (*types.Actor, error)
ResolveToKeyAddress(ctx context.Context, addr address.Address, ts *types.TipSet) (address.Address, error)
}
type versionSpec struct {
networkVersion network.Version
atOrBelow abi.ChainEpoch
@ -1393,3 +1398,5 @@ func (sm *StateManager) GetMarketState(ctx context.Context, ts *types.TipSet) (m
}
return actState, nil
}
var _ StateManagerAPI = (*StateManager)(nil)

View File

@ -289,6 +289,15 @@ func GetWorkerAPI(ctx *cli.Context) (api.WorkerAPI, jsonrpc.ClientCloser, error)
return client.NewWorkerRPC(ctx.Context, addr, headers)
}
func GetGatewayAPI(ctx *cli.Context) (api.GatewayAPI, jsonrpc.ClientCloser, error) {
addr, headers, err := GetRawAPI(ctx, repo.FullNode)
if err != nil {
return nil, nil, err
}
return client.NewGatewayRPC(ctx.Context, addr, headers)
}
func DaemonContext(cctx *cli.Context) context.Context {
if mtCtx, ok := cctx.App.Metadata[metadataTraceContext]; ok {
return mtCtx.(context.Context)

View File

@ -49,17 +49,6 @@ func (a *GatewayAPI) checkTipset(ctx context.Context, ts types.TipSetKey) error
return nil
}
func (a *GatewayAPI) StateGetActor(ctx context.Context, actor address.Address, ts types.TipSetKey) (*types.Actor, error) {
ctx, span := trace.StartSpan(ctx, "StateGetActor")
defer span.End()
if err := a.checkTipset(ctx, ts); err != nil {
return nil, fmt.Errorf("bad tipset: %w", err)
}
return a.api.StateGetActor(ctx, actor, ts)
}
func (a *GatewayAPI) ChainHead(ctx context.Context) (*types.TipSet, error) {
ctx, span := trace.StartSpan(ctx, "ChainHead")
defer span.End()
@ -88,3 +77,25 @@ func (a *GatewayAPI) MpoolPush(ctx context.Context, sm *types.SignedMessage) (ci
return a.api.MpoolPushUntrusted(ctx, sm)
}
func (a *GatewayAPI) StateGetActor(ctx context.Context, actor address.Address, ts types.TipSetKey) (*types.Actor, error) {
ctx, span := trace.StartSpan(ctx, "StateGetActor")
defer span.End()
if err := a.checkTipset(ctx, ts); err != nil {
return nil, fmt.Errorf("bad tipset: %w", err)
}
return a.api.StateGetActor(ctx, actor, ts)
}
func (a *GatewayAPI) StateAccountKey(ctx context.Context, addr address.Address, tsk types.TipSetKey) (address.Address, error) {
ctx, span := trace.StartSpan(ctx, "StateAccountKey")
defer span.End()
if err := a.checkTipset(ctx, tsk); err != nil {
return address.Undef, fmt.Errorf("bad tipset: %w", err)
}
return a.api.StateAccountKey(ctx, addr, tsk)
}

View File

@ -15,6 +15,8 @@ import (
"runtime/pprof"
"strings"
"go.uber.org/fx"
"github.com/filecoin-project/lotus/chain/types"
paramfetch "github.com/filecoin-project/go-paramfetch"
@ -114,6 +116,10 @@ var DaemonCmd = &cli.Command{
Name: "halt-after-import",
Usage: "halt the process after importing chain from file",
},
&cli.BoolFlag{
Name: "lite",
Usage: "start lotus in lite mode",
},
&cli.StringFlag{
Name: "pprof",
Usage: "specify name of file for writing cpu profile to",
@ -240,6 +246,27 @@ var DaemonCmd = &cli.Command{
shutdownChan := make(chan struct{})
// If the daemon is started in "lite mode", replace the StateManager
// with a thin client to a gateway server
liteMode := node.Options()
if cctx.Bool("lite") {
gapi, closer, err := lcli.GetGatewayAPI(cctx)
if err != nil {
return err
}
createRPCStateMgr := func(lc fx.Lifecycle) *modules.RPCStateManager {
lc.Append(fx.Hook{
OnStop: func(ctx context.Context) error {
closer()
return nil
},
})
return modules.NewRPCStateManager(gapi)
}
liteMode = node.Override(new(stmgr.StateManagerAPI), createRPCStateMgr)
}
var api api.FullNode
stop, err := node.New(ctx,
@ -251,6 +278,7 @@ var DaemonCmd = &cli.Command{
node.Repo(r),
genesis,
liteMode,
node.ApplyIf(func(s *node.Settings) bool { return cctx.IsSet("api") },
node.Override(node.SetApiEndpointKey, func(lr repo.LockedRepo) error {

View File

@ -261,6 +261,7 @@ func Online() Option {
Override(new(*store.ChainStore), modules.ChainStore),
Override(new(stmgr.UpgradeSchedule), stmgr.DefaultUpgradeSchedule()),
Override(new(*stmgr.StateManager), stmgr.NewStateManagerWithUpgradeSchedule),
Override(new(stmgr.StateManagerAPI), From(new(*stmgr.StateManager))),
Override(new(*wallet.Wallet), wallet.NewWallet),
Override(new(*messagesigner.MessageSigner), messagesigner.NewMessageSigner),

View File

@ -19,8 +19,8 @@ import (
type WalletAPI struct {
fx.In
StateManager *stmgr.StateManager
Wallet *wallet.Wallet
stmgr.StateManagerAPI
Wallet *wallet.Wallet
}
func (a *WalletAPI) WalletNew(ctx context.Context, typ crypto.SigType) (address.Address, error) {
@ -36,7 +36,7 @@ func (a *WalletAPI) WalletList(ctx context.Context) ([]address.Address, error) {
}
func (a *WalletAPI) WalletBalance(ctx context.Context, addr address.Address) (types.BigInt, error) {
act, err := a.StateManager.LoadActorTsk(ctx, addr, types.EmptyTSK)
act, err := a.StateManagerAPI.LoadActorTsk(ctx, addr, types.EmptyTSK)
if xerrors.Is(err, types.ErrActorNotFound) {
return big.Zero(), nil
} else if err != nil {
@ -46,7 +46,7 @@ func (a *WalletAPI) WalletBalance(ctx context.Context, addr address.Address) (ty
}
func (a *WalletAPI) WalletSign(ctx context.Context, k address.Address, msg []byte) (*crypto.Signature, error) {
keyAddr, err := a.StateManager.ResolveToKeyAddress(ctx, k, nil)
keyAddr, err := a.StateManagerAPI.ResolveToKeyAddress(ctx, k, nil)
if err != nil {
return nil, xerrors.Errorf("failed to resolve ID address: %w", keyAddr)
}

View File

@ -0,0 +1,29 @@
package modules
import (
"context"
"github.com/filecoin-project/lotus/api"
"github.com/filecoin-project/go-address"
"github.com/filecoin-project/lotus/chain/stmgr"
"github.com/filecoin-project/lotus/chain/types"
)
type RPCStateManager struct {
gapi api.GatewayAPI
}
func NewRPCStateManager(api api.GatewayAPI) *RPCStateManager {
return &RPCStateManager{gapi: api}
}
func (s *RPCStateManager) LoadActorTsk(ctx context.Context, addr address.Address, tsk types.TipSetKey) (*types.Actor, error) {
return s.gapi.StateGetActor(ctx, addr, tsk)
}
func (s *RPCStateManager) ResolveToKeyAddress(ctx context.Context, addr address.Address, ts *types.TipSet) (address.Address, error) {
return s.gapi.StateAccountKey(ctx, addr, ts.Key())
}
var _ stmgr.StateManagerAPI = (*RPCStateManager)(nil)