2019-07-08 19:07:16 +00:00
|
|
|
package node
|
|
|
|
|
|
|
|
import (
|
|
|
|
"context"
|
2019-07-16 16:07:08 +00:00
|
|
|
|
2019-07-08 19:07:16 +00:00
|
|
|
"github.com/filecoin-project/go-lotus/api"
|
|
|
|
"github.com/filecoin-project/go-lotus/build"
|
2019-07-09 15:19:27 +00:00
|
|
|
"github.com/filecoin-project/go-lotus/chain"
|
2019-07-11 02:36:43 +00:00
|
|
|
"github.com/filecoin-project/go-lotus/chain/address"
|
2019-07-18 20:26:04 +00:00
|
|
|
"github.com/filecoin-project/go-lotus/chain/types"
|
2019-07-11 02:36:43 +00:00
|
|
|
"github.com/filecoin-project/go-lotus/miner"
|
2019-07-12 09:59:18 +00:00
|
|
|
"github.com/filecoin-project/go-lotus/node/client"
|
2019-07-23 18:49:09 +00:00
|
|
|
"github.com/filecoin-project/go-lotus/node/repo"
|
2019-07-08 19:07:16 +00:00
|
|
|
|
2019-07-23 17:27:45 +00:00
|
|
|
"github.com/gbrlsnchs/jwt/v3"
|
2019-07-17 03:05:55 +00:00
|
|
|
"github.com/ipfs/go-cid"
|
2019-07-23 17:27:45 +00:00
|
|
|
logging "github.com/ipfs/go-log"
|
2019-07-08 19:07:16 +00:00
|
|
|
"github.com/libp2p/go-libp2p-core/host"
|
|
|
|
"github.com/libp2p/go-libp2p-core/peer"
|
2019-07-09 15:19:27 +00:00
|
|
|
pubsub "github.com/libp2p/go-libp2p-pubsub"
|
2019-07-08 21:01:15 +00:00
|
|
|
ma "github.com/multiformats/go-multiaddr"
|
2019-07-23 17:27:45 +00:00
|
|
|
"golang.org/x/xerrors"
|
2019-07-08 19:07:16 +00:00
|
|
|
)
|
|
|
|
|
2019-07-23 17:27:45 +00:00
|
|
|
var log = logging.Logger("node")
|
|
|
|
|
2019-07-09 10:58:13 +00:00
|
|
|
type API struct {
|
2019-07-12 09:59:18 +00:00
|
|
|
client.LocalStorage
|
|
|
|
|
2019-07-23 18:49:09 +00:00
|
|
|
Host host.Host
|
|
|
|
Chain *chain.ChainStore
|
|
|
|
PubSub *pubsub.PubSub
|
|
|
|
Mpool *chain.MessagePool
|
|
|
|
Wallet *chain.Wallet
|
2019-07-23 17:27:45 +00:00
|
|
|
Keystore types.KeyStore
|
2019-07-23 18:49:09 +00:00
|
|
|
Repo repo.LockedRepo
|
2019-07-23 17:27:45 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
const JWTSecretName = "auth-jwt-private"
|
|
|
|
|
|
|
|
type jwtPayload struct {
|
|
|
|
Allow []string
|
|
|
|
}
|
|
|
|
|
|
|
|
func (a *API) AuthVerify(ctx context.Context, token string) ([]string, error) {
|
|
|
|
key, err := a.Keystore.Get(JWTSecretName)
|
|
|
|
if err != nil {
|
|
|
|
return nil, xerrors.Errorf("couldn't get JWT secret: %w", err)
|
|
|
|
}
|
|
|
|
|
|
|
|
var payload jwtPayload
|
|
|
|
if _, err := jwt.Verify([]byte(token), jwt.NewHS256(key.PrivateKey), &payload); err != nil {
|
|
|
|
return nil, xerrors.Errorf("JWT Verification failed: %w", err)
|
|
|
|
}
|
|
|
|
|
|
|
|
return payload.Allow, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
func (a *API) AuthNew(ctx context.Context, perms []string) ([]byte, error) {
|
|
|
|
key, err := a.Keystore.Get(JWTSecretName)
|
|
|
|
if err != nil {
|
|
|
|
log.Warn("Generating new API secret")
|
|
|
|
|
|
|
|
key = types.KeyInfo{
|
|
|
|
Type: "jwt-hmac-secret",
|
|
|
|
PrivateKey: make([]byte, 32),
|
|
|
|
}
|
|
|
|
|
|
|
|
if err := a.Keystore.Put(JWTSecretName, key); err != nil {
|
|
|
|
return nil, xerrors.Errorf("writing API secret: %w", err)
|
|
|
|
}
|
|
|
|
|
2019-07-23 18:49:09 +00:00
|
|
|
// TODO: make this configurable
|
|
|
|
p := jwtPayload{
|
|
|
|
Allow: api.AllPermissions,
|
|
|
|
}
|
|
|
|
|
|
|
|
cliToken, err := jwt.Sign(&p, jwt.NewHS256(key.PrivateKey))
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
|
|
|
|
if err := a.Repo.SetAPIToken(cliToken); err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
2019-07-23 17:27:45 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
p := jwtPayload{
|
|
|
|
Allow: perms, // TODO: consider checking validity
|
|
|
|
}
|
|
|
|
|
|
|
|
return jwt.Sign(&p, jwt.NewHS256(key.PrivateKey))
|
2019-07-09 15:19:27 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
func (a *API) ChainSubmitBlock(ctx context.Context, blk *chain.BlockMsg) error {
|
2019-07-11 02:36:43 +00:00
|
|
|
if err := a.Chain.AddBlock(blk.Header); err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
2019-07-09 15:19:27 +00:00
|
|
|
b, err := blk.Serialize()
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
// TODO: anything else to do here?
|
|
|
|
return a.PubSub.Publish("/fil/blocks", b)
|
|
|
|
}
|
|
|
|
|
2019-07-11 02:36:43 +00:00
|
|
|
func (a *API) ChainHead(context.Context) (*chain.TipSet, error) {
|
|
|
|
return a.Chain.GetHeaviestTipSet(), nil
|
|
|
|
}
|
|
|
|
|
|
|
|
func (a *API) ChainGetRandomness(ctx context.Context, pts *chain.TipSet) ([]byte, error) {
|
|
|
|
// TODO: this needs to look back in the chain for the right random beacon value
|
|
|
|
return []byte("foo bar random"), nil
|
2019-07-08 19:07:16 +00:00
|
|
|
}
|
|
|
|
|
2019-07-17 06:05:11 +00:00
|
|
|
func (a *API) ChainWaitMsg(ctx context.Context, msg cid.Cid) (*api.MsgWait, error) {
|
|
|
|
panic("TODO")
|
2019-07-17 03:05:55 +00:00
|
|
|
}
|
|
|
|
|
2019-07-23 00:54:27 +00:00
|
|
|
func (a *API) ChainGetBlock(ctx context.Context, msg cid.Cid) (*chain.BlockHeader, error) {
|
|
|
|
return a.Chain.GetBlock(msg)
|
|
|
|
}
|
|
|
|
|
|
|
|
func (a *API) ChainGetBlockMessages(ctx context.Context, msg cid.Cid) ([]*chain.SignedMessage, error) {
|
|
|
|
b, err := a.Chain.GetBlock(msg)
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
|
|
|
|
return a.Chain.MessagesForBlock(b)
|
|
|
|
}
|
|
|
|
|
2019-07-09 10:58:13 +00:00
|
|
|
func (a *API) ID(context.Context) (peer.ID, error) {
|
|
|
|
return a.Host.ID(), nil
|
2019-07-08 19:07:16 +00:00
|
|
|
}
|
|
|
|
|
2019-07-09 10:58:13 +00:00
|
|
|
func (a *API) Version(context.Context) (api.Version, error) {
|
|
|
|
return api.Version{
|
|
|
|
Version: build.Version,
|
|
|
|
}, nil
|
2019-07-08 19:07:16 +00:00
|
|
|
}
|
|
|
|
|
2019-07-11 02:36:43 +00:00
|
|
|
func (a *API) 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
|
|
|
|
// also need to accept ts == nil just fine, assume nil == chain.Head()
|
2019-07-09 22:58:51 +00:00
|
|
|
return a.Mpool.Pending(), nil
|
|
|
|
}
|
|
|
|
|
2019-07-17 03:05:55 +00:00
|
|
|
func (a *API) MpoolPush(ctx context.Context, smsg *chain.SignedMessage) error {
|
|
|
|
msgb, err := smsg.Serialize()
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
return a.PubSub.Publish("/fil/messages", msgb)
|
|
|
|
}
|
|
|
|
|
|
|
|
func (a *API) MpoolGetNonce(ctx context.Context, addr address.Address) (uint64, error) {
|
|
|
|
return a.Mpool.GetNonce(addr)
|
|
|
|
}
|
|
|
|
|
2019-07-11 02:36:43 +00:00
|
|
|
func (a *API) MinerStart(ctx context.Context, addr address.Address) error {
|
|
|
|
// hrm...
|
|
|
|
m := miner.NewMiner(a, addr)
|
|
|
|
|
|
|
|
go m.Mine(context.TODO())
|
|
|
|
|
|
|
|
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) {
|
|
|
|
fblk, err := chain.MinerCreateBlock(a.Chain, addr, parents, tickets, proof, msgs)
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
|
|
|
|
var out chain.BlockMsg
|
|
|
|
out.Header = fblk.Header
|
|
|
|
for _, msg := range fblk.Messages {
|
|
|
|
out.Messages = append(out.Messages, msg.Cid())
|
|
|
|
}
|
|
|
|
|
|
|
|
return &out, nil
|
|
|
|
}
|
|
|
|
|
2019-07-09 10:58:13 +00:00
|
|
|
func (a *API) NetPeers(context.Context) ([]peer.AddrInfo, error) {
|
|
|
|
conns := a.Host.Network().Conns()
|
|
|
|
out := make([]peer.AddrInfo, len(conns))
|
2019-07-08 19:07:16 +00:00
|
|
|
|
2019-07-09 10:58:13 +00:00
|
|
|
for i, conn := range conns {
|
|
|
|
out[i] = peer.AddrInfo{
|
|
|
|
ID: conn.RemotePeer(),
|
|
|
|
Addrs: []ma.Multiaddr{
|
|
|
|
conn.RemoteMultiaddr(),
|
|
|
|
},
|
2019-07-08 19:07:16 +00:00
|
|
|
}
|
|
|
|
}
|
2019-07-09 10:58:13 +00:00
|
|
|
|
|
|
|
return out, nil
|
2019-07-08 19:07:16 +00:00
|
|
|
}
|
|
|
|
|
2019-07-13 00:41:32 +00:00
|
|
|
func (a *API) WalletNew(ctx context.Context, typ string) (address.Address, error) {
|
|
|
|
return a.Wallet.GenerateKey(typ)
|
|
|
|
}
|
|
|
|
|
|
|
|
func (a *API) WalletList(ctx context.Context) ([]address.Address, error) {
|
2019-07-18 15:41:30 +00:00
|
|
|
return a.Wallet.ListAddrs()
|
2019-07-13 00:41:32 +00:00
|
|
|
}
|
|
|
|
|
2019-07-18 20:26:04 +00:00
|
|
|
func (a *API) WalletBalance(ctx context.Context, addr address.Address) (types.BigInt, error) {
|
|
|
|
return a.Chain.GetBalance(addr)
|
|
|
|
}
|
|
|
|
|
2019-07-17 03:05:55 +00:00
|
|
|
func (a *API) WalletSign(ctx context.Context, k address.Address, msg []byte) (*chain.Signature, error) {
|
|
|
|
return a.Wallet.Sign(k, msg)
|
|
|
|
}
|
|
|
|
|
|
|
|
func (a *API) WalletDefaultAddress(ctx context.Context) (address.Address, error) {
|
2019-07-18 19:12:30 +00:00
|
|
|
addrs, err := a.Wallet.ListAddrs()
|
|
|
|
if err != nil {
|
|
|
|
return address.Undef, err
|
|
|
|
}
|
2019-07-17 03:05:55 +00:00
|
|
|
|
|
|
|
// TODO: store a default address in the config or 'wallet' portion of the repo
|
|
|
|
return addrs[0], nil
|
|
|
|
}
|
|
|
|
|
2019-07-09 10:58:13 +00:00
|
|
|
func (a *API) NetConnect(ctx context.Context, p peer.AddrInfo) error {
|
|
|
|
return a.Host.Connect(ctx, p)
|
2019-07-08 19:07:16 +00:00
|
|
|
}
|
2019-07-08 21:01:15 +00:00
|
|
|
|
2019-07-09 17:03:36 +00:00
|
|
|
func (a *API) NetAddrsListen(context.Context) (peer.AddrInfo, error) {
|
|
|
|
return peer.AddrInfo{
|
|
|
|
ID: a.Host.ID(),
|
|
|
|
Addrs: a.Host.Addrs(),
|
|
|
|
}, nil
|
2019-07-08 21:01:15 +00:00
|
|
|
}
|
2019-07-09 10:58:13 +00:00
|
|
|
|
|
|
|
var _ api.API = &API{}
|