Skip to content

Commit

Permalink
feat: lotus-lite - replace wallet StateManager with thin client to ga…
Browse files Browse the repository at this point in the history
…teway
  • Loading branch information
dirkmc committed Sep 29, 2020
1 parent 8205149 commit ab14f79
Show file tree
Hide file tree
Showing 10 changed files with 163 additions and 15 deletions.
17 changes: 17 additions & 0 deletions api/api_gateway.go
Original file line number Diff line number Diff line change
@@ -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)
}
32 changes: 32 additions & 0 deletions api/apistruct/struct.go
Original file line number Diff line number Diff line change
Expand Up @@ -350,6 +350,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) {
Expand Down Expand Up @@ -1329,7 +1340,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{}
14 changes: 14 additions & 0 deletions api/client/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -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
}
7 changes: 7 additions & 0 deletions chain/stmgr/stmgr.go
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,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 StateManager struct {
cs *store.ChainStore

Expand Down Expand Up @@ -1314,3 +1319,5 @@ func (sm *StateManager) GetMarketState(ctx context.Context, ts *types.TipSet) (m
}
return actState, nil
}

var _ StateManagerAPI = (*StateManager)(nil)
9 changes: 9 additions & 0 deletions cli/cmd.go
Original file line number Diff line number Diff line change
Expand Up @@ -251,6 +251,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)
Expand Down
33 changes: 22 additions & 11 deletions cmd/lotus-gateway/api.go
Original file line number Diff line number Diff line change
Expand Up @@ -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()
Expand Down Expand Up @@ -88,3 +77,25 @@ func (a *GatewayAPI) MpoolPush(ctx context.Context, sm *types.SignedMessage) (ci

return a.api.MpoolPush(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)
}
28 changes: 28 additions & 0 deletions cmd/lotus/daemon.go
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down Expand Up @@ -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",
Expand Down Expand Up @@ -232,6 +238,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,
Expand All @@ -243,6 +270,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 {
Expand Down
1 change: 1 addition & 0 deletions node/builder.go
Original file line number Diff line number Diff line change
Expand Up @@ -258,6 +258,7 @@ func Online() Option {
Override(new(vm.SyscallBuilder), vm.Syscalls),
Override(new(*store.ChainStore), modules.ChainStore),
Override(new(*stmgr.StateManager), stmgr.NewStateManager),
Override(new(stmgr.StateManagerAPI), stmgr.NewStateManager),
Override(new(*wallet.Wallet), wallet.NewWallet),

Override(new(dtypes.ChainGCLocker), blockstore.NewGCLocker),
Expand Down
8 changes: 4 additions & 4 deletions node/impl/full/wallet.go
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand All @@ -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 {
Expand All @@ -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)
}
Expand Down
29 changes: 29 additions & 0 deletions node/modules/statemanager.go
Original file line number Diff line number Diff line change
@@ -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)

0 comments on commit ab14f79

Please sign in to comment.