fix: message signer - always compare with mpool nonce

This commit is contained in:
Dirk McCormick 2020-09-29 12:19:04 +02:00
parent 3c524ac0e0
commit d1c10a61dd
4 changed files with 30 additions and 25 deletions

View File

@ -4,21 +4,22 @@ import (
"bytes" "bytes"
"context" "context"
"github.com/filecoin-project/lotus/chain/wallet"
"github.com/filecoin-project/lotus/chain/messagepool"
"github.com/filecoin-project/go-address" "github.com/filecoin-project/go-address"
"github.com/filecoin-project/lotus/chain/messagepool"
"github.com/filecoin-project/lotus/chain/types" "github.com/filecoin-project/lotus/chain/types"
"github.com/filecoin-project/lotus/chain/wallet"
"github.com/filecoin-project/lotus/node/modules/dtypes" "github.com/filecoin-project/lotus/node/modules/dtypes"
"github.com/ipfs/go-datastore" "github.com/ipfs/go-datastore"
"github.com/ipfs/go-datastore/namespace" "github.com/ipfs/go-datastore/namespace"
logging "github.com/ipfs/go-log/v2"
cbg "github.com/whyrusleeping/cbor-gen" cbg "github.com/whyrusleeping/cbor-gen"
"golang.org/x/xerrors" "golang.org/x/xerrors"
) )
const dsKeyActorNonce = "ActorNonce" const dsKeyActorNonce = "ActorNonce"
var log = logging.Logger("messagesigner")
type mpoolAPI interface { type mpoolAPI interface {
GetNonce(address.Address) (uint64, error) GetNonce(address.Address) (uint64, error)
} }
@ -67,30 +68,30 @@ func (ms *MessageSigner) SignMessage(ctx context.Context, msg *types.Message) (*
// nextNonce increments the nonce. // nextNonce increments the nonce.
// If there is no nonce in the datastore, gets the nonce from the message pool. // If there is no nonce in the datastore, gets the nonce from the message pool.
func (ms *MessageSigner) nextNonce(addr address.Address) (uint64, error) { func (ms *MessageSigner) nextNonce(addr address.Address) (uint64, error) {
addrNonceKey := datastore.KeyWithNamespaces([]string{dsKeyActorNonce, addr.String()}) // Nonces used to be created by the mempool and we need to support nodes
// that have mempool nonces, so first check the mempool for a nonce for
// this address. Note that the mempool returns the actor state's nonce
// by default.
nonce, err := ms.mpool.GetNonce(addr)
if err != nil {
return 0, xerrors.Errorf("failed to get nonce from mempool: %w", err)
}
// Get the nonce for this address from the datastore // Get the nonce for this address from the datastore
nonceBytes, err := ms.ds.Get(addrNonceKey) addrNonceKey := datastore.KeyWithNamespaces([]string{dsKeyActorNonce, addr.String()})
dsNonceBytes, err := ms.ds.Get(addrNonceKey)
var nonce uint64
switch { switch {
case xerrors.Is(err, datastore.ErrNotFound): case xerrors.Is(err, datastore.ErrNotFound):
// If a nonce for this address hasn't yet been created in the // If a nonce for this address hasn't yet been created in the
// datastore, check the mempool - nonces used to be created by // datastore, just use the nonce from the mempool
// the mempool so we need to support nodes that still have mempool
// nonces. Note that the mempool returns the actor state's nonce by
// default.
nonce, err = ms.mpool.GetNonce(addr)
if err != nil {
return 0, xerrors.Errorf("failed to get nonce from mempool: %w", err)
}
case err != nil: case err != nil:
return 0, xerrors.Errorf("failed to get nonce from datastore: %w", err) return 0, xerrors.Errorf("failed to get nonce from datastore: %w", err)
default: default:
// There is a nonce in the mempool, so unmarshall and increment it // There is a nonce in the datastore, so unmarshall and increment it
maj, val, err := cbg.CborReadHeader(bytes.NewReader(nonceBytes)) maj, val, err := cbg.CborReadHeader(bytes.NewReader(dsNonceBytes))
if err != nil { if err != nil {
return 0, xerrors.Errorf("failed to parse nonce from datastore: %w", err) return 0, xerrors.Errorf("failed to parse nonce from datastore: %w", err)
} }
@ -98,7 +99,14 @@ func (ms *MessageSigner) nextNonce(addr address.Address) (uint64, error) {
return 0, xerrors.Errorf("bad cbor type parsing nonce from datastore") return 0, xerrors.Errorf("bad cbor type parsing nonce from datastore")
} }
nonce = val + 1 dsNonce := val + 1
// The message pool nonce should be <= than the datastore nonce
if nonce <= dsNonce {
nonce = dsNonce
} else {
log.Warnf("mempool nonce was larger than datastore nonce (%d > %d)", nonce, dsNonce)
}
} }
// Write the nonce for this address to the datastore // Write the nonce for this address to the datastore

View File

@ -98,10 +98,9 @@ func TestMessageSignerSignMessage(t *testing.T) {
To: to1, To: to1,
From: from1, From: from1,
}, },
// Should ignore mpool nonce because after the first message nonce // Should adjust datastore nonce because mpool nonce is higher
// will come from the datastore
mpoolNonce: [1]uint64{10}, mpoolNonce: [1]uint64{10},
expNonce: 6, expNonce: 10,
}}, }},
}, { }, {
// Nonce should increment independently for each address // Nonce should increment independently for each address

View File

@ -6,8 +6,6 @@ import (
"os" "os"
"time" "time"
"github.com/filecoin-project/lotus/chain/messagesigner"
logging "github.com/ipfs/go-log" logging "github.com/ipfs/go-log"
ci "github.com/libp2p/go-libp2p-core/crypto" ci "github.com/libp2p/go-libp2p-core/crypto"
"github.com/libp2p/go-libp2p-core/host" "github.com/libp2p/go-libp2p-core/host"
@ -37,6 +35,7 @@ import (
"github.com/filecoin-project/lotus/chain/gen/slashfilter" "github.com/filecoin-project/lotus/chain/gen/slashfilter"
"github.com/filecoin-project/lotus/chain/market" "github.com/filecoin-project/lotus/chain/market"
"github.com/filecoin-project/lotus/chain/messagepool" "github.com/filecoin-project/lotus/chain/messagepool"
"github.com/filecoin-project/lotus/chain/messagesigner"
"github.com/filecoin-project/lotus/chain/metrics" "github.com/filecoin-project/lotus/chain/metrics"
"github.com/filecoin-project/lotus/chain/stmgr" "github.com/filecoin-project/lotus/chain/stmgr"
"github.com/filecoin-project/lotus/chain/store" "github.com/filecoin-project/lotus/chain/store"

View File

@ -4,14 +4,13 @@ import (
"context" "context"
"encoding/json" "encoding/json"
"github.com/filecoin-project/lotus/chain/messagesigner"
"github.com/filecoin-project/go-address" "github.com/filecoin-project/go-address"
"github.com/ipfs/go-cid" "github.com/ipfs/go-cid"
"go.uber.org/fx" "go.uber.org/fx"
"golang.org/x/xerrors" "golang.org/x/xerrors"
"github.com/filecoin-project/lotus/api" "github.com/filecoin-project/lotus/api"
"github.com/filecoin-project/lotus/chain/messagesigner"
"github.com/filecoin-project/lotus/chain/types" "github.com/filecoin-project/lotus/chain/types"
"github.com/filecoin-project/lotus/node/modules/dtypes" "github.com/filecoin-project/lotus/node/modules/dtypes"
) )