2019-07-24 01:13:56 +00:00
|
|
|
package impl
|
2019-07-08 19:07:16 +00:00
|
|
|
|
|
|
|
import (
|
|
|
|
"context"
|
2019-07-26 04:54:22 +00:00
|
|
|
|
2019-07-25 23:26:40 +00:00
|
|
|
"golang.org/x/xerrors"
|
2019-07-16 16:07:08 +00:00
|
|
|
|
2019-07-08 19:07:16 +00:00
|
|
|
"github.com/filecoin-project/go-lotus/api"
|
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-25 22:15:33 +00:00
|
|
|
"github.com/filecoin-project/go-lotus/chain/gen"
|
2019-07-26 04:54:22 +00:00
|
|
|
"github.com/filecoin-project/go-lotus/chain/store"
|
2019-07-18 20:26:04 +00:00
|
|
|
"github.com/filecoin-project/go-lotus/chain/types"
|
2019-07-30 00:46:56 +00:00
|
|
|
"github.com/filecoin-project/go-lotus/chain/vm"
|
2019-07-25 22:15:33 +00:00
|
|
|
"github.com/filecoin-project/go-lotus/chain/wallet"
|
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 20:27:05 +00:00
|
|
|
|
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-09 15:19:27 +00:00
|
|
|
pubsub "github.com/libp2p/go-libp2p-pubsub"
|
2019-07-08 19:07:16 +00:00
|
|
|
)
|
|
|
|
|
2019-07-23 17:27:45 +00:00
|
|
|
var log = logging.Logger("node")
|
|
|
|
|
2019-07-24 00:40:19 +00:00
|
|
|
type FullNodeAPI struct {
|
2019-07-12 09:59:18 +00:00
|
|
|
client.LocalStorage
|
|
|
|
|
2019-07-24 00:58:31 +00:00
|
|
|
CommonAPI
|
|
|
|
|
2019-07-26 04:54:22 +00:00
|
|
|
Chain *store.ChainStore
|
2019-07-24 01:10:26 +00:00
|
|
|
PubSub *pubsub.PubSub
|
|
|
|
Mpool *chain.MessagePool
|
2019-07-25 22:15:33 +00:00
|
|
|
Wallet *wallet.Wallet
|
2019-07-09 15:19:27 +00:00
|
|
|
}
|
|
|
|
|
2019-07-28 19:19:33 +00:00
|
|
|
func (a *FullNodeAPI) ChainNotify(ctx context.Context) (<-chan *store.HeadChange, error) {
|
|
|
|
return a.Chain.SubHeadChanges(ctx), nil
|
|
|
|
}
|
|
|
|
|
2019-07-24 00:40:19 +00:00
|
|
|
func (a *FullNodeAPI) 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-26 04:54:22 +00:00
|
|
|
func (a *FullNodeAPI) ChainHead(context.Context) (*types.TipSet, error) {
|
2019-07-11 02:36:43 +00:00
|
|
|
return a.Chain.GetHeaviestTipSet(), nil
|
|
|
|
}
|
|
|
|
|
2019-07-26 04:54:22 +00:00
|
|
|
func (a *FullNodeAPI) ChainGetRandomness(ctx context.Context, pts *types.TipSet) ([]byte, error) {
|
2019-07-11 02:36:43 +00:00
|
|
|
// 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-24 00:40:19 +00:00
|
|
|
func (a *FullNodeAPI) ChainWaitMsg(ctx context.Context, msg cid.Cid) (*api.MsgWait, error) {
|
2019-07-28 02:32:09 +00:00
|
|
|
blkcid, recpt, err := a.Chain.WaitForMessage(ctx, msg)
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
|
|
|
|
return &api.MsgWait{
|
|
|
|
InBlock: blkcid,
|
2019-07-28 05:35:32 +00:00
|
|
|
Receipt: *recpt,
|
2019-07-28 02:32:09 +00:00
|
|
|
}, nil
|
2019-07-17 03:05:55 +00:00
|
|
|
}
|
|
|
|
|
2019-07-25 22:15:03 +00:00
|
|
|
func (a *FullNodeAPI) ChainGetBlock(ctx context.Context, msg cid.Cid) (*types.BlockHeader, error) {
|
2019-07-23 00:54:27 +00:00
|
|
|
return a.Chain.GetBlock(msg)
|
|
|
|
}
|
|
|
|
|
2019-08-02 03:51:34 +00:00
|
|
|
func (a *FullNodeAPI) ChainGetBlockMessages(ctx context.Context, msg cid.Cid) (*api.BlockMessages, error) {
|
2019-07-23 00:54:27 +00:00
|
|
|
b, err := a.Chain.GetBlock(msg)
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
|
2019-08-02 03:51:34 +00:00
|
|
|
bmsgs, smsgs, err := a.Chain.MessagesForBlock(b)
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
2019-07-23 00:54:27 +00:00
|
|
|
}
|
|
|
|
|
2019-08-02 03:51:34 +00:00
|
|
|
return &api.BlockMessages{
|
|
|
|
BlsMessages: bmsgs,
|
|
|
|
SecpkMessages: smsgs,
|
|
|
|
}, nil
|
2019-07-23 00:54:27 +00:00
|
|
|
}
|
|
|
|
|
2019-07-31 16:54:28 +00:00
|
|
|
func (a *FullNodeAPI) ChainCall(ctx context.Context, msg *types.Message, ts *types.TipSet) (*types.MessageReceipt, error) {
|
|
|
|
if ts == nil {
|
|
|
|
ts = a.Chain.GetHeaviestTipSet()
|
|
|
|
}
|
|
|
|
state, err := a.Chain.TipSetState(ts.Cids())
|
2019-07-30 00:46:56 +00:00
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
|
2019-07-31 16:54:28 +00:00
|
|
|
vmi, err := vm.NewVM(state, ts.Height(), ts.Blocks()[0].Miner, a.Chain)
|
2019-07-30 00:46:56 +00:00
|
|
|
if err != nil {
|
|
|
|
return nil, xerrors.Errorf("failed to set up vm: %w", err)
|
|
|
|
}
|
|
|
|
|
|
|
|
if msg.GasLimit == types.EmptyInt {
|
|
|
|
msg.GasLimit = types.NewInt(10000000000)
|
|
|
|
}
|
|
|
|
if msg.GasPrice == types.EmptyInt {
|
|
|
|
msg.GasPrice = types.NewInt(0)
|
|
|
|
}
|
|
|
|
if msg.Value == types.EmptyInt {
|
|
|
|
msg.Value = types.NewInt(0)
|
|
|
|
}
|
|
|
|
|
|
|
|
// TODO: maybe just use the invoker directly?
|
2019-08-03 11:26:35 +00:00
|
|
|
ret, err := vmi.ApplyMessage(ctx, msg)
|
|
|
|
return &ret.MessageReceipt, err
|
2019-07-30 00:46:56 +00:00
|
|
|
}
|
|
|
|
|
2019-07-26 04:54:22 +00:00
|
|
|
func (a *FullNodeAPI) MpoolPending(ctx context.Context, ts *types.TipSet) ([]*types.SignedMessage, error) {
|
2019-07-11 02:36:43 +00:00
|
|
|
// 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-25 22:15:03 +00:00
|
|
|
func (a *FullNodeAPI) MpoolPush(ctx context.Context, smsg *types.SignedMessage) error {
|
2019-07-17 03:05:55 +00:00
|
|
|
msgb, err := smsg.Serialize()
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
2019-07-28 05:35:32 +00:00
|
|
|
if err := a.Mpool.Add(smsg); err != nil {
|
|
|
|
return err
|
|
|
|
}
|
2019-07-17 03:05:55 +00:00
|
|
|
|
|
|
|
return a.PubSub.Publish("/fil/messages", msgb)
|
|
|
|
}
|
|
|
|
|
2019-07-24 00:40:19 +00:00
|
|
|
func (a *FullNodeAPI) MpoolGetNonce(ctx context.Context, addr address.Address) (uint64, error) {
|
2019-07-17 03:05:55 +00:00
|
|
|
return a.Mpool.GetNonce(addr)
|
|
|
|
}
|
|
|
|
|
2019-07-24 00:40:19 +00:00
|
|
|
func (a *FullNodeAPI) MinerStart(ctx context.Context, addr address.Address) error {
|
2019-07-11 02:36:43 +00:00
|
|
|
// hrm...
|
|
|
|
m := miner.NewMiner(a, addr)
|
|
|
|
|
|
|
|
go m.Mine(context.TODO())
|
|
|
|
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
2019-07-26 04:54:22 +00:00
|
|
|
func (a *FullNodeAPI) MinerCreateBlock(ctx context.Context, addr address.Address, parents *types.TipSet, tickets []types.Ticket, proof types.ElectionProof, msgs []*types.SignedMessage) (*chain.BlockMsg, error) {
|
2019-07-25 22:15:33 +00:00
|
|
|
fblk, err := gen.MinerCreateBlock(ctx, a.Chain, addr, parents, tickets, proof, msgs)
|
2019-07-11 02:36:43 +00:00
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
|
|
|
|
var out chain.BlockMsg
|
|
|
|
out.Header = fblk.Header
|
2019-08-01 20:40:47 +00:00
|
|
|
for _, msg := range fblk.BlsMessages {
|
|
|
|
out.BlsMessages = append(out.BlsMessages, msg.Cid())
|
|
|
|
}
|
|
|
|
for _, msg := range fblk.SecpkMessages {
|
|
|
|
out.SecpkMessages = append(out.SecpkMessages, msg.Cid())
|
2019-07-11 02:36:43 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
return &out, nil
|
|
|
|
}
|
|
|
|
|
2019-07-24 00:40:19 +00:00
|
|
|
func (a *FullNodeAPI) WalletNew(ctx context.Context, typ string) (address.Address, error) {
|
2019-07-13 00:41:32 +00:00
|
|
|
return a.Wallet.GenerateKey(typ)
|
|
|
|
}
|
|
|
|
|
2019-07-24 00:40:19 +00:00
|
|
|
func (a *FullNodeAPI) 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-24 00:40:19 +00:00
|
|
|
func (a *FullNodeAPI) WalletBalance(ctx context.Context, addr address.Address) (types.BigInt, error) {
|
2019-07-18 20:26:04 +00:00
|
|
|
return a.Chain.GetBalance(addr)
|
|
|
|
}
|
|
|
|
|
2019-07-24 05:38:16 +00:00
|
|
|
func (a *FullNodeAPI) WalletSign(ctx context.Context, k address.Address, msg []byte) (*types.Signature, error) {
|
2019-07-17 03:05:55 +00:00
|
|
|
return a.Wallet.Sign(k, msg)
|
|
|
|
}
|
|
|
|
|
2019-07-24 00:40:19 +00:00
|
|
|
func (a *FullNodeAPI) 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-25 23:26:40 +00:00
|
|
|
if len(addrs) == 0 {
|
|
|
|
return address.Undef, xerrors.New("no addresses in wallet")
|
|
|
|
}
|
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-24 00:40:19 +00:00
|
|
|
var _ api.FullNode = &FullNodeAPI{}
|