Fix nonce getting on Lotus lite
Resolves #5593 #5995 Signed-off-by: Jakub Sztandera <kubuxu@protocol.ai>
This commit is contained in:
parent
50b4ea3083
commit
77d004ec06
@ -23,7 +23,7 @@ const dsKeyActorNonce = "ActorNextNonce"
|
|||||||
var log = logging.Logger("messagesigner")
|
var log = logging.Logger("messagesigner")
|
||||||
|
|
||||||
type MpoolNonceAPI interface {
|
type MpoolNonceAPI interface {
|
||||||
GetNonce(address.Address) (uint64, error)
|
GetNonce(context.Context, address.Address, types.TipSetKey) (uint64, error)
|
||||||
}
|
}
|
||||||
|
|
||||||
// MessageSigner keeps track of nonces per address, and increments the nonce
|
// MessageSigner keeps track of nonces per address, and increments the nonce
|
||||||
@ -97,7 +97,7 @@ func (ms *MessageSigner) nextNonce(addr address.Address) (uint64, error) {
|
|||||||
// that have mempool nonces, so first check the mempool for a nonce for
|
// 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
|
// this address. Note that the mempool returns the actor state's nonce
|
||||||
// by default.
|
// by default.
|
||||||
nonce, err := ms.mpool.GetNonce(addr)
|
nonce, err := ms.mpool.GetNonce(context.TODO(), addr, types.EmptyTSK)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return 0, xerrors.Errorf("failed to get nonce from mempool: %w", err)
|
return 0, xerrors.Errorf("failed to get nonce from mempool: %w", err)
|
||||||
}
|
}
|
||||||
|
@ -35,7 +35,7 @@ func (mp *mockMpool) setNonce(addr address.Address, nonce uint64) {
|
|||||||
mp.nonces[addr] = nonce
|
mp.nonces[addr] = nonce
|
||||||
}
|
}
|
||||||
|
|
||||||
func (mp *mockMpool) GetNonce(addr address.Address) (uint64, error) {
|
func (mp *mockMpool) GetNonce(_ context.Context, addr address.Address, _ types.TipSetKey) (uint64, error) {
|
||||||
mp.lk.RLock()
|
mp.lk.RLock()
|
||||||
defer mp.lk.RUnlock()
|
defer mp.lk.RUnlock()
|
||||||
|
|
||||||
|
@ -2,6 +2,7 @@ package modules
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
"strings"
|
||||||
|
|
||||||
"go.uber.org/fx"
|
"go.uber.org/fx"
|
||||||
"golang.org/x/xerrors"
|
"golang.org/x/xerrors"
|
||||||
@ -19,41 +20,77 @@ import (
|
|||||||
type MpoolNonceAPI struct {
|
type MpoolNonceAPI struct {
|
||||||
fx.In
|
fx.In
|
||||||
|
|
||||||
StateAPI full.StateAPI
|
ChainModule full.ChainModuleAPI
|
||||||
|
StateModule full.StateModuleAPI
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetNonce gets the nonce from current chain head.
|
// GetNonce gets the nonce from current chain head.
|
||||||
func (a *MpoolNonceAPI) GetNonce(addr address.Address) (uint64, error) {
|
func (a *MpoolNonceAPI) GetNonce(ctx context.Context, addr address.Address, tsk types.TipSetKey) (uint64, error) {
|
||||||
ts := a.StateAPI.Chain.GetHeaviestTipSet()
|
var err error
|
||||||
|
var ts *types.TipSet
|
||||||
// make sure we have a key address so we can compare with messages
|
if tsk == types.EmptyTSK {
|
||||||
keyAddr, err := a.StateAPI.StateManager.ResolveToKeyAddress(context.TODO(), addr, ts)
|
// we need consistent tsk
|
||||||
|
ts, err = a.ChainModule.ChainHead(ctx)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return 0, err
|
return 0, xerrors.Errorf("getting head: %w", err)
|
||||||
|
}
|
||||||
|
tsk = ts.Key()
|
||||||
|
} else {
|
||||||
|
ts, err = a.ChainModule.ChainGetTipSet(ctx, tsk)
|
||||||
|
if err != nil {
|
||||||
|
return 0, xerrors.Errorf("getting tipset: %w", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
keyAddr := addr
|
||||||
|
|
||||||
|
if addr.Protocol() == address.ID {
|
||||||
|
// make sure we have a key address so we can compare with messages
|
||||||
|
keyAddr, err = a.StateModule.StateAccountKey(ctx, addr, tsk)
|
||||||
|
if err != nil {
|
||||||
|
return 0, xerrors.Errorf("getting account key: %w", err)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
addr, err = a.StateModule.StateLookupID(ctx, addr, types.EmptyTSK)
|
||||||
|
if err != nil {
|
||||||
|
log.Infof("failed to look up id addr for %s: %w", addr, err)
|
||||||
|
addr = address.Undef
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Load the last nonce from the state, if it exists.
|
// Load the last nonce from the state, if it exists.
|
||||||
highestNonce := uint64(0)
|
highestNonce := uint64(0)
|
||||||
if baseActor, err := a.StateAPI.StateManager.LoadActorRaw(context.TODO(), addr, ts.ParentState()); err != nil {
|
act, err := a.StateModule.StateGetActor(ctx, keyAddr, ts.Key())
|
||||||
if !xerrors.Is(err, types.ErrActorNotFound) {
|
if err != nil {
|
||||||
return 0, err
|
if strings.Contains(err.Error(), types.ErrActorNotFound.Error()) {
|
||||||
|
return 0, types.ErrActorNotFound
|
||||||
|
}
|
||||||
|
return 0, xerrors.Errorf("getting actor: %w", err)
|
||||||
|
}
|
||||||
|
highestNonce = act.Nonce
|
||||||
|
|
||||||
|
apply := func(msg *types.Message) {
|
||||||
|
if msg.From != addr && msg.From != keyAddr {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if msg.Nonce == highestNonce {
|
||||||
|
highestNonce = msg.Nonce + 1
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
highestNonce = baseActor.Nonce
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Otherwise, find the highest nonce in the tipset.
|
for _, b := range ts.Blocks() {
|
||||||
msgs, err := a.StateAPI.Chain.MessagesForTipset(ts)
|
msgs, err := a.ChainModule.ChainGetBlockMessages(ctx, b.Cid())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return 0, err
|
return 0, xerrors.Errorf("getting block messages: %w", err)
|
||||||
}
|
}
|
||||||
for _, msg := range msgs {
|
if keyAddr.Protocol() == address.BLS {
|
||||||
vmmsg := msg.VMMessage()
|
for _, m := range msgs.BlsMessages {
|
||||||
if vmmsg.From != keyAddr {
|
apply(m)
|
||||||
continue
|
}
|
||||||
|
} else {
|
||||||
|
for _, sm := range msgs.SecpkMessages {
|
||||||
|
apply(&sm.Message)
|
||||||
}
|
}
|
||||||
if vmmsg.Nonce >= highestNonce {
|
|
||||||
highestNonce = vmmsg.Nonce + 1
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return highestNonce, nil
|
return highestNonce, nil
|
||||||
|
Loading…
Reference in New Issue
Block a user