Fix jsonrpc client after splitting apis

This commit is contained in:
Łukasz Magiera 2019-07-24 02:40:19 +02:00
parent eda03095b0
commit f0e807dabb
7 changed files with 197 additions and 172 deletions

View File

@ -7,9 +7,26 @@ import (
"github.com/filecoin-project/go-lotus/lib/jsonrpc" "github.com/filecoin-project/go-lotus/lib/jsonrpc"
) )
// NewRPC creates a new http jsonrpc client. // NewFullNodeRPC creates a new http jsonrpc client.
func NewRPC(addr string, requestHeader http.Header) (api.FullNode, error) { func NewFullNodeRPC(addr string, requestHeader http.Header) (api.FullNode, error) {
var res api.FullNodeStruct var res api.FullNodeStruct
_, err := jsonrpc.NewClient(addr, "Filecoin", &res.Internal, requestHeader) _, err := jsonrpc.NewMergeClient(addr, "Filecoin",
[]interface{}{
&res.CommonStruct.Internal,
&res.Internal,
}, requestHeader)
return &res, err
}
// NewStorageMinerRPC creates a new http jsonrpc client for storage miner
func NewStorageMinerRPC(addr string, requestHeader http.Header) (api.StorageMiner, error) {
var res api.StorageMinerStruct
_, err := jsonrpc.NewMergeClient(addr, "Filecoin",
[]interface{}{
&res.CommonStruct.Internal,
&res.Internal,
}, requestHeader)
return &res, err return &res, err
} }

View File

@ -48,7 +48,7 @@ func GetAPI(ctx *cli.Context) (api.FullNode, error) {
headers.Add("Authorization", "Bearer "+string(token)) headers.Add("Authorization", "Bearer "+string(token))
} }
return client.NewRPC("ws://"+addr+"/rpc/v0", headers) return client.NewFullNodeRPC("ws://"+addr+"/rpc/v0", headers)
} }
// ReqContext returns context for cli execution. Calling it for the first time // ReqContext returns context for cli execution. Calling it for the first time

View File

@ -66,7 +66,7 @@ var runCmd = &cli.Command{
log.Infof("Remote version %s", v) log.Infof("Remote version %s", v)
rpcServer := jsonrpc.NewServer() rpcServer := jsonrpc.NewServer()
//rpcServer.Register("Filecoin", minerapi) rpcServer.Register("Filecoin", minerapi)
http.Handle("/rpc/v0", rpcServer) http.Handle("/rpc/v0", rpcServer)
return http.ListenAndServe("127.0.0.1:"+cctx.String("api"), http.DefaultServeMux) return http.ListenAndServe("127.0.0.1:"+cctx.String("api"), http.DefaultServeMux)
}, },

View File

