fix miner message filter nonce checking
This commit is contained in:
parent
8e09fd6ca8
commit
9ad4a00cda
@ -29,6 +29,7 @@ type FullNode interface {
|
|||||||
ChainGetBlockMessages(context.Context, cid.Cid) (*BlockMessages, error)
|
ChainGetBlockMessages(context.Context, cid.Cid) (*BlockMessages, error)
|
||||||
ChainGetParentReceipts(context.Context, cid.Cid) ([]*types.MessageReceipt, error)
|
ChainGetParentReceipts(context.Context, cid.Cid) ([]*types.MessageReceipt, error)
|
||||||
ChainGetParentMessages(context.Context, cid.Cid) ([]Message, error)
|
ChainGetParentMessages(context.Context, cid.Cid) ([]Message, error)
|
||||||
|
ChainGetTipSetMessages(context.Context, types.TipSetKey) ([]Message, error)
|
||||||
ChainGetTipSetByHeight(context.Context, uint64, *types.TipSet) (*types.TipSet, error)
|
ChainGetTipSetByHeight(context.Context, uint64, *types.TipSet) (*types.TipSet, error)
|
||||||
ChainReadObj(context.Context, cid.Cid) ([]byte, error)
|
ChainReadObj(context.Context, cid.Cid) ([]byte, error)
|
||||||
ChainSetHead(context.Context, *types.TipSet) error
|
ChainSetHead(context.Context, *types.TipSet) error
|
||||||
|
@ -45,6 +45,7 @@ type FullNodeStruct struct {
|
|||||||
ChainGetBlockMessages func(context.Context, cid.Cid) (*BlockMessages, error) `perm:"read"`
|
ChainGetBlockMessages func(context.Context, cid.Cid) (*BlockMessages, error) `perm:"read"`
|
||||||
ChainGetParentReceipts func(context.Context, cid.Cid) ([]*types.MessageReceipt, error) `perm:"read"`
|
ChainGetParentReceipts func(context.Context, cid.Cid) ([]*types.MessageReceipt, error) `perm:"read"`
|
||||||
ChainGetParentMessages func(context.Context, cid.Cid) ([]Message, error) `perm:"read"`
|
ChainGetParentMessages func(context.Context, cid.Cid) ([]Message, error) `perm:"read"`
|
||||||
|
ChainGetTipSetMessages func(context.Context, types.TipSetKey) ([]Message, error) `perm:"read"`
|
||||||
ChainGetTipSetByHeight func(context.Context, uint64, *types.TipSet) (*types.TipSet, error) `perm:"read"`
|
ChainGetTipSetByHeight func(context.Context, uint64, *types.TipSet) (*types.TipSet, error) `perm:"read"`
|
||||||
ChainReadObj func(context.Context, cid.Cid) ([]byte, error) `perm:"read"`
|
ChainReadObj func(context.Context, cid.Cid) ([]byte, error) `perm:"read"`
|
||||||
ChainSetHead func(context.Context, *types.TipSet) error `perm:"admin"`
|
ChainSetHead func(context.Context, *types.TipSet) error `perm:"admin"`
|
||||||
@ -310,6 +311,10 @@ func (c *FullNodeStruct) ChainGetParentMessages(ctx context.Context, b cid.Cid)
|
|||||||
return c.Internal.ChainGetParentMessages(ctx, b)
|
return c.Internal.ChainGetParentMessages(ctx, b)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (c *FullNodeStruct) ChainGetTipSetMessages(ctx context.Context, tsk types.TipSetKey) ([]Message, error) {
|
||||||
|
return c.Internal.ChainGetTipSetMessages(ctx, tsk)
|
||||||
|
}
|
||||||
|
|
||||||
func (c *FullNodeStruct) ChainNotify(ctx context.Context) (<-chan []*store.HeadChange, error) {
|
func (c *FullNodeStruct) ChainNotify(ctx context.Context) (<-chan []*store.HeadChange, error) {
|
||||||
return c.Internal.ChainNotify(ctx)
|
return c.Internal.ChainNotify(ctx)
|
||||||
}
|
}
|
||||||
|
@ -334,14 +334,40 @@ func (m *Miner) computeTicket(ctx context.Context, addr address.Address, base *M
|
|||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *Miner) createBlock(base *MiningBase, addr address.Address, ticket *types.Ticket, proof *types.EPostProof) (*types.BlockMsg, error) {
|
func (m *Miner) actorLookup(ctx context.Context, addr address.Address, ts *types.TipSet) (uint64, *types.BigInt, error) {
|
||||||
|
// TODO: strong opportunities for some caching in this method
|
||||||
|
act, err := m.api.StateGetActor(ctx, addr, ts)
|
||||||
|
if err != nil {
|
||||||
|
return 0, nil, xerrors.Errorf("looking up actor failed: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
msgs, err := m.api.ChainGetTipSetMessages(ctx, ts.Key())
|
||||||
|
if err != nil {
|
||||||
|
return 0, nil, xerrors.Errorf("failed to get tipset messages: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
balance := act.Balance
|
||||||
|
curnonce := act.Nonce
|
||||||
|
for _, m := range msgs {
|
||||||
|
if m.Message.From == addr {
|
||||||
|
if m.Message.Nonce != curnonce {
|
||||||
|
return 0, nil, xerrors.Errorf("tipset messages had bad nonce: %s had nonce %d, expected %d", m.Cid, m.Message.Nonce, curnonce)
|
||||||
|
}
|
||||||
|
curnonce++
|
||||||
|
balance = types.BigSub(balance, m.Message.RequiredFunds())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return curnonce, &balance, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *Miner) createBlock(base *MiningBase, addr address.Address, ticket *types.Ticket, proof *types.EPostProof) (*types.BlockMsg, error) {
|
||||||
pending, err := m.api.MpoolPending(context.TODO(), base.ts)
|
pending, err := m.api.MpoolPending(context.TODO(), base.ts)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, xerrors.Errorf("failed to get pending messages: %w", err)
|
return nil, xerrors.Errorf("failed to get pending messages: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
msgs, err := selectMessages(context.TODO(), m.api.StateGetActor, base, pending)
|
msgs, err := selectMessages(context.TODO(), m.actorLookup, base, pending)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, xerrors.Errorf("message filtering failed: %w", err)
|
return nil, xerrors.Errorf("message filtering failed: %w", err)
|
||||||
}
|
}
|
||||||
@ -354,7 +380,7 @@ func (m *Miner) createBlock(base *MiningBase, addr address.Address, ticket *type
|
|||||||
return m.api.MinerCreateBlock(context.TODO(), addr, base.ts, ticket, proof, msgs, nheight, uint64(uts))
|
return m.api.MinerCreateBlock(context.TODO(), addr, base.ts, ticket, proof, msgs, nheight, uint64(uts))
|
||||||
}
|
}
|
||||||
|
|
||||||
type actorLookup func(context.Context, address.Address, *types.TipSet) (*types.Actor, error)
|
type actorLookup func(context.Context, address.Address, *types.TipSet) (uint64, *types.BigInt, error)
|
||||||
|
|
||||||
func selectMessages(ctx context.Context, al actorLookup, base *MiningBase, msgs []*types.SignedMessage) ([]*types.SignedMessage, error) {
|
func selectMessages(ctx context.Context, al actorLookup, base *MiningBase, msgs []*types.SignedMessage) ([]*types.SignedMessage, error) {
|
||||||
out := make([]*types.SignedMessage, 0, len(msgs))
|
out := make([]*types.SignedMessage, 0, len(msgs))
|
||||||
@ -367,14 +393,15 @@ func selectMessages(ctx context.Context, al actorLookup, base *MiningBase, msgs
|
|||||||
}
|
}
|
||||||
|
|
||||||
from := msg.Message.From
|
from := msg.Message.From
|
||||||
act, err := al(ctx, from, base.ts)
|
|
||||||
|
if _, ok := inclNonces[from]; !ok {
|
||||||
|
nonce, balance, err := al(ctx, from, base.ts)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, xerrors.Errorf("failed to check message sender balance: %w", err)
|
return nil, xerrors.Errorf("failed to check message sender balance: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if _, ok := inclNonces[from]; !ok {
|
inclNonces[from] = nonce
|
||||||
inclNonces[from] = act.Nonce
|
inclBalances[from] = *balance
|
||||||
inclBalances[from] = act.Balance
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if inclBalances[from].LessThan(msg.Message.RequiredFunds()) {
|
if inclBalances[from].LessThan(msg.Message.RequiredFunds()) {
|
||||||
|
@ -33,8 +33,8 @@ func TestMessageFiltering(t *testing.T) {
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
af := func(ctx context.Context, addr address.Address, ts *types.TipSet) (*types.Actor, error) {
|
af := func(ctx context.Context, addr address.Address, ts *types.TipSet) (uint64, *types.BigInt, error) {
|
||||||
return actors[addr], nil
|
return actors[addr].Nonce, &actors[addr].Balance, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
msgs := []types.Message{
|
msgs := []types.Message{
|
||||||
|
@ -68,6 +68,7 @@ func (a *ChainAPI) ChainGetBlockMessages(ctx context.Context, msg cid.Cid) (*api
|
|||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO: Maybe deprecate in favor of just using ChainGetTipSetMessages?
|
||||||
func (a *ChainAPI) ChainGetParentMessages(ctx context.Context, bcid cid.Cid) ([]api.Message, error) {
|
func (a *ChainAPI) ChainGetParentMessages(ctx context.Context, bcid cid.Cid) ([]api.Message, error) {
|
||||||
b, err := a.Chain.GetBlock(bcid)
|
b, err := a.Chain.GetBlock(bcid)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -101,6 +102,28 @@ func (a *ChainAPI) ChainGetParentMessages(ctx context.Context, bcid cid.Cid) ([]
|
|||||||
return out, nil
|
return out, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (a *ChainAPI) ChainGetTipSetMessages(ctx context.Context, tsk types.TipSetKey) ([]api.Message, error) {
|
||||||
|
ts, err := a.Chain.LoadTipSet(tsk.Cids())
|
||||||
|
if err != nil {
|
||||||
|
return nil, xerrors.Errorf("failed to load tipset from key: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
messages, err := a.Chain.MessagesForTipset(ts)
|
||||||
|
if err != nil {
|
||||||
|
return nil, xerrors.Errorf("getting messages for tipset: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
var out []api.Message
|
||||||
|
for _, m := range messages {
|
||||||
|
out = append(out, api.Message{
|
||||||
|
Cid: m.Cid(),
|
||||||
|
Message: m.VMMessage(),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
return out, nil
|
||||||
|
}
|
||||||
|
|
||||||
func (a *ChainAPI) ChainGetParentReceipts(ctx context.Context, bcid cid.Cid) ([]*types.MessageReceipt, error) {
|
func (a *ChainAPI) ChainGetParentReceipts(ctx context.Context, bcid cid.Cid) ([]*types.MessageReceipt, error) {
|
||||||
b, err := a.Chain.GetBlock(bcid)
|
b, err := a.Chain.GetBlock(bcid)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
Loading…
Reference in New Issue
Block a user