feat: lotus-lite - replace wallet StateManager with thin client to gateway
This commit is contained in:
parent
bacac245c7
commit
e19cd9ed01
17
api/api_gateway.go
Normal file
17
api/api_gateway.go
Normal 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)
|
||||||
|
}
|
@ -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
|
// CommonStruct
|
||||||
|
|
||||||
func (c *CommonStruct) AuthVerify(ctx context.Context, token string) ([]auth.Permission, error) {
|
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)
|
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.Common = &CommonStruct{}
|
||||||
var _ api.FullNode = &FullNodeStruct{}
|
var _ api.FullNode = &FullNodeStruct{}
|
||||||
var _ api.StorageMiner = &StorageMinerStruct{}
|
var _ api.StorageMiner = &StorageMinerStruct{}
|
||||||
var _ api.WorkerAPI = &WorkerStruct{}
|
var _ api.WorkerAPI = &WorkerStruct{}
|
||||||
|
var _ api.GatewayAPI = &GatewayStruct{}
|
||||||
|
@ -82,3 +82,17 @@ func NewWorkerRPC(ctx context.Context, addr string, requestHeader http.Header) (
|
|||||||
|
|
||||||
return &res, closer, err
|
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
|
||||||
|
}
|
||||||
|
@ -40,6 +40,11 @@ import (
|
|||||||
|
|
||||||
var log = logging.Logger("statemgr")
|
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 {
|
type versionSpec struct {
|
||||||
networkVersion network.Version
|
networkVersion network.Version
|
||||||
atOrBelow abi.ChainEpoch
|
atOrBelow abi.ChainEpoch
|
||||||
@ -1393,3 +1398,5 @@ func (sm *StateManager) GetMarketState(ctx context.Context, ts *types.TipSet) (m
|
|||||||
}
|
}
|
||||||
return actState, nil
|
return actState, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var _ StateManagerAPI = (*StateManager)(nil)
|
||||||
|
@ -289,6 +289,15 @@ func GetWorkerAPI(ctx *cli.Context) (api.WorkerAPI, jsonrpc.ClientCloser, error)
|
|||||||
return client.NewWorkerRPC(ctx.Context, addr, headers)
|
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 {
|
func DaemonContext(cctx *cli.Context) context.Context {
|
||||||
if mtCtx, ok := cctx.App.Metadata[metadataTraceContext]; ok {
|
if mtCtx, ok := cctx.App.Metadata[metadataTraceContext]; ok {
|
||||||
return mtCtx.(context.Context)
|
return mtCtx.(context.Context)
|
||||||
|
@ -49,17 +49,6 @@ func (a *GatewayAPI) checkTipset(ctx context.Context, ts types.TipSetKey) error
|
|||||||
return nil
|
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) {
|
func (a *GatewayAPI) ChainHead(ctx context.Context) (*types.TipSet, error) {
|
||||||
ctx, span := trace.StartSpan(ctx, "ChainHead")
|
ctx, span := trace.StartSpan(ctx, "ChainHead")
|
||||||
defer span.End()
|
defer span.End()
|
||||||
@ -88,3 +77,25 @@ func (a *GatewayAPI) MpoolPush(ctx context.Context, sm *types.SignedMessage) (ci
|
|||||||
|
|
||||||
return a.api.MpoolPushUntrusted(ctx, sm)
|
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)
|
||||||
|
}
|
||||||
|
@ -15,6 +15,8 @@ import (
|
|||||||
"runtime/pprof"
|
"runtime/pprof"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
|
"go.uber.org/fx"
|
||||||
|
|
||||||
"github.com/filecoin-project/lotus/chain/types"
|
"github.com/filecoin-project/lotus/chain/types"
|
||||||
|
|
||||||
paramfetch "github.com/filecoin-project/go-paramfetch"
|
paramfetch "github.com/filecoin-project/go-paramfetch"
|
||||||
@ -114,6 +116,10 @@ var DaemonCmd = &cli.Command{
|
|||||||
Name: "halt-after-import",
|
Name: "halt-after-import",
|
||||||
Usage: "halt the process after importing chain from file",
|
Usage: "halt the process after importing chain from file",
|
||||||
},
|
},
|
||||||
|
&cli.BoolFlag{
|
||||||
|
Name: "lite",
|
||||||
|
Usage: "start lotus in lite mode",
|
||||||
|
},
|
||||||
&cli.StringFlag{
|
&cli.StringFlag{
|
||||||
Name: "pprof",
|
Name: "pprof",
|
||||||
Usage: "specify name of file for writing cpu profile to",
|
Usage: "specify name of file for writing cpu profile to",
|
||||||
@ -240,6 +246,27 @@ var DaemonCmd = &cli.Command{
|
|||||||
|
|
||||||
shutdownChan := make(chan struct{})
|
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
|
var api api.FullNode
|
||||||
|
|
||||||
stop, err := node.New(ctx,
|
stop, err := node.New(ctx,
|
||||||
@ -251,6 +278,7 @@ var DaemonCmd = &cli.Command{
|
|||||||
node.Repo(r),
|
node.Repo(r),
|
||||||
|
|
||||||
genesis,
|
genesis,
|
||||||
|
liteMode,
|
||||||
|
|
||||||
node.ApplyIf(func(s *node.Settings) bool { return cctx.IsSet("api") },
|
node.ApplyIf(func(s *node.Settings) bool { return cctx.IsSet("api") },
|
||||||
node.Override(node.SetApiEndpointKey, func(lr repo.LockedRepo) error {
|
node.Override(node.SetApiEndpointKey, func(lr repo.LockedRepo) error {
|
||||||
|
@ -261,6 +261,7 @@ func Online() Option {
|
|||||||
Override(new(*store.ChainStore), modules.ChainStore),
|
Override(new(*store.ChainStore), modules.ChainStore),
|
||||||
Override(new(stmgr.UpgradeSchedule), stmgr.DefaultUpgradeSchedule()),
|
Override(new(stmgr.UpgradeSchedule), stmgr.DefaultUpgradeSchedule()),
|
||||||
Override(new(*stmgr.StateManager), stmgr.NewStateManagerWithUpgradeSchedule),
|
Override(new(*stmgr.StateManager), stmgr.NewStateManagerWithUpgradeSchedule),
|
||||||
|
Override(new(stmgr.StateManagerAPI), From(new(*stmgr.StateManager))),
|
||||||
Override(new(*wallet.Wallet), wallet.NewWallet),
|
Override(new(*wallet.Wallet), wallet.NewWallet),
|
||||||
Override(new(*messagesigner.MessageSigner), messagesigner.NewMessageSigner),
|
Override(new(*messagesigner.MessageSigner), messagesigner.NewMessageSigner),
|
||||||
|
|
||||||
|
@ -19,8 +19,8 @@ import (
|
|||||||
type WalletAPI struct {
|
type WalletAPI struct {
|
||||||
fx.In
|
fx.In
|
||||||
|
|
||||||
StateManager *stmgr.StateManager
|
stmgr.StateManagerAPI
|
||||||
Wallet *wallet.Wallet
|
Wallet *wallet.Wallet
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *WalletAPI) WalletNew(ctx context.Context, typ crypto.SigType) (address.Address, error) {
|
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) {
|
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) {
|
if xerrors.Is(err, types.ErrActorNotFound) {
|
||||||
return big.Zero(), nil
|
return big.Zero(), nil
|
||||||
} else if err != 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) {
|
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 {
|
if err != nil {
|
||||||
return nil, xerrors.Errorf("failed to resolve ID address: %w", keyAddr)
|
return nil, xerrors.Errorf("failed to resolve ID address: %w", keyAddr)
|
||||||
}
|
}
|
||||||
|
29
node/modules/statemanager.go
Normal file
29
node/modules/statemanager.go
Normal 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)
|
Loading…
Reference in New Issue
Block a user