diff --git a/.gitignore b/.gitignore index 940f37b3ff4..05f762d8d9b 100644 --- a/.gitignore +++ b/.gitignore @@ -11,6 +11,7 @@ /lotus-stats /lotus-bench /lotus-gateway +/lotus-pcr /bench.json /lotuspond/front/node_modules /lotuspond/front/build diff --git a/api/api_full.go b/api/api_full.go index cbf05b3636e..dace85ed3cd 100644 --- a/api/api_full.go +++ b/api/api_full.go @@ -354,6 +354,8 @@ type FullNode interface { StateSectorPartition(ctx context.Context, maddr address.Address, sectorNumber abi.SectorNumber, tok types.TipSetKey) (*SectorLocation, error) // StateSearchMsg searches for a message in the chain, and returns its receipt and the tipset where it was executed StateSearchMsg(context.Context, cid.Cid) (*MsgLookup, error) + // StateMsgGasCost searches for a message in the chain, and returns details of the messages gas costs, including the penalty and miner tip + StateMsgGasCost(context.Context, cid.Cid, types.TipSetKey) (*MsgGasCost, error) // StateWaitMsg looks back in the chain for a message. If not found, it blocks until the // message arrives on chain, and gets to the indicated confidence depth. StateWaitMsg(ctx context.Context, cid cid.Cid, confidence uint64) (*MsgLookup, error) @@ -531,6 +533,17 @@ type MsgLookup struct { Height abi.ChainEpoch } +type MsgGasCost struct { + Message cid.Cid // Can be different than requested, in case it was replaced, but only gas values changed + GasUsed abi.TokenAmount + BaseFeeBurn abi.TokenAmount + OverEstimationBurn abi.TokenAmount + MinerPenalty abi.TokenAmount + MinerTip abi.TokenAmount + Refund abi.TokenAmount + TotalCost abi.TokenAmount +} + type BlockMessages struct { BlsMessages []*types.Message SecpkMessages []*types.SignedMessage diff --git a/api/apistruct/struct.go b/api/apistruct/struct.go index 53c8414bae3..b37c667e998 100644 --- a/api/apistruct/struct.go +++ b/api/apistruct/struct.go @@ -183,6 +183,7 @@ type FullNodeStruct struct { StateReplay func(context.Context, types.TipSetKey, cid.Cid) (*api.InvocResult, error) `perm:"read"` StateGetActor func(context.Context, address.Address, types.TipSetKey) (*types.Actor, error) `perm:"read"` StateReadState func(context.Context, address.Address, types.TipSetKey) (*api.ActorState, error) `perm:"read"` + StateMsgGasCost func(context.Context, cid.Cid, types.TipSetKey) (*api.MsgGasCost, error) `perm:"read"` StateWaitMsg func(ctx context.Context, cid cid.Cid, confidence uint64) (*api.MsgLookup, error) `perm:"read"` StateSearchMsg func(context.Context, cid.Cid) (*api.MsgLookup, error) `perm:"read"` StateListMiners func(context.Context, types.TipSetKey) ([]address.Address, error) `perm:"read"` @@ -816,6 +817,10 @@ func (c *FullNodeStruct) StateReadState(ctx context.Context, addr address.Addres return c.Internal.StateReadState(ctx, addr, tsk) } +func (c *FullNodeStruct) StateMsgGasCost(ctx context.Context, msgc cid.Cid, tsk types.TipSetKey) (*api.MsgGasCost, error) { + return c.Internal.StateMsgGasCost(ctx, msgc, tsk) +} + func (c *FullNodeStruct) StateWaitMsg(ctx context.Context, msgc cid.Cid, confidence uint64) (*api.MsgLookup, error) { return c.Internal.StateWaitMsg(ctx, msgc, confidence) } diff --git a/build/params_2k.go b/build/params_2k.go index 0ef1d9b3407..9913374e166 100644 --- a/build/params_2k.go +++ b/build/params_2k.go @@ -29,7 +29,7 @@ func init() { BuildType |= Build2k } -const BlockDelaySecs = uint64(30) +const BlockDelaySecs = uint64(4) const PropagationDelaySecs = uint64(1) diff --git a/chain/stmgr/stmgr.go b/chain/stmgr/stmgr.go index e6103e2b3a3..a7f94e6ee6a 100644 --- a/chain/stmgr/stmgr.go +++ b/chain/stmgr/stmgr.go @@ -233,8 +233,8 @@ func (sm *StateManager) ApplyBlocks(ctx context.Context, parentEpoch abi.ChainEp } receipts = append(receipts, &r.MessageReceipt) - gasReward = big.Add(gasReward, r.MinerTip) - penalty = big.Add(penalty, r.Penalty) + gasReward = big.Add(gasReward, r.GasCosts.MinerTip) + penalty = big.Add(penalty, r.GasCosts.MinerPenalty) if cb != nil { if err := cb(cm.Cid(), m, r); err != nil { diff --git a/chain/stmgr/utils.go b/chain/stmgr/utils.go index 27b71f35850..c09f2b22a3e 100644 --- a/chain/stmgr/utils.go +++ b/chain/stmgr/utils.go @@ -554,7 +554,7 @@ func MinerGetBaseInfo(ctx context.Context, sm *StateManager, bcs beacon.Schedule sectors, err := GetSectorsForWinningPoSt(ctx, pv, sm, lbst, maddr, prand) if err != nil { - return nil, xerrors.Errorf("getting wpost proving set: %w", err) + return nil, xerrors.Errorf("getting winning post proving set: %w", err) } if len(sectors) == 0 { diff --git a/chain/store/store.go b/chain/store/store.go index 20a7e30311e..ad30e0324bd 100644 --- a/chain/store/store.go +++ b/chain/store/store.go @@ -18,7 +18,6 @@ import ( "github.com/filecoin-project/specs-actors/actors/util/adt" "github.com/filecoin-project/lotus/api" - "github.com/filecoin-project/lotus/chain/state" "github.com/filecoin-project/lotus/chain/vm" "github.com/filecoin-project/lotus/journal" bstore "github.com/filecoin-project/lotus/lib/blockstore" @@ -767,32 +766,16 @@ type BlockMessages struct { func (cs *ChainStore) BlockMsgsForTipset(ts *types.TipSet) ([]BlockMessages, error) { applied := make(map[address.Address]uint64) - cst := cbor.NewCborStore(cs.bs) - st, err := state.LoadStateTree(cst, ts.Blocks()[0].ParentStateRoot) - if err != nil { - return nil, xerrors.Errorf("failed to load state tree") - } - - preloadAddr := func(a address.Address) error { - if _, ok := applied[a]; !ok { - act, err := st.GetActor(a) - if err != nil { - return err - } - - applied[a] = act.Nonce - } - return nil - } - selectMsg := func(m *types.Message) (bool, error) { - if err := preloadAddr(m.From); err != nil { - return false, err + // The first match for a sender is guaranteed to have correct nonce -- the block isn't valid otherwise + if _, ok := applied[m.From]; !ok { + applied[m.From] = m.Nonce } if applied[m.From] != m.Nonce { return false, nil } + applied[m.From]++ return true, nil diff --git a/chain/sync.go b/chain/sync.go index f7530f5564c..b5716a34308 100644 --- a/chain/sync.go +++ b/chain/sync.go @@ -991,7 +991,7 @@ func (syncer *Syncer) VerifyWinningPoStProof(ctx context.Context, h *types.Block rand, err := store.DrawRandomness(rbase.Data, crypto.DomainSeparationTag_WinningPoStChallengeSeed, h.Height, buf.Bytes()) if err != nil { - return xerrors.Errorf("failed to get randomness for verifying winningPost proof: %w", err) + return xerrors.Errorf("failed to get randomness for verifying winning post proof: %w", err) } mid, err := address.IDFromAddress(h.Miner) diff --git a/chain/sync_test.go b/chain/sync_test.go index 0b0d1ed0098..f4c83341f4c 100644 --- a/chain/sync_test.go +++ b/chain/sync_test.go @@ -662,6 +662,49 @@ func TestDuplicateNonce(t *testing.T) { require.Equal(t, includedMsg, mft[0].VMMessage().Cid(), "messages for tipset didn't contain expected message") } +// This test asserts that a block that includes a message with bad nonce can't be synced. A nonce is "bad" if it can't +// be applied on the parent state. +func TestBadNonce(t *testing.T) { + H := 10 + tu := prepSyncTest(t, H) + + base := tu.g.CurTipset + + // Produce a message from the banker with a bad nonce + makeBadMsg := func() *types.SignedMessage { + + ba, err := tu.nds[0].StateGetActor(context.TODO(), tu.g.Banker(), base.TipSet().Key()) + require.NoError(t, err) + msg := types.Message{ + To: tu.g.Banker(), + From: tu.g.Banker(), + + Nonce: ba.Nonce + 5, + + Value: types.NewInt(1), + + Method: 0, + + GasLimit: 100_000_000, + GasFeeCap: types.NewInt(0), + GasPremium: types.NewInt(0), + } + + sig, err := tu.g.Wallet().Sign(context.TODO(), tu.g.Banker(), msg.Cid().Bytes()) + require.NoError(t, err) + + return &types.SignedMessage{ + Message: msg, + Signature: *sig, + } + } + + msgs := make([][]*types.SignedMessage, 1) + msgs[0] = []*types.SignedMessage{makeBadMsg()} + + tu.mineOnBlock(base, 0, []int{0}, true, true, msgs) +} + func BenchmarkSyncBasic(b *testing.B) { for i := 0; i < b.N; i++ { runSyncBenchLength(b, 100) diff --git a/chain/vm/burn.go b/chain/vm/burn.go index eb0611349e8..9f9b95755b7 100644 --- a/chain/vm/burn.go +++ b/chain/vm/burn.go @@ -22,6 +22,17 @@ type GasOutputs struct { GasBurned int64 } +// ZeroGasOutputs returns a logically zeroed GasOutputs. +func ZeroGasOutputs() GasOutputs { + return GasOutputs{ + BaseFeeBurn: big.Zero(), + OverEstimationBurn: big.Zero(), + MinerPenalty: big.Zero(), + MinerTip: big.Zero(), + Refund: big.Zero(), + } +} + // ComputeGasOverestimationBurn computes amount of gas to be refunded and amount of gas to be burned // Result is (refund, burn) func ComputeGasOverestimationBurn(gasUsed, gasLimit int64) (int64, int64) { @@ -58,13 +69,7 @@ func ComputeGasOverestimationBurn(gasUsed, gasLimit int64) (int64, int64) { func ComputeGasOutputs(gasUsed, gasLimit int64, baseFee, feeCap, gasPremium abi.TokenAmount) GasOutputs { gasUsedBig := big.NewInt(gasUsed) - out := GasOutputs{ - BaseFeeBurn: big.Zero(), - OverEstimationBurn: big.Zero(), - MinerPenalty: big.Zero(), - MinerTip: big.Zero(), - Refund: big.Zero(), - } + out := ZeroGasOutputs() baseFeeToPay := baseFee if baseFee.Cmp(feeCap.Int) > 0 { diff --git a/chain/vm/vm.go b/chain/vm/vm.go index c9acc865861..a90856a1b3e 100644 --- a/chain/vm/vm.go +++ b/chain/vm/vm.go @@ -201,10 +201,9 @@ type Rand interface { type ApplyRet struct { types.MessageReceipt ActorErr aerrors.ActorError - Penalty types.BigInt - MinerTip types.BigInt ExecutionTrace types.ExecutionTrace Duration time.Duration + GasCosts GasOutputs } func (vm *VM) send(ctx context.Context, msg *types.Message, parent *Runtime, @@ -328,8 +327,7 @@ func (vm *VM) ApplyImplicitMessage(ctx context.Context, msg *types.Message) (*Ap }, ActorErr: actorErr, ExecutionTrace: rt.executionTrace, - Penalty: types.NewInt(0), - MinerTip: types.NewInt(0), + GasCosts: GasOutputs{}, Duration: time.Since(start), }, actorErr } @@ -357,14 +355,15 @@ func (vm *VM) ApplyMessage(ctx context.Context, cmsg types.ChainMsg) (*ApplyRet, msgGasCost := msgGas.Total() // this should never happen, but is currently still exercised by some tests if msgGasCost > msg.GasLimit { + gasOutputs := ZeroGasOutputs() + gasOutputs.MinerPenalty = types.BigMul(vm.baseFee, abi.NewTokenAmount(msgGasCost)) return &ApplyRet{ MessageReceipt: types.MessageReceipt{ ExitCode: exitcode.SysErrOutOfGas, GasUsed: 0, }, - Penalty: types.BigMul(vm.baseFee, abi.NewTokenAmount(msgGasCost)), + GasCosts: gasOutputs, Duration: time.Since(start), - MinerTip: big.Zero(), }, nil } @@ -375,15 +374,16 @@ func (vm *VM) ApplyMessage(ctx context.Context, cmsg types.ChainMsg) (*ApplyRet, // this should never happen, but is currently still exercised by some tests if err != nil { if xerrors.Is(err, types.ErrActorNotFound) { + gasOutputs := ZeroGasOutputs() + gasOutputs.MinerPenalty = minerPenaltyAmount return &ApplyRet{ MessageReceipt: types.MessageReceipt{ ExitCode: exitcode.SysErrSenderInvalid, GasUsed: 0, }, ActorErr: aerrors.Newf(exitcode.SysErrSenderInvalid, "actor not found: %s", msg.From), - Penalty: minerPenaltyAmount, + GasCosts: gasOutputs, Duration: time.Since(start), - MinerTip: big.Zero(), }, nil } return nil, xerrors.Errorf("failed to look up from actor: %w", err) @@ -391,19 +391,22 @@ func (vm *VM) ApplyMessage(ctx context.Context, cmsg types.ChainMsg) (*ApplyRet, // this should never happen, but is currently still exercised by some tests if !fromActor.Code.Equals(builtin.AccountActorCodeID) { + gasOutputs := ZeroGasOutputs() + gasOutputs.MinerPenalty = minerPenaltyAmount return &ApplyRet{ MessageReceipt: types.MessageReceipt{ ExitCode: exitcode.SysErrSenderInvalid, GasUsed: 0, }, ActorErr: aerrors.Newf(exitcode.SysErrSenderInvalid, "send from not account actor: %s", fromActor.Code), - Penalty: minerPenaltyAmount, + GasCosts: gasOutputs, Duration: time.Since(start), - MinerTip: big.Zero(), }, nil } if msg.Nonce != fromActor.Nonce { + gasOutputs := ZeroGasOutputs() + gasOutputs.MinerPenalty = minerPenaltyAmount return &ApplyRet{ MessageReceipt: types.MessageReceipt{ ExitCode: exitcode.SysErrSenderStateInvalid, @@ -411,14 +414,16 @@ func (vm *VM) ApplyMessage(ctx context.Context, cmsg types.ChainMsg) (*ApplyRet, }, ActorErr: aerrors.Newf(exitcode.SysErrSenderStateInvalid, "actor nonce invalid: msg:%d != state:%d", msg.Nonce, fromActor.Nonce), - Penalty: minerPenaltyAmount, + + GasCosts: gasOutputs, Duration: time.Since(start), - MinerTip: big.Zero(), }, nil } gascost := types.BigMul(types.NewInt(uint64(msg.GasLimit)), msg.GasFeeCap) if fromActor.Balance.LessThan(gascost) { + gasOutputs := ZeroGasOutputs() + gasOutputs.MinerPenalty = minerPenaltyAmount return &ApplyRet{ MessageReceipt: types.MessageReceipt{ ExitCode: exitcode.SysErrSenderStateInvalid, @@ -426,9 +431,8 @@ func (vm *VM) ApplyMessage(ctx context.Context, cmsg types.ChainMsg) (*ApplyRet, }, ActorErr: aerrors.Newf(exitcode.SysErrSenderStateInvalid, "actor balance less than needed: %s < %s", types.FIL(fromActor.Balance), types.FIL(gascost)), - Penalty: minerPenaltyAmount, + GasCosts: gasOutputs, Duration: time.Since(start), - MinerTip: big.Zero(), }, nil } @@ -521,8 +525,7 @@ func (vm *VM) ApplyMessage(ctx context.Context, cmsg types.ChainMsg) (*ApplyRet, }, ActorErr: actorErr, ExecutionTrace: rt.executionTrace, - Penalty: gasOutputs.MinerPenalty, - MinerTip: gasOutputs.MinerTip, + GasCosts: gasOutputs, Duration: time.Since(start), }, nil } diff --git a/cli/client.go b/cli/client.go index e68f98791f8..d9ce9251ec7 100644 --- a/cli/client.go +++ b/cli/client.go @@ -12,6 +12,8 @@ import ( "text/tabwriter" "time" + "github.com/filecoin-project/specs-actors/actors/builtin" + tm "github.com/buger/goterm" "github.com/docker/go-units" "github.com/fatih/color" @@ -527,6 +529,11 @@ func interactiveDeal(cctx *cli.Context) error { continue } + if days < int(build.MinDealDuration/builtin.EpochsInDay) { + printErr(xerrors.Errorf("minimum duration is %d days", int(build.MinDealDuration/builtin.EpochsInDay))) + continue + } + state = "miner" case "miner": fmt.Print("Miner Address (t0..): ") diff --git a/cli/state.go b/cli/state.go index bfcbdf94a0d..2476d7c59a4 100644 --- a/cli/state.go +++ b/cli/state.go @@ -66,6 +66,7 @@ var stateCmd = &cli.Command{ stateGetDealSetCmd, stateWaitMsgCmd, stateSearchMsgCmd, + stateMsgCostCmd, stateMinerInfo, stateMarketCmd, }, @@ -1312,6 +1313,60 @@ var stateSearchMsgCmd = &cli.Command{ }, } +var stateMsgCostCmd = &cli.Command{ + Name: "msg-cost", + Usage: "Get the detailed gas costs of a message", + ArgsUsage: "[messageCid]", + Action: func(cctx *cli.Context) error { + if !cctx.Args().Present() { + return fmt.Errorf("must specify message cid to get gas costs for") + } + + api, closer, err := GetFullNodeAPI(cctx) + if err != nil { + return err + } + defer closer() + + ctx := ReqContext(cctx) + + msg, err := cid.Decode(cctx.Args().First()) + if err != nil { + return err + } + + tsk := types.EmptyTSK + + ts, err := LoadTipSet(ctx, cctx, api) + if err != nil { + return err + } + + if ts != nil { + tsk = ts.Key() + } + + mgc, err := api.StateMsgGasCost(ctx, msg, tsk) + if err != nil { + return err + } + + if mgc != nil { + fmt.Printf("Message CID: %s", mgc.Message) + fmt.Printf("\nGas Used: %d", mgc.GasUsed) + fmt.Printf("\nBase Fee Burn: %d", mgc.BaseFeeBurn) + fmt.Printf("\nOverestimation Burn: %d", mgc.OverEstimationBurn) + fmt.Printf("\nMiner Tip: %d", mgc.MinerTip) + fmt.Printf("\nRefund: %d", mgc.Refund) + fmt.Printf("\nTotal Cost: %d", mgc.TotalCost) + fmt.Printf("\nMiner Penalty: %d", mgc.MinerPenalty) + } else { + fmt.Print("message was not found on chain") + } + return nil + }, +} + var stateCallCmd = &cli.Command{ Name: "call", Usage: "Invoke a method on an actor locally", diff --git a/cmd/lotus-bench/import.go b/cmd/lotus-bench/import.go index 7fe63eae19f..f2845ba208f 100644 --- a/cmd/lotus-bench/import.go +++ b/cmd/lotus-bench/import.go @@ -56,6 +56,10 @@ var importBenchCmd = &cli.Command{ Usage: "set the parallelism factor for batch seal verification", Value: runtime.NumCPU(), }, + &cli.StringFlag{ + Name: "repodir", + Usage: "set the repo directory for the lotus bench run (defaults to /tmp)", + }, }, Action: func(cctx *cli.Context) error { vm.BatchSealVerifyParallelism = cctx.Int("batch-seal-verify-threads") @@ -70,9 +74,15 @@ var importBenchCmd = &cli.Command{ } defer cfi.Close() //nolint:errcheck // read only file - tdir, err := ioutil.TempDir("", "lotus-import-bench") - if err != nil { - return err + var tdir string + if rdir := cctx.String("repodir"); rdir != "" { + tdir = rdir + } else { + tmp, err := ioutil.TempDir("", "lotus-import-bench") + if err != nil { + return err + } + tdir = tmp } bds, err := badger.NewDatastore(tdir, nil) diff --git a/cmd/lotus-bench/main.go b/cmd/lotus-bench/main.go index 431bfdd4472..7da7544151e 100644 --- a/cmd/lotus-bench/main.go +++ b/cmd/lotus-bench/main.go @@ -387,7 +387,7 @@ var sealBenchCmd = &cli.Command{ return err } if !ok { - log.Error("post verification failed") + log.Error("window post verification failed") } verifyWindowpost1 := time.Now() @@ -403,7 +403,7 @@ var sealBenchCmd = &cli.Command{ return err } if !ok { - log.Error("post verification failed") + log.Error("window post verification failed") } verifyWindowpost2 := time.Now() diff --git a/documentation/en/api-methods.md b/documentation/en/api-methods.md index d72beca983a..2f3164bb794 100644 --- a/documentation/en/api-methods.md +++ b/documentation/en/api-methods.md @@ -148,6 +148,7 @@ * [StateMinerRecoveries](#StateMinerRecoveries) * [StateMinerSectorCount](#StateMinerSectorCount) * [StateMinerSectors](#StateMinerSectors) + * [StateMsgGasCost](#StateMsgGasCost) * [StateNetworkName](#StateNetworkName) * [StateReadState](#StateReadState) * [StateReplay](#StateReplay) @@ -3737,6 +3738,45 @@ Inputs: Response: `null` +### StateMsgGasCost +StateMsgGasCost searches for a message in the chain, and returns details of the messages gas costs, including the penalty and miner tip + + +Perms: read + +Inputs: +```json +[ + { + "/": "bafy2bzacea3wsdh6y3a36tb3skempjoxqpuyompjbmfeyf34fi3uy6uue42v4" + }, + [ + { + "/": "bafy2bzacea3wsdh6y3a36tb3skempjoxqpuyompjbmfeyf34fi3uy6uue42v4" + }, + { + "/": "bafy2bzacebp3shtrn43k7g3unredz7fxn4gj533d3o43tqn2p2ipxxhrvchve" + } + ] +] +``` + +Response: +```json +{ + "Message": { + "/": "bafy2bzacea3wsdh6y3a36tb3skempjoxqpuyompjbmfeyf34fi3uy6uue42v4" + }, + "GasUsed": "0", + "BaseFeeBurn": "0", + "OverEstimationBurn": "0", + "MinerPenalty": "0", + "MinerTip": "0", + "Refund": "0", + "TotalCost": "0" +} +``` + ### StateNetworkName StateNetworkName returns the name of the network the node is synced to diff --git a/extern/storage-sealing/upgrade_queue.go b/extern/storage-sealing/upgrade_queue.go index 650fdc83d10..af2d1827d8a 100644 --- a/extern/storage-sealing/upgrade_queue.go +++ b/extern/storage-sealing/upgrade_queue.go @@ -67,6 +67,8 @@ func (m *Sealing) tryUpgradeSector(ctx context.Context, params *miner.SectorPreC params.ReplaceSectorDeadline = loc.Deadline params.ReplaceSectorPartition = loc.Partition + log.Infof("replacing sector %d with %d", *replace, params.SectorNumber) + ri, err := m.api.StateSectorGetInfo(ctx, m.maddr, *replace, nil) if err != nil { log.Errorf("error calling StateSectorGetInfo for replaced sector: %+v", err) diff --git a/node/builder.go b/node/builder.go index 8c7674ffde5..c37a5db5819 100644 --- a/node/builder.go +++ b/node/builder.go @@ -382,7 +382,7 @@ func StorageMiner(out *api.StorageMiner) Option { func(s *Settings) error { resAPI := &impl.StorageMinerAPI{} - s.invokes[ExtractApiKey] = fx.Extract(resAPI) + s.invokes[ExtractApiKey] = fx.Populate(resAPI) *out = resAPI return nil }, @@ -509,7 +509,7 @@ func FullAPI(out *api.FullNode) Option { }, func(s *Settings) error { resAPI := &impl.FullNodeAPI{} - s.invokes[ExtractApiKey] = fx.Extract(resAPI) + s.invokes[ExtractApiKey] = fx.Populate(resAPI) *out = resAPI return nil }, diff --git a/node/impl/full/state.go b/node/impl/full/state.go index f9fcdab8a5e..0bd776a608a 100644 --- a/node/impl/full/state.go +++ b/node/impl/full/state.go @@ -1225,3 +1225,52 @@ func (a *StateAPI) StateCirculatingSupply(ctx context.Context, tsk types.TipSetK return a.StateManager.GetCirculatingSupplyDetailed(ctx, ts.Height(), sTree) } + +func (a *StateAPI) StateMsgGasCost(ctx context.Context, inputMsg cid.Cid, tsk types.TipSetKey) (*api.MsgGasCost, error) { + var msg cid.Cid + var ts *types.TipSet + var err error + if tsk != types.EmptyTSK { + msg = inputMsg + ts, err = a.Chain.LoadTipSet(tsk) + if err != nil { + return nil, xerrors.Errorf("loading tipset %s: %w", tsk, err) + } + } else { + mlkp, err := a.StateSearchMsg(ctx, inputMsg) + if err != nil { + return nil, xerrors.Errorf("searching for msg %s: %w", inputMsg, err) + } + if mlkp == nil { + return nil, xerrors.Errorf("didn't find msg %s", inputMsg) + } + + executionTs, err := a.Chain.GetTipSetFromKey(mlkp.TipSet) + if err != nil { + return nil, xerrors.Errorf("loading tipset %s: %w", mlkp.TipSet, err) + } + + ts, err = a.Chain.LoadTipSet(executionTs.Parents()) + if err != nil { + return nil, xerrors.Errorf("loading parent tipset %s: %w", mlkp.TipSet, err) + } + + msg = mlkp.Message + } + + m, r, err := a.StateManager.Replay(ctx, ts, msg) + if err != nil { + return nil, err + } + + return &api.MsgGasCost{ + Message: msg, + GasUsed: big.NewInt(r.GasUsed), + BaseFeeBurn: r.GasCosts.BaseFeeBurn, + OverEstimationBurn: r.GasCosts.OverEstimationBurn, + MinerPenalty: r.GasCosts.MinerPenalty, + MinerTip: r.GasCosts.MinerTip, + Refund: r.GasCosts.Refund, + TotalCost: big.Sub(m.RequiredFunds(), r.GasCosts.Refund), + }, nil +} diff --git a/storage/addresses.go b/storage/addresses.go index bef84536733..2388b9fca59 100644 --- a/storage/addresses.go +++ b/storage/addresses.go @@ -60,7 +60,7 @@ func AddressFor(ctx context.Context, a addrSelectApi, mi api.MinerInfo, use Addr return addr, nil } - log.Warnw("control address didn't have enough funds for PoSt message", "address", addr, "required", types.FIL(minFunds), "balance", types.FIL(b)) + log.Warnw("control address didn't have enough funds for window post message", "address", addr, "required", types.FIL(minFunds), "balance", types.FIL(b)) } // Try to use the owner account if we can, fallback to worker if we can't diff --git a/storage/wdpost_run.go b/storage/wdpost_run.go index 7aa90bbba8e..17b56744053 100644 --- a/storage/wdpost_run.go +++ b/storage/wdpost_run.go @@ -78,7 +78,7 @@ func (s *WindowPoStScheduler) doPost(ctx context.Context, deadline *dline.Info, posts, err := s.runPost(ctx, *deadline, ts) if err != nil { - log.Errorf("runPost failed: %+v", err) + log.Errorf("run window post failed: %+v", err) s.failPost(err, deadline) return } @@ -92,7 +92,7 @@ func (s *WindowPoStScheduler) doPost(ctx context.Context, deadline *dline.Info, post := &posts[i] sm, err := s.submitPost(ctx, post) if err != nil { - log.Errorf("submitPost failed: %+v", err) + log.Errorf("submit window post failed: %+v", err) s.failPost(err, deadline) } else { recordProofsEvent(post.Partitions, sm.Cid()) @@ -397,7 +397,7 @@ func (s *WindowPoStScheduler) runPost(ctx context.Context, di dline.Info, ts *ty rand, err := s.api.ChainGetRandomnessFromBeacon(ctx, ts.Key(), crypto.DomainSeparationTag_WindowedPoStChallengeSeed, di.Challenge, buf.Bytes()) if err != nil { - return nil, xerrors.Errorf("failed to get chain randomness for windowPost (ts=%d; deadline=%d): %w", ts.Height(), di, err) + return nil, xerrors.Errorf("failed to get chain randomness for window post (ts=%d; deadline=%d): %w", ts.Height(), di, err) } // Get the partitions for the given deadline @@ -490,7 +490,7 @@ func (s *WindowPoStScheduler) runPost(ctx context.Context, di dline.Info, ts *ty } // Generate proof - log.Infow("running windowPost", + log.Infow("running window post", "chain-random", rand, "deadline", di, "height", ts.Height(), @@ -507,7 +507,7 @@ func (s *WindowPoStScheduler) runPost(ctx context.Context, di dline.Info, ts *ty postOut, ps, err = s.prover.GenerateWindowPoSt(ctx, abi.ActorID(mid), sinfos, abi.PoStRandomness(rand)) elapsed := time.Since(tsStart) - log.Infow("computing window PoSt", "batch", batchIdx, "elapsed", elapsed) + log.Infow("computing window post", "batch", batchIdx, "elapsed", elapsed) if err == nil { // Proof generation successful, stop retrying @@ -517,10 +517,10 @@ func (s *WindowPoStScheduler) runPost(ctx context.Context, di dline.Info, ts *ty // Proof generation failed, so retry if len(ps) == 0 { - return nil, xerrors.Errorf("running post failed: %w", err) + return nil, xerrors.Errorf("running window post failed: %w", err) } - log.Warnw("generate window PoSt skipped sectors", "sectors", ps, "error", err, "try", retries) + log.Warnw("generate window post skipped sectors", "sectors", ps, "error", err, "try", retries) skipCount += uint64(len(ps)) for _, sector := range ps { @@ -547,7 +547,7 @@ func (s *WindowPoStScheduler) runPost(ctx context.Context, di dline.Info, ts *ty commEpoch := di.Open commRand, err := s.api.ChainGetRandomnessFromTickets(ctx, ts.Key(), crypto.DomainSeparationTag_PoStChainCommit, commEpoch, nil) if err != nil { - return nil, xerrors.Errorf("failed to get chain randomness for windowPost (ts=%d; deadline=%d): %w", ts.Height(), commEpoch, err) + return nil, xerrors.Errorf("failed to get chain randomness for window post (ts=%d; deadline=%d): %w", ts.Height(), commEpoch, err) } for i := range posts { @@ -644,7 +644,7 @@ func (s *WindowPoStScheduler) submitPost(ctx context.Context, proof *miner.Submi enc, aerr := actors.SerializeParams(proof) if aerr != nil { - return nil, xerrors.Errorf("could not serialize submit post parameters: %w", aerr) + return nil, xerrors.Errorf("could not serialize submit window post parameters: %w", aerr) } msg := &types.Message{ @@ -705,7 +705,7 @@ func (s *WindowPoStScheduler) setSender(ctx context.Context, msg *types.Message, pa, err := AddressFor(ctx, s.api, mi, PoStAddr, minFunds) if err != nil { - log.Errorw("error selecting address for post", "error", err) + log.Errorw("error selecting address for window post", "error", err) msg.From = s.worker return } diff --git a/storage/wdpost_sched.go b/storage/wdpost_sched.go index 037f4e481f3..d130d801cf5 100644 --- a/storage/wdpost_sched.go +++ b/storage/wdpost_sched.go @@ -110,7 +110,7 @@ func (s *WindowPoStScheduler) Run(ctx context.Context) { select { case changes, ok := <-notifs: if !ok { - log.Warn("WindowPoStScheduler notifs channel closed") + log.Warn("window post scheduler notifs channel closed") notifs = nil continue } @@ -151,10 +151,10 @@ func (s *WindowPoStScheduler) Run(ctx context.Context) { } if err := s.revert(ctx, lowest); err != nil { - log.Error("handling head reverts in windowPost sched: %+v", err) + log.Error("handling head reverts in window post sched: %+v", err) } if err := s.update(ctx, highest); err != nil { - log.Error("handling head updates in windowPost sched: %+v", err) + log.Error("handling head updates in window post sched: %+v", err) } span.End() @@ -184,7 +184,7 @@ func (s *WindowPoStScheduler) revert(ctx context.Context, newLowest *types.TipSe func (s *WindowPoStScheduler) update(ctx context.Context, new *types.TipSet) error { if new == nil { - return xerrors.Errorf("no new tipset in WindowPoStScheduler.update") + return xerrors.Errorf("no new tipset in window post sched update") } di, err := s.api.StateMinerProvingDeadline(ctx, s.actor, new.Key()) @@ -206,7 +206,7 @@ func (s *WindowPoStScheduler) update(ctx context.Context, new *types.TipSet) err // (Need to get correct deadline above, which is tricky) if di.Open+StartConfidence >= new.Height() { - log.Info("not starting windowPost yet, waiting for startconfidence", di.Open, di.Open+StartConfidence, new.Height()) + log.Info("not starting window post yet, waiting for startconfidence", di.Open, di.Open+StartConfidence, new.Height()) return nil } @@ -216,7 +216,7 @@ func (s *WindowPoStScheduler) update(ctx context.Context, new *types.TipSet) err s.activeEPS = 0 } s.failLk.Unlock()*/ - log.Infof("at %d, doPost for P %d, dd %d", new.Height(), di.PeriodStart, di.Index) + log.Infof("at %d, do window post for P %d, dd %d", new.Height(), di.PeriodStart, di.Index) s.doPost(ctx, di, new) @@ -238,7 +238,7 @@ func (s *WindowPoStScheduler) abortActivePoSt() { } }) - log.Warnf("Aborting Window PoSt (Deadline: %+v)", s.activeDeadline) + log.Warnf("Aborting window post (Deadline: %+v)", s.activeDeadline) } s.activeDeadline = nil