-
Notifications
You must be signed in to change notification settings - Fork 1.3k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Make state tipset usage consistent in the API #4545
Changes from all commits
b8e3808
e164dbb
a47b063
b78b9a4
56a9d05
feb24c9
52bfed1
8f60371
2c772d6
33c1283
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -146,7 +146,7 @@ Perms: admin | |
|
||
Inputs: `null` | ||
|
||
Response: `65536` | ||
Response: `65792` | ||
|
||
## Add | ||
|
||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -21,7 +21,6 @@ import ( | |
"github.com/filecoin-project/lotus/api" | ||
"github.com/filecoin-project/lotus/build" | ||
"github.com/filecoin-project/lotus/chain/gen" | ||
"github.com/filecoin-project/lotus/chain/messagepool/gasguess" | ||
"github.com/filecoin-project/lotus/chain/store" | ||
"github.com/filecoin-project/lotus/chain/types" | ||
"github.com/filecoin-project/lotus/journal" | ||
|
@@ -506,33 +505,3 @@ func (m *Miner) createBlock(base *MiningBase, addr address.Address, ticket *type | |
WinningPoStProof: wpostProof, | ||
}) | ||
} | ||
|
||
type actCacheEntry struct { | ||
act *types.Actor | ||
err error | ||
} | ||
|
||
type cachedActorLookup struct { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. dead code |
||
tsk types.TipSetKey | ||
cache map[address.Address]actCacheEntry | ||
fallback gasguess.ActorLookup | ||
} | ||
|
||
func (c *cachedActorLookup) StateGetActor(ctx context.Context, a address.Address, tsk types.TipSetKey) (*types.Actor, error) { | ||
if c.tsk == tsk { | ||
e, has := c.cache[a] | ||
if has { | ||
return e.act, e.err | ||
} | ||
} | ||
|
||
e, err := c.fallback(ctx, a, tsk) | ||
if c.tsk == tsk { | ||
c.cache[a] = actCacheEntry{ | ||
act: e, err: err, | ||
} | ||
} | ||
return e, err | ||
} | ||
|
||
type ActorLookup func(context.Context, address.Address, types.TipSetKey) (*types.Actor, error) |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -6,7 +6,6 @@ import ( | |
"strconv" | ||
|
||
cid "github.com/ipfs/go-cid" | ||
cbor "github.com/ipfs/go-ipld-cbor" | ||
"go.uber.org/fx" | ||
"golang.org/x/xerrors" | ||
|
||
|
@@ -35,7 +34,6 @@ import ( | |
"github.com/filecoin-project/lotus/chain/types" | ||
"github.com/filecoin-project/lotus/chain/vm" | ||
"github.com/filecoin-project/lotus/chain/wallet" | ||
"github.com/filecoin-project/lotus/lib/bufbstore" | ||
"github.com/filecoin-project/lotus/node/modules/dtypes" | ||
) | ||
|
||
|
@@ -94,19 +92,20 @@ func (a *StateAPI) StateNetworkName(ctx context.Context) (dtypes.NetworkName, er | |
} | ||
|
||
func (a *StateAPI) StateMinerSectors(ctx context.Context, addr address.Address, sectorNos *bitfield.BitField, tsk types.TipSetKey) ([]*miner.SectorOnChainInfo, error) { | ||
ts, err := a.Chain.GetTipSetFromKey(tsk) | ||
act, err := a.StateManager.LoadActorTsk(ctx, addr, tsk) | ||
if err != nil { | ||
return nil, xerrors.Errorf("loading tipset %s: %w", tsk, err) | ||
return nil, xerrors.Errorf("failed to load miner actor: %w", err) | ||
} | ||
return stmgr.GetMinerSectorSet(ctx, a.StateManager, ts, addr, sectorNos) | ||
} | ||
|
||
func (a *StateAPI) StateMinerActiveSectors(ctx context.Context, maddr address.Address, tsk types.TipSetKey) ([]*miner.SectorOnChainInfo, error) { // TODO: only used in cli | ||
ts, err := a.Chain.GetTipSetFromKey(tsk) | ||
mas, err := miner.Load(a.StateManager.ChainStore().Store(ctx), act) | ||
if err != nil { | ||
return nil, xerrors.Errorf("loading tipset %s: %w", tsk, err) | ||
return nil, xerrors.Errorf("failed to load miner actor state: %w", err) | ||
} | ||
|
||
return mas.LoadSectors(sectorNos) | ||
} | ||
|
||
func (a *StateAPI) StateMinerActiveSectors(ctx context.Context, maddr address.Address, tsk types.TipSetKey) ([]*miner.SectorOnChainInfo, error) { // TODO: only used in cli | ||
act, err := a.StateManager.LoadActorTsk(ctx, maddr, tsk) | ||
if err != nil { | ||
return nil, xerrors.Errorf("failed to load miner actor: %w", err) | ||
|
@@ -122,7 +121,7 @@ func (a *StateAPI) StateMinerActiveSectors(ctx context.Context, maddr address.Ad | |
return nil, xerrors.Errorf("merge partition active sets: %w", err) | ||
} | ||
|
||
return stmgr.GetMinerSectorSet(ctx, a.StateManager, ts, maddr, &activeSectors) | ||
return mas.LoadSectors(&activeSectors) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This avoids loading the actor twice. |
||
} | ||
|
||
func (m *StateModule) StateMinerInfo(ctx context.Context, actor address.Address, tsk types.TipSetKey) (miner.MinerInfo, error) { | ||
|
@@ -426,38 +425,12 @@ func (a *StateAPI) StateReplay(ctx context.Context, tsk types.TipSetKey, mc cid. | |
}, nil | ||
} | ||
|
||
func stateForTs(ctx context.Context, ts *types.TipSet, cstore *store.ChainStore, smgr *stmgr.StateManager) (*state.StateTree, error) { | ||
if ts == nil { | ||
ts = cstore.GetHeaviestTipSet() | ||
} | ||
|
||
st, _, err := smgr.TipSetState(ctx, ts) | ||
if err != nil { | ||
return nil, err | ||
} | ||
|
||
buf := bufbstore.NewBufferedBstore(cstore.Blockstore()) | ||
cst := cbor.NewCborStore(buf) | ||
return state.LoadStateTree(cst, st) | ||
} | ||
func (a *StateAPI) stateForTs(ctx context.Context, ts *types.TipSet) (*state.StateTree, error) { | ||
return stateForTs(ctx, ts, a.Chain, a.StateManager) | ||
} | ||
func (m *StateModule) stateForTs(ctx context.Context, ts *types.TipSet) (*state.StateTree, error) { | ||
return stateForTs(ctx, ts, m.Chain, m.StateManager) | ||
} | ||
|
||
func (m *StateModule) StateGetActor(ctx context.Context, actor address.Address, tsk types.TipSetKey) (*types.Actor, error) { | ||
ts, err := m.Chain.GetTipSetFromKey(tsk) | ||
if err != nil { | ||
return nil, xerrors.Errorf("loading tipset %s: %w", tsk, err) | ||
} | ||
state, err := m.stateForTs(ctx, ts) | ||
if err != nil { | ||
return nil, xerrors.Errorf("computing tipset state failed: %w", err) | ||
} | ||
|
||
return state.GetActor(actor) | ||
return m.StateManager.LoadActor(ctx, actor, ts) | ||
} | ||
|
||
func (m *StateModule) StateLookupID(ctx context.Context, addr address.Address, tsk types.TipSetKey) (address.Address, error) { | ||
|
@@ -483,17 +456,12 @@ func (a *StateAPI) StateReadState(ctx context.Context, actor address.Address, ts | |
if err != nil { | ||
return nil, xerrors.Errorf("loading tipset %s: %w", tsk, err) | ||
} | ||
state, err := a.stateForTs(ctx, ts) | ||
if err != nil { | ||
return nil, xerrors.Errorf("getting state for tipset: %w", err) | ||
} | ||
|
||
act, err := state.GetActor(actor) | ||
act, err := a.StateManager.LoadActor(ctx, actor, ts) | ||
if err != nil { | ||
return nil, xerrors.Errorf("getting actor: %w", err) | ||
} | ||
|
||
blk, err := state.Store.(*cbor.BasicIpldStore).Blocks.Get(act.Head) | ||
blk, err := a.Chain.Blockstore().Get(act.Head) | ||
if err != nil { | ||
return nil, xerrors.Errorf("getting actor head: %w", err) | ||
} | ||
|
@@ -529,6 +497,7 @@ func (a *StateAPI) StateDecodeParams(ctx context.Context, toAddr address.Address | |
|
||
// This is on StateAPI because miner.Miner requires this, and MinerAPI requires miner.Miner | ||
func (a *StateAPI) MinerGetBaseInfo(ctx context.Context, maddr address.Address, epoch abi.ChainEpoch, tsk types.TipSetKey) (*api.MiningBaseInfo, error) { | ||
// XXX: Gets the state by computing the tipset state, instead of looking at the parent. | ||
return stmgr.MinerGetBaseInfo(ctx, a.StateManager, a.Beacon, tsk, epoch, maddr, a.ProofVerifier) | ||
} | ||
|
||
|
@@ -1372,11 +1341,11 @@ func (a *StateAPI) StateCirculatingSupply(ctx context.Context, tsk types.TipSetK | |
return types.EmptyInt, xerrors.Errorf("loading tipset %s: %w", tsk, err) | ||
} | ||
|
||
sTree, err := a.stateForTs(ctx, ts) | ||
sTree, err := a.StateManager.ParentState(ts) | ||
if err != nil { | ||
return types.EmptyInt, err | ||
} | ||
return a.StateManager.GetCirculatingSupply(ctx, ts.Height(), sTree) | ||
return a.StateManager.GetCirculatingSupply(ctx, ts.Height()-1, sTree) | ||
} | ||
|
||
func (a *StateAPI) StateVMCirculatingSupplyInternal(ctx context.Context, tsk types.TipSetKey) (api.CirculatingSupply, error) { | ||
|
@@ -1393,7 +1362,7 @@ func stateVMCirculatingSupplyInternal( | |
return api.CirculatingSupply{}, xerrors.Errorf("loading tipset %s: %w", tsk, err) | ||
} | ||
|
||
sTree, err := stateForTs(ctx, ts, cstore, smgr) | ||
sTree, err := smgr.ParentState(ts) | ||
if err != nil { | ||
return api.CirculatingSupply{}, err | ||
} | ||
|
@@ -1407,5 +1376,7 @@ func (m *StateModule) StateNetworkVersion(ctx context.Context, tsk types.TipSetK | |
return network.VersionMax, xerrors.Errorf("loading tipset %s: %w", tsk, err) | ||
} | ||
|
||
// TODO: Height-1 to be consistent with the rest of the APIs? | ||
// But that's likely going to break a bunch of stuff. | ||
return m.StateManager.GetNtwkVersion(ctx, ts.Height()), nil | ||
} |
Original file line number | Diff line number | Diff line change | ||||||
---|---|---|---|---|---|---|---|---|
|
@@ -4,6 +4,7 @@ import ( | |||||||
"context" | ||||||||
|
||||||||
"go.uber.org/fx" | ||||||||
"golang.org/x/xerrors" | ||||||||
|
||||||||
"github.com/filecoin-project/lotus/node/impl/full" | ||||||||
|
||||||||
|
@@ -21,13 +22,41 @@ type MpoolNonceAPI struct { | |||||||
StateAPI full.StateAPI | ||||||||
} | ||||||||
|
||||||||
// GetNonce gets the nonce from actor state | ||||||||
// GetNonce gets the nonce from current chain head. | ||||||||
func (a *MpoolNonceAPI) GetNonce(addr address.Address) (uint64, error) { | ||||||||
Stebalien marked this conversation as resolved.
Show resolved
Hide resolved
|
||||||||
act, err := a.StateAPI.StateGetActor(context.Background(), addr, types.EmptyTSK) | ||||||||
ts := a.StateAPI.Chain.GetHeaviestTipSet() | ||||||||
|
||||||||
// make sure we have a key address so we can compare with messages | ||||||||
keyAddr, err := a.StateAPI.StateManager.ResolveToKeyAddress(context.TODO(), addr, ts) | ||||||||
if err != nil { | ||||||||
return 0, err | ||||||||
} | ||||||||
|
||||||||
// Load the last nonce from the state, if it exists. | ||||||||
highestNonce := uint64(0) | ||||||||
if baseActor, err := a.StateAPI.StateManager.LoadActorRaw(context.TODO(), addr, ts.ParentState()); err != nil { | ||||||||
if !xerrors.Is(err, types.ErrActorNotFound) { | ||||||||
return 0, err | ||||||||
} | ||||||||
} else { | ||||||||
highestNonce = baseActor.Nonce | ||||||||
} | ||||||||
|
||||||||
// Otherwise, find the highest nonce in the tipset. | ||||||||
msgs, err := a.StateAPI.Chain.MessagesForTipset(ts) | ||||||||
if err != nil { | ||||||||
return 0, err | ||||||||
} | ||||||||
return act.Nonce, nil | ||||||||
for _, msg := range msgs { | ||||||||
vmmsg := msg.VMMessage() | ||||||||
if vmmsg.From != keyAddr { | ||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think msg.From can technically also be an ID address, though I don't see messages like that on-chain There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. You sure? It looks like message verification will fail if the from address is not a public key. lotus/chain/messagepool/messagepool.go Lines 635 to 637 in 4937fb9
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Uff we should fix it. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. yeah, you should abosolutely be able to send a message with an ID address as the from There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Well, we can add that to the network upgrade. Note: we'll need to carefully check the VM to make sure we resolve everything as expected before passing it off to the actors. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Note: we currently implicitly resolve the from address when sending. Should we not be doing that? |
||||||||
continue | ||||||||
} | ||||||||
if vmmsg.Nonce >= highestNonce { | ||||||||
highestNonce = vmmsg.Nonce + 1 | ||||||||
} | ||||||||
} | ||||||||
return highestNonce, nil | ||||||||
} | ||||||||
|
||||||||
var _ messagesigner.MpoolNonceAPI = (*MpoolNonceAPI)(nil) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This was a drive-by fix. Removed because it was only being used in one place at this point.