2019-08-20 16:48:33 +00:00
|
|
|
package full
|
|
|
|
|
|
|
|
import (
|
|
|
|
"context"
|
2020-09-05 13:17:55 +00:00
|
|
|
"encoding/json"
|
2022-08-16 19:39:06 +00:00
|
|
|
|
2022-09-13 20:52:47 +00:00
|
|
|
"github.com/google/uuid"
|
2022-08-16 19:56:32 +00:00
|
|
|
"github.com/ipfs/go-cid"
|
2019-08-20 16:48:33 +00:00
|
|
|
"go.uber.org/fx"
|
2019-09-16 14:17:08 +00:00
|
|
|
"golang.org/x/xerrors"
|
2019-08-20 16:48:33 +00:00
|
|
|
|
2022-08-16 19:56:32 +00:00
|
|
|
"github.com/filecoin-project/go-address"
|
2022-07-07 20:06:51 +00:00
|
|
|
"github.com/filecoin-project/go-state-types/big"
|
2022-06-14 15:00:51 +00:00
|
|
|
|
2019-11-17 07:44:06 +00:00
|
|
|
"github.com/filecoin-project/lotus/api"
|
2020-10-01 15:54:28 +00:00
|
|
|
"github.com/filecoin-project/lotus/chain/messagepool"
|
|
|
|
"github.com/filecoin-project/lotus/chain/messagesigner"
|
2019-10-18 04:47:41 +00:00
|
|
|
"github.com/filecoin-project/lotus/chain/types"
|
2020-10-01 15:54:28 +00:00
|
|
|
"github.com/filecoin-project/lotus/node/modules/dtypes"
|
2019-08-20 16:48:33 +00:00
|
|
|
)
|
|
|
|
|
2020-10-01 15:51:27 +00:00
|
|
|
type MpoolModuleAPI interface {
|
2020-09-30 15:59:18 +00:00
|
|
|
MpoolPush(ctx context.Context, smsg *types.SignedMessage) (cid.Cid, error)
|
|
|
|
}
|
|
|
|
|
2021-04-03 11:20:50 +00:00
|
|
|
var _ MpoolModuleAPI = *new(api.FullNode)
|
|
|
|
|
2020-10-01 15:51:27 +00:00
|
|
|
// MpoolModule provides a default implementation of MpoolModuleAPI.
|
|
|
|
// It can be swapped out with another implementation through Dependency
|
|
|
|
// Injection (for example with a thin RPC client).
|
|
|
|
type MpoolModule struct {
|
|
|
|
fx.In
|
|
|
|
|
|
|
|
Mpool *messagepool.MessagePool
|
|
|
|
}
|
|
|
|
|
|
|
|
var _ MpoolModuleAPI = (*MpoolModule)(nil)
|
|
|
|
|
2019-08-20 16:48:33 +00:00
|
|
|
type MpoolAPI struct {
|
|
|
|
fx.In
|
|
|
|
|
2020-10-01 15:51:27 +00:00
|
|
|
MpoolModuleAPI
|
|
|
|
|
2019-09-16 14:17:08 +00:00
|
|
|
WalletAPI
|
2020-07-20 17:48:30 +00:00
|
|
|
GasAPI
|
2019-09-16 14:17:08 +00:00
|
|
|
|
2022-09-08 18:20:05 +00:00
|
|
|
MessageSigner messagesigner.MsgSigner
|
2020-08-08 16:56:33 +00:00
|
|
|
|
2020-08-11 17:32:31 +00:00
|
|
|
PushLocks *dtypes.MpoolLocker
|
2019-08-20 16:48:33 +00:00
|
|
|
}
|
|
|
|
|
2020-08-07 14:45:31 +00:00
|
|
|
func (a *MpoolAPI) MpoolGetConfig(context.Context) (*types.MpoolConfig, error) {
|
|
|
|
return a.Mpool.GetConfig(), nil
|
|
|
|
}
|
|
|
|
|
|
|
|
func (a *MpoolAPI) MpoolSetConfig(ctx context.Context, cfg *types.MpoolConfig) error {
|
2021-12-11 21:03:00 +00:00
|
|
|
return a.Mpool.SetConfig(ctx, cfg)
|
2020-08-07 14:45:31 +00:00
|
|
|
}
|
|
|
|
|
2020-08-11 11:05:04 +00:00
|
|
|
func (a *MpoolAPI) MpoolSelect(ctx context.Context, tsk types.TipSetKey, ticketQuality float64) ([]*types.SignedMessage, error) {
|
2021-12-11 21:03:00 +00:00
|
|
|
ts, err := a.Chain.GetTipSetFromKey(ctx, tsk)
|
2020-08-05 20:17:14 +00:00
|
|
|
if err != nil {
|
|
|
|
return nil, xerrors.Errorf("loading tipset %s: %w", tsk, err)
|
|
|
|
}
|
|
|
|
|
2021-05-30 19:20:47 +00:00
|
|
|
return a.Mpool.SelectMessages(ctx, ts, ticketQuality)
|
2020-08-05 20:17:14 +00:00
|
|
|
}
|
|
|
|
|
2020-02-11 23:29:45 +00:00
|
|
|
func (a *MpoolAPI) MpoolPending(ctx context.Context, tsk types.TipSetKey) ([]*types.SignedMessage, error) {
|
2021-12-11 21:03:00 +00:00
|
|
|
ts, err := a.Chain.GetTipSetFromKey(ctx, tsk)
|
2020-02-11 23:29:45 +00:00
|
|
|
if err != nil {
|
|
|
|
return nil, xerrors.Errorf("loading tipset %s: %w", tsk, err)
|
|
|
|
}
|
2021-05-18 18:56:42 +00:00
|
|
|
pending, mpts := a.Mpool.Pending(ctx)
|
2019-12-03 19:33:29 +00:00
|
|
|
|
|
|
|
haveCids := map[cid.Cid]struct{}{}
|
|
|
|
for _, m := range pending {
|
|
|
|
haveCids[m.Cid()] = struct{}{}
|
|
|
|
}
|
|
|
|
|
2019-12-03 19:34:31 +00:00
|
|
|
if ts == nil || mpts.Height() > ts.Height() {
|
2019-12-03 19:33:29 +00:00
|
|
|
return pending, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
for {
|
|
|
|
if mpts.Height() == ts.Height() {
|
|
|
|
if mpts.Equals(ts) {
|
|
|
|
return pending, nil
|
|
|
|
}
|
|
|
|
|
2021-07-29 18:58:59 +00:00
|
|
|
// different blocks in tipsets of the same height
|
|
|
|
// we exclude messages that have been included in blocks in the mpool tipset
|
2021-12-17 09:42:09 +00:00
|
|
|
have, err := a.Mpool.MessagesForBlocks(ctx, mpts.Blocks())
|
2019-12-03 19:33:29 +00:00
|
|
|
if err != nil {
|
|
|
|
return nil, xerrors.Errorf("getting messages for base ts: %w", err)
|
|
|
|
}
|
|
|
|
|
|
|
|
for _, m := range have {
|
|
|
|
haveCids[m.Cid()] = struct{}{}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-12-17 09:42:09 +00:00
|
|
|
msgs, err := a.Mpool.MessagesForBlocks(ctx, ts.Blocks())
|
2019-12-03 19:33:29 +00:00
|
|
|
if err != nil {
|
|
|
|
return nil, xerrors.Errorf(": %w", err)
|
|
|
|
}
|
|
|
|
|
|
|
|
for _, m := range msgs {
|
|
|
|
if _, ok := haveCids[m.Cid()]; ok {
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
|
|
|
|
haveCids[m.Cid()] = struct{}{}
|
|
|
|
pending = append(pending, m)
|
|
|
|
}
|
|
|
|
|
|
|
|
if mpts.Height() >= ts.Height() {
|
|
|
|
return pending, nil
|
|
|
|
}
|
|
|
|
|
2021-12-11 21:03:00 +00:00
|
|
|
ts, err = a.Chain.LoadTipSet(ctx, ts.Parents())
|
2019-12-03 19:33:29 +00:00
|
|
|
if err != nil {
|
|
|
|
return nil, xerrors.Errorf("loading parent tipset: %w", err)
|
|
|
|
}
|
|
|
|
}
|
2019-08-20 16:48:33 +00:00
|
|
|
}
|
|
|
|
|
2020-08-21 20:24:53 +00:00
|
|
|
func (a *MpoolAPI) MpoolClear(ctx context.Context, local bool) error {
|
2021-05-29 00:35:50 +00:00
|
|
|
a.Mpool.Clear(ctx, local)
|
2020-08-21 17:28:45 +00:00
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
2020-10-01 15:51:27 +00:00
|
|
|
func (m *MpoolModule) MpoolPush(ctx context.Context, smsg *types.SignedMessage) (cid.Cid, error) {
|
2022-10-04 16:49:09 +00:00
|
|
|
return m.Mpool.Push(ctx, smsg, true)
|
2019-09-16 14:17:08 +00:00
|
|
|
}
|
|
|
|
|
2020-09-18 06:40:43 +00:00
|
|
|
func (a *MpoolAPI) MpoolPushUntrusted(ctx context.Context, smsg *types.SignedMessage) (cid.Cid, error) {
|
2021-05-18 18:56:42 +00:00
|
|
|
return a.Mpool.PushUntrusted(ctx, smsg)
|
2020-09-18 06:40:43 +00:00
|
|
|
}
|
|
|
|
|
2020-08-12 20:17:21 +00:00
|
|
|
func (a *MpoolAPI) MpoolPushMessage(ctx context.Context, msg *types.Message, spec *api.MessageSendSpec) (*types.SignedMessage, error) {
|
2020-09-23 16:28:11 +00:00
|
|
|
cp := *msg
|
|
|
|
msg = &cp
|
2020-09-05 13:17:55 +00:00
|
|
|
inMsg := *msg
|
2022-08-16 19:39:06 +00:00
|
|
|
|
2022-10-18 19:53:42 +00:00
|
|
|
// Generate spec and uuid if not available in the message
|
|
|
|
if spec == nil {
|
|
|
|
spec = &api.MessageSendSpec{
|
|
|
|
MsgUuid: uuid.New(),
|
|
|
|
}
|
|
|
|
} else if (spec.MsgUuid == uuid.UUID{}) {
|
|
|
|
spec.MsgUuid = uuid.New()
|
|
|
|
} else {
|
|
|
|
// Check if this uuid has already been processed. Ignore if uuid is not populated
|
2022-08-16 19:39:06 +00:00
|
|
|
signedMessage, err := a.MessageSigner.GetSignedMessage(ctx, spec.MsgUuid)
|
|
|
|
if err == nil {
|
|
|
|
log.Warnf("Message already processed. cid=%s", signedMessage.Cid())
|
|
|
|
return signedMessage, nil
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-01-13 19:11:13 +00:00
|
|
|
fromA, err := a.Stmgr.ResolveToDeterministicAddress(ctx, msg.From, nil)
|
2020-09-23 16:28:11 +00:00
|
|
|
if err != nil {
|
|
|
|
return nil, xerrors.Errorf("getting key address: %w", err)
|
|
|
|
}
|
2020-08-08 16:56:33 +00:00
|
|
|
{
|
2020-08-11 17:32:31 +00:00
|
|
|
done, err := a.PushLocks.TakeLock(ctx, fromA)
|
|
|
|
if err != nil {
|
|
|
|
return nil, xerrors.Errorf("taking lock: %w", err)
|
2020-08-08 20:51:24 +00:00
|
|
|
}
|
2020-08-11 17:32:31 +00:00
|
|
|
defer done()
|
2020-08-08 16:56:33 +00:00
|
|
|
}
|
|
|
|
|
2019-09-16 14:17:08 +00:00
|
|
|
if msg.Nonce != 0 {
|
2019-09-17 08:15:26 +00:00
|
|
|
return nil, xerrors.Errorf("MpoolPushMessage expects message nonce to be 0, was %d", msg.Nonce)
|
2019-08-20 16:48:33 +00:00
|
|
|
}
|
2020-07-20 19:50:03 +00:00
|
|
|
|
2020-09-23 16:28:11 +00:00
|
|
|
msg, err = a.GasAPI.GasEstimateMessageGas(ctx, msg, spec, types.EmptyTSK)
|
2020-08-19 21:25:58 +00:00
|
|
|
if err != nil {
|
|
|
|
return nil, xerrors.Errorf("GasEstimateMessageGas error: %w", err)
|
2020-08-06 19:14:08 +00:00
|
|
|
}
|
2019-08-20 16:48:33 +00:00
|
|
|
|
2020-09-05 13:17:55 +00:00
|
|
|
if msg.GasPremium.GreaterThan(msg.GasFeeCap) {
|
|
|
|
inJson, _ := json.Marshal(inMsg)
|
|
|
|
outJson, _ := json.Marshal(msg)
|
|
|
|
return nil, xerrors.Errorf("After estimation, GasPremium is greater than GasFeeCap, inmsg: %s, outmsg: %s",
|
|
|
|
inJson, outJson)
|
|
|
|
}
|
|
|
|
|
2020-09-23 16:28:11 +00:00
|
|
|
if msg.From.Protocol() == address.ID {
|
|
|
|
log.Warnf("Push from ID address (%s), adjusting to %s", msg.From, fromA)
|
|
|
|
msg.From = fromA
|
|
|
|
}
|
2019-10-06 01:34:45 +00:00
|
|
|
|
2020-09-23 16:28:11 +00:00
|
|
|
b, err := a.WalletBalance(ctx, msg.From)
|
|
|
|
if err != nil {
|
|
|
|
return nil, xerrors.Errorf("mpool push: getting origin balance: %w", err)
|
|
|
|
}
|
2019-10-06 01:34:45 +00:00
|
|
|
|
2022-07-07 20:06:51 +00:00
|
|
|
requiredFunds := big.Add(msg.Value, msg.RequiredFunds())
|
|
|
|
if b.LessThan(requiredFunds) {
|
|
|
|
return nil, xerrors.Errorf("mpool push: not enough funds: %s < %s", b, requiredFunds)
|
2020-09-23 16:28:11 +00:00
|
|
|
}
|
2019-10-06 01:34:45 +00:00
|
|
|
|
2020-10-05 12:17:40 +00:00
|
|
|
// Sign and push the message
|
2022-09-08 18:20:05 +00:00
|
|
|
signedMsg, err := a.MessageSigner.SignMessage(ctx, msg, spec, func(smsg *types.SignedMessage) error {
|
2020-10-07 09:26:15 +00:00
|
|
|
if _, err := a.MpoolModuleAPI.MpoolPush(ctx, smsg); err != nil {
|
2020-10-05 12:17:40 +00:00
|
|
|
return xerrors.Errorf("mpool push: failed to push message: %w", err)
|
|
|
|
}
|
|
|
|
return nil
|
|
|
|
})
|
2022-08-16 19:39:06 +00:00
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
|
|
|
|
// Store uuid->signed message in datastore
|
2022-10-18 19:53:42 +00:00
|
|
|
err = a.MessageSigner.StoreSignedMessage(ctx, spec.MsgUuid, signedMsg)
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
2022-08-16 19:39:06 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
return signedMsg, nil
|
2019-08-20 16:48:33 +00:00
|
|
|
}
|
|
|
|
|
2020-10-08 02:04:43 +00:00
|
|
|
func (a *MpoolAPI) MpoolBatchPush(ctx context.Context, smsgs []*types.SignedMessage) ([]cid.Cid, error) {
|
|
|
|
var messageCids []cid.Cid
|
|
|
|
for _, smsg := range smsgs {
|
2022-10-04 16:49:09 +00:00
|
|
|
smsgCid, err := a.Mpool.Push(ctx, smsg, true)
|
2020-10-08 02:04:43 +00:00
|
|
|
if err != nil {
|
|
|
|
return messageCids, err
|
|
|
|
}
|
|
|
|
messageCids = append(messageCids, smsgCid)
|
|
|
|
}
|
|
|
|
return messageCids, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
func (a *MpoolAPI) MpoolBatchPushUntrusted(ctx context.Context, smsgs []*types.SignedMessage) ([]cid.Cid, error) {
|
|
|
|
var messageCids []cid.Cid
|
|
|
|
for _, smsg := range smsgs {
|
2021-05-18 18:56:42 +00:00
|
|
|
smsgCid, err := a.Mpool.PushUntrusted(ctx, smsg)
|
2020-10-08 02:04:43 +00:00
|
|
|
if err != nil {
|
|
|
|
return messageCids, err
|
|
|
|
}
|
|
|
|
messageCids = append(messageCids, smsgCid)
|
|
|
|
}
|
|
|
|
return messageCids, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
func (a *MpoolAPI) MpoolBatchPushMessage(ctx context.Context, msgs []*types.Message, spec *api.MessageSendSpec) ([]*types.SignedMessage, error) {
|
|
|
|
var smsgs []*types.SignedMessage
|
|
|
|
for _, msg := range msgs {
|
|
|
|
smsg, err := a.MpoolPushMessage(ctx, msg, spec)
|
|
|
|
if err != nil {
|
|
|
|
return smsgs, err
|
|
|
|
}
|
|
|
|
smsgs = append(smsgs, smsg)
|
|
|
|
}
|
|
|
|
return smsgs, nil
|
|
|
|
}
|
|
|
|
|
2021-04-02 14:12:34 +00:00
|
|
|
func (a *MpoolAPI) MpoolCheckMessages(ctx context.Context, protos []*api.MessagePrototype) ([][]api.MessageCheckStatus, error) {
|
2021-06-14 11:27:53 +00:00
|
|
|
return a.Mpool.CheckMessages(ctx, protos)
|
2021-03-12 15:10:12 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
func (a *MpoolAPI) MpoolCheckPendingMessages(ctx context.Context, from address.Address) ([][]api.MessageCheckStatus, error) {
|
2021-06-14 11:27:53 +00:00
|
|
|
return a.Mpool.CheckPendingMessages(ctx, from)
|
2021-03-12 15:10:12 +00:00
|
|
|
}
|
|
|
|
|
2021-03-23 14:55:38 +00:00
|
|
|
func (a *MpoolAPI) MpoolCheckReplaceMessages(ctx context.Context, msgs []*types.Message) ([][]api.MessageCheckStatus, error) {
|
2021-06-14 11:27:53 +00:00
|
|
|
return a.Mpool.CheckReplaceMessages(ctx, msgs)
|
2021-03-23 14:55:38 +00:00
|
|
|
}
|
|
|
|
|
2019-08-20 16:48:33 +00:00
|
|
|
func (a *MpoolAPI) MpoolGetNonce(ctx context.Context, addr address.Address) (uint64, error) {
|
2021-04-16 15:18:54 +00:00
|
|
|
return a.Mpool.GetNonce(ctx, addr, types.EmptyTSK)
|
2019-08-20 16:48:33 +00:00
|
|
|
}
|
2019-11-17 07:44:06 +00:00
|
|
|
|
|
|
|
func (a *MpoolAPI) MpoolSub(ctx context.Context) (<-chan api.MpoolUpdate, error) {
|
|
|
|
return a.Mpool.Updates(ctx)
|
|
|
|
}
|