@ -59,17 +59,12 @@ type ClientCloser func()
// Returned value closes the client connection // Returned value closes the client connection
// TODO: Example // TODO: Example
func NewClient(addr string, namespace string, handler interface{}, requestHeader http.Header) (ClientCloser, error) { func NewClient(addr string, namespace string, handler interface{}, requestHeader http.Header) (ClientCloser, error) {
htyp := reflect.TypeOf(handler) return NewMergeClient(addr, namespace, []interface{}{handler}, requestHeader)
if htyp.Kind() != reflect.Ptr { }
return nil, xerrors.New("expected handler to be a pointer")
}
typ := htyp.Elem()
if typ.Kind() != reflect.Struct {
return nil, xerrors.New("handler should be a struct")
}
val := reflect.ValueOf(handler)
// NewMergeClient is like NewClient, but allows to specify multiple structs
// to be filled in the same namespace, using one connection
func NewMergeClient(addr string, namespace string, outs []interface{}, requestHeader http.Header) (ClientCloser, error) {
var idCtr int64 var idCtr int64
conn, _, err := websocket.DefaultDialer.Dial(addr, requestHeader) conn, _, err := websocket.DefaultDialer.Dial(addr, requestHeader)
@ -88,6 +83,18 @@ func NewClient(addr string, namespace string, handler interface{}, requestHeader
stop: stop, stop: stop,
}).handleWsConn(context.TODO()) }).handleWsConn(context.TODO())
for _, handler := range outs {
htyp := reflect.TypeOf(handler)
if htyp.Kind() != reflect.Ptr {
return nil, xerrors.New("expected handler to be a pointer")
}
typ := htyp.Elem()
if typ.Kind() != reflect.Struct {
return nil, xerrors.New("handler should be a struct")
}
val := reflect.ValueOf(handler)
for i := 0; i < typ.NumField(); i++ { for i := 0; i < typ.NumField(); i++ {
f := typ.Field(i) f := typ.Field(i)
ftyp := f.Type ftyp := f.Type
@ -242,6 +249,7 @@ func NewClient(addr string, namespace string, handler interface{}, requestHeader
val.Elem().Field(i).Set(fn) val.Elem().Field(i).Set(fn)
} }
}
return func() { return func() {
close(stop) close(stop)

View File

@ -24,7 +24,7 @@ import (
var log = logging.Logger("node") var log = logging.Logger("node")
type API struct { type FullNodeAPI struct {
client.LocalStorage client.LocalStorage
Host host.Host Host host.Host
@ -39,7 +39,7 @@ type jwtPayload struct {
Allow []string Allow []string
} }
func (a *API) AuthVerify(ctx context.Context, token string) ([]string, error) { func (a *FullNodeAPI) AuthVerify(ctx context.Context, token string) ([]string, error) {
var payload jwtPayload var payload jwtPayload
if _, err := jwt.Verify([]byte(token), (*jwt.HMACSHA)(a.APISecret), &payload); err != nil { if _, err := jwt.Verify([]byte(token), (*jwt.HMACSHA)(a.APISecret), &payload); err != nil {
return nil, xerrors.Errorf("JWT Verification failed: %w", err) return nil, xerrors.Errorf("JWT Verification failed: %w", err)
@ -48,7 +48,7 @@ func (a *API) AuthVerify(ctx context.Context, token string) ([]string, error) {
return payload.Allow, nil return payload.Allow, nil
} }
func (a *API) AuthNew(ctx context.Context, perms []string) ([]byte, error) { func (a *FullNodeAPI) AuthNew(ctx context.Context, perms []string) ([]byte, error) {
p := jwtPayload{ p := jwtPayload{
Allow: perms, // TODO: consider checking validity Allow: perms, // TODO: consider checking validity
} }
@ -56,7 +56,7 @@ func (a *API) AuthNew(ctx context.Context, perms []string) ([]byte, error) {
return jwt.Sign(&p, (*jwt.HMACSHA)(a.APISecret)) return jwt.Sign(&p, (*jwt.HMACSHA)(a.APISecret))
} }
func (a *API) ChainSubmitBlock(ctx context.Context, blk *chain.BlockMsg) error { func (a *FullNodeAPI) ChainSubmitBlock(ctx context.Context, blk *chain.BlockMsg) error {
if err := a.Chain.AddBlock(blk.Header); err != nil { if err := a.Chain.AddBlock(blk.Header); err != nil {
return err return err
} }
@ -70,24 +70,24 @@ func (a *API) ChainSubmitBlock(ctx context.Context, blk *chain.BlockMsg) error {
return a.PubSub.Publish("/fil/blocks", b) return a.PubSub.Publish("/fil/blocks", b)
} }
func (a *API) ChainHead(context.Context) (*chain.TipSet, error) { func (a *FullNodeAPI) ChainHead(context.Context) (*chain.TipSet, error) {
return a.Chain.GetHeaviestTipSet(), nil return a.Chain.GetHeaviestTipSet(), nil
} }
func (a *API) ChainGetRandomness(ctx context.Context, pts *chain.TipSet) ([]byte, error) { func (a *FullNodeAPI) ChainGetRandomness(ctx context.Context, pts *chain.TipSet) ([]byte, error) {
// TODO: this needs to look back in the chain for the right random beacon value // TODO: this needs to look back in the chain for the right random beacon value
return []byte("foo bar random"), nil return []byte("foo bar random"), nil
} }
func (a *API) ChainWaitMsg(ctx context.Context, msg cid.Cid) (*api.MsgWait, error) { func (a *FullNodeAPI) ChainWaitMsg(ctx context.Context, msg cid.Cid) (*api.MsgWait, error) {
panic("TODO") panic("TODO")
} }
func (a *API) ChainGetBlock(ctx context.Context, msg cid.Cid) (*chain.BlockHeader, error) { func (a *FullNodeAPI) ChainGetBlock(ctx context.Context, msg cid.Cid) (*chain.BlockHeader, error) {
return a.Chain.GetBlock(msg) return a.Chain.GetBlock(msg)
} }
func (a *API) ChainGetBlockMessages(ctx context.Context, msg cid.Cid) ([]*chain.SignedMessage, error) { func (a *FullNodeAPI) ChainGetBlockMessages(ctx context.Context, msg cid.Cid) ([]*chain.SignedMessage, error) {
b, err := a.Chain.GetBlock(msg) b, err := a.Chain.GetBlock(msg)
if err != nil { if err != nil {
return nil, err return nil, err
@ -96,23 +96,23 @@ func (a *API) ChainGetBlockMessages(ctx context.Context, msg cid.Cid) ([]*chain.
return a.Chain.MessagesForBlock(b) return a.Chain.MessagesForBlock(b)
} }
func (a *API) ID(context.Context) (peer.ID, error) { func (a *FullNodeAPI) ID(context.Context) (peer.ID, error) {
return a.Host.ID(), nil return a.Host.ID(), nil
} }
func (a *API) Version(context.Context) (api.Version, error) { func (a *FullNodeAPI) Version(context.Context) (api.Version, error) {
return api.Version{ return api.Version{
Version: build.Version, Version: build.Version,
}, nil }, nil
} }
func (a *API) MpoolPending(ctx context.Context, ts *chain.TipSet) ([]*chain.SignedMessage, error) { func (a *FullNodeAPI) MpoolPending(ctx context.Context, ts *chain.TipSet) ([]*chain.SignedMessage, error) {
// TODO: need to make sure we don't return messages that were already included in the referenced chain // TODO: need to make sure we don't return messages that were already included in the referenced chain
// also need to accept ts == nil just fine, assume nil == chain.Head() // also need to accept ts == nil just fine, assume nil == chain.Head()
return a.Mpool.Pending(), nil return a.Mpool.Pending(), nil
} }
func (a *API) MpoolPush(ctx context.Context, smsg *chain.SignedMessage) error { func (a *FullNodeAPI) MpoolPush(ctx context.Context, smsg *chain.SignedMessage) error {
msgb, err := smsg.Serialize() msgb, err := smsg.Serialize()
if err != nil { if err != nil {
return err return err
@ -121,11 +121,11 @@ func (a *API) MpoolPush(ctx context.Context, smsg *chain.SignedMessage) error {
return a.PubSub.Publish("/fil/messages", msgb) return a.PubSub.Publish("/fil/messages", msgb)
} }
func (a *API) MpoolGetNonce(ctx context.Context, addr address.Address) (uint64, error) { func (a *FullNodeAPI) MpoolGetNonce(ctx context.Context, addr address.Address) (uint64, error) {
return a.Mpool.GetNonce(addr) return a.Mpool.GetNonce(addr)
} }
func (a *API) MinerStart(ctx context.Context, addr address.Address) error { func (a *FullNodeAPI) MinerStart(ctx context.Context, addr address.Address) error {
// hrm... // hrm...
m := miner.NewMiner(a, addr) m := miner.NewMiner(a, addr)
@ -134,7 +134,7 @@ func (a *API) MinerStart(ctx context.Context, addr address.Address) error {
return nil return nil
} }
func (a *API) MinerCreateBlock(ctx context.Context, addr address.Address, parents *chain.TipSet, tickets []chain.Ticket, proof chain.ElectionProof, msgs []*chain.SignedMessage) (*chain.BlockMsg, error) { func (a *FullNodeAPI) MinerCreateBlock(ctx context.Context, addr address.Address, parents *chain.TipSet, tickets []chain.Ticket, proof chain.ElectionProof, msgs []*chain.SignedMessage) (*chain.BlockMsg, error) {
fblk, err := chain.MinerCreateBlock(a.Chain, addr, parents, tickets, proof, msgs) fblk, err := chain.MinerCreateBlock(a.Chain, addr, parents, tickets, proof, msgs)
if err != nil { if err != nil {
return nil, err return nil, err
@ -149,7 +149,7 @@ func (a *API) MinerCreateBlock(ctx context.Context, addr address.Address, parent
return &out, nil return &out, nil
} }
func (a *API) NetPeers(context.Context) ([]peer.AddrInfo, error) { func (a *FullNodeAPI) NetPeers(context.Context) ([]peer.AddrInfo, error) {
conns := a.Host.Network().Conns() conns := a.Host.Network().Conns()
out := make([]peer.AddrInfo, len(conns)) out := make([]peer.AddrInfo, len(conns))
@ -165,23 +165,23 @@ func (a *API) NetPeers(context.Context) ([]peer.AddrInfo, error) {
return out, nil return out, nil
} }
func (a *API) WalletNew(ctx context.Context, typ string) (address.Address, error) { func (a *FullNodeAPI) WalletNew(ctx context.Context, typ string) (address.Address, error) {
return a.Wallet.GenerateKey(typ) return a.Wallet.GenerateKey(typ)
} }
func (a *API) WalletList(ctx context.Context) ([]address.Address, error) { func (a *FullNodeAPI) WalletList(ctx context.Context) ([]address.Address, error) {
return a.Wallet.ListAddrs() return a.Wallet.ListAddrs()
} }
func (a *API) WalletBalance(ctx context.Context, addr address.Address) (types.BigInt, error) { func (a *FullNodeAPI) WalletBalance(ctx context.Context, addr address.Address) (types.BigInt, error) {
return a.Chain.GetBalance(addr) return a.Chain.GetBalance(addr)
} }
func (a *API) WalletSign(ctx context.Context, k address.Address, msg []byte) (*chain.Signature, error) { func (a *FullNodeAPI) WalletSign(ctx context.Context, k address.Address, msg []byte) (*chain.Signature, error) {
return a.Wallet.Sign(k, msg) return a.Wallet.Sign(k, msg)
} }
func (a *API) WalletDefaultAddress(ctx context.Context) (address.Address, error) { func (a *FullNodeAPI) WalletDefaultAddress(ctx context.Context) (address.Address, error) {
addrs, err := a.Wallet.ListAddrs() addrs, err := a.Wallet.ListAddrs()
if err != nil { if err != nil {
return address.Undef, err return address.Undef, err
@ -191,15 +191,15 @@ func (a *API) WalletDefaultAddress(ctx context.Context) (address.Address, error)
return addrs[0], nil return addrs[0], nil
} }
func (a *API) NetConnect(ctx context.Context, p peer.AddrInfo) error { func (a *FullNodeAPI) NetConnect(ctx context.Context, p peer.AddrInfo) error {
return a.Host.Connect(ctx, p) return a.Host.Connect(ctx, p)
} }
func (a *API) NetAddrsListen(context.Context) (peer.AddrInfo, error) { func (a *FullNodeAPI) NetAddrsListen(context.Context) (peer.AddrInfo, error) {
return peer.AddrInfo{ return peer.AddrInfo{
ID: a.Host.ID(), ID: a.Host.ID(),
Addrs: a.Host.Addrs(), Addrs: a.Host.Addrs(),
}, nil }, nil
} }
var _ api.FullNode = &API{} var _ api.FullNode = &FullNodeAPI{}

View File

@ -270,7 +270,7 @@ func Repo(r repo.Repo) Option {
func FullAPI(out *api.FullNode) Option { func FullAPI(out *api.FullNode) Option {
return func(s *Settings) error { return func(s *Settings) error {
resAPI := &API{} resAPI := &FullNodeAPI{}
s.invokes[ExtractApiKey] = fx.Extract(resAPI) s.invokes[ExtractApiKey] = fx.Extract(resAPI)
*out = resAPI *out = resAPI
return nil return nil

View File

@ -58,7 +58,7 @@ func rpcBuilder(t *testing.T, n int) []api.FullNode {
testServ := httptest.NewServer(rpcServer) // todo: close testServ := httptest.NewServer(rpcServer) // todo: close
var err error var err error
out[i], err = client.NewRPC("ws://"+testServ.Listener.Addr().String(), nil) out[i], err = client.NewFullNodeRPC("ws://"+testServ.Listener.Addr().String(), nil)
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }