From 60a031a7134b673f4ebb31f61e3536969bc54634 Mon Sep 17 00:00:00 2001 From: Aayush Rajasekaran Date: Mon, 14 Sep 2020 00:25:54 -0400 Subject: [PATCH 1/3] Lower devnet block time --- build/params_2k.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build/params_2k.go b/build/params_2k.go index 0ef1d9b34..9913374e1 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) From d1850ea27d1488990f2395656a4154eabe0c9608 Mon Sep 17 00:00:00 2001 From: Aayush Rajasekaran Date: Sun, 13 Sep 2020 01:26:44 -0400 Subject: [PATCH 2/3] Add an API to get detailed gas costs for a message --- api/api_full.go | 13 ++++++++ api/apistruct/struct.go | 5 +++ chain/stmgr/stmgr.go | 4 +-- chain/vm/vm.go | 35 +++++++++++---------- cli/state.go | 55 +++++++++++++++++++++++++++++++++ documentation/en/api-methods.md | 35 +++++++++++++++++++++ node/impl/full/state.go | 40 ++++++++++++++++++++++++ 7 files changed, 169 insertions(+), 18 deletions(-) diff --git a/api/api_full.go b/api/api_full.go index 23226443a..588e567a8 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 fdb9843ff..9f2b7bc4b 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/chain/stmgr/stmgr.go b/chain/stmgr/stmgr.go index e6103e2b3..a7f94e6ee 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/vm/vm.go b/chain/vm/vm.go index e389a3531..eb1ef70ce 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 } @@ -362,9 +360,10 @@ func (vm *VM) ApplyMessage(ctx context.Context, cmsg types.ChainMsg) (*ApplyRet, ExitCode: exitcode.SysErrOutOfGas, GasUsed: 0, }, - Penalty: types.BigMul(vm.baseFee, abi.NewTokenAmount(msgGasCost)), + GasCosts: GasOutputs{ + MinerPenalty: types.BigMul(vm.baseFee, abi.NewTokenAmount(msgGasCost)), + }, Duration: time.Since(start), - MinerTip: big.Zero(), }, nil } @@ -381,9 +380,10 @@ func (vm *VM) ApplyMessage(ctx context.Context, cmsg types.ChainMsg) (*ApplyRet, GasUsed: 0, }, ActorErr: aerrors.Newf(exitcode.SysErrSenderInvalid, "actor not found: %s", msg.From), - Penalty: minerPenaltyAmount, + GasCosts: GasOutputs{ + MinerPenalty: minerPenaltyAmount, + }, Duration: time.Since(start), - MinerTip: big.Zero(), }, nil } return nil, xerrors.Errorf("failed to look up from actor: %w", err) @@ -397,9 +397,10 @@ func (vm *VM) ApplyMessage(ctx context.Context, cmsg types.ChainMsg) (*ApplyRet, GasUsed: 0, }, ActorErr: aerrors.Newf(exitcode.SysErrSenderInvalid, "send from not account actor: %s", fromActor.Code), - Penalty: minerPenaltyAmount, + GasCosts: GasOutputs{ + MinerPenalty: minerPenaltyAmount, + }, Duration: time.Since(start), - MinerTip: big.Zero(), }, nil } @@ -411,9 +412,11 @@ 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{ + MinerPenalty: minerPenaltyAmount, + }, Duration: time.Since(start), - MinerTip: big.Zero(), }, nil } @@ -426,9 +429,10 @@ 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{ + MinerPenalty: minerPenaltyAmount, + }, 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/state.go b/cli/state.go index 1036e8fe5..7729e729a 100644 --- a/cli/state.go +++ b/cli/state.go @@ -65,6 +65,7 @@ var stateCmd = &cli.Command{ stateGetDealSetCmd, stateWaitMsgCmd, stateSearchMsgCmd, + stateMsgCostCmd, stateMinerInfo, stateMarketCmd, }, @@ -1304,6 +1305,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("\nMessage CID: %d", 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("\nRefundd: %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/documentation/en/api-methods.md b/documentation/en/api-methods.md index 27875eca1..ec298d635 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) @@ -3731,6 +3732,40 @@ 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" + } +] +``` + +Response: +```json +{ + "Message": { + "/": "bafy2bzacea3wsdh6y3a36tb3skempjoxqpuyompjbmfeyf34fi3uy6uue42v4" + }, + "Receipt": { + "ExitCode": 0, + "Return": "Ynl0ZSBhcnJheQ==", + "GasUsed": 9 + }, + "BaseFeeBurn": "0", + "OverEstimationBurn": "0", + "MinerPenalty": "0", + "MinerTip": "0", + "Refund": "0" +} +``` + ### StateNetworkName StateNetworkName returns the name of the network the node is synced to diff --git a/node/impl/full/state.go b/node/impl/full/state.go index e183fafa4..1fb078001 100644 --- a/node/impl/full/state.go +++ b/node/impl/full/state.go @@ -1226,3 +1226,43 @@ 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 { + msg, err := a.StateSearchMsg(ctx, inputMsg) + if err != nil { + return nil, xerrors.Errorf("searching for msg %s: %w", inputMsg, err) + } + + ts, err = a.Chain.GetTipSetFromKey(msg.TipSet) + if err != nil { + return nil, xerrors.Errorf("loading tipset %s: %w", msg.TipSet, err) + } + } + + m, r, err := a.StateManager.Replay(ctx, ts, msg) + if err != nil { + return nil, err + } + + gasSpent := big.Sub(big.NewInt(m.GasLimit), r.GasCosts.Refund) + 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.Mul(gasSpent, m.GasFeeCap), + }, nil +} From 0edcae9e046346217c482b7d1c093d5a6dc77ac8 Mon Sep 17 00:00:00 2001 From: Aayush Rajasekaran Date: Mon, 14 Sep 2020 01:23:29 -0400 Subject: [PATCH 3/3] Fixup new command --- cli/state.go | 4 ++-- documentation/en/api-methods.md | 19 ++++++++++++------- extern/storage-sealing/upgrade_queue.go | 2 ++ node/impl/full/state.go | 23 ++++++++++++++++------- 4 files changed, 32 insertions(+), 16 deletions(-) diff --git a/cli/state.go b/cli/state.go index 7729e729a..62d751204 100644 --- a/cli/state.go +++ b/cli/state.go @@ -1344,12 +1344,12 @@ var stateMsgCostCmd = &cli.Command{ } if mgc != nil { - fmt.Printf("\nMessage CID: %d", mgc.Message) + 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("\nRefundd: %d", mgc.Refund) + fmt.Printf("\nRefund: %d", mgc.Refund) fmt.Printf("\nTotal Cost: %d", mgc.TotalCost) fmt.Printf("\nMiner Penalty: %d", mgc.MinerPenalty) } else { diff --git a/documentation/en/api-methods.md b/documentation/en/api-methods.md index ec298d635..5bba832df 100644 --- a/documentation/en/api-methods.md +++ b/documentation/en/api-methods.md @@ -3743,7 +3743,15 @@ Inputs: [ { "/": "bafy2bzacea3wsdh6y3a36tb3skempjoxqpuyompjbmfeyf34fi3uy6uue42v4" - } + }, + [ + { + "/": "bafy2bzacea3wsdh6y3a36tb3skempjoxqpuyompjbmfeyf34fi3uy6uue42v4" + }, + { + "/": "bafy2bzacebp3shtrn43k7g3unredz7fxn4gj533d3o43tqn2p2ipxxhrvchve" + } + ] ] ``` @@ -3753,16 +3761,13 @@ Response: "Message": { "/": "bafy2bzacea3wsdh6y3a36tb3skempjoxqpuyompjbmfeyf34fi3uy6uue42v4" }, - "Receipt": { - "ExitCode": 0, - "Return": "Ynl0ZSBhcnJheQ==", - "GasUsed": 9 - }, + "GasUsed": "0", "BaseFeeBurn": "0", "OverEstimationBurn": "0", "MinerPenalty": "0", "MinerTip": "0", - "Refund": "0" + "Refund": "0", + "TotalCost": "0" } ``` diff --git a/extern/storage-sealing/upgrade_queue.go b/extern/storage-sealing/upgrade_queue.go index 650fdc83d..af2d1827d 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/impl/full/state.go b/node/impl/full/state.go index 1fb078001..c37ab9c3d 100644 --- a/node/impl/full/state.go +++ b/node/impl/full/state.go @@ -1238,15 +1238,25 @@ func (a *StateAPI) StateMsgGasCost(ctx context.Context, inputMsg cid.Cid, tsk ty return nil, xerrors.Errorf("loading tipset %s: %w", tsk, err) } } else { - msg, err := a.StateSearchMsg(ctx, inputMsg) + mlkp, err := a.StateSearchMsg(ctx, inputMsg) if err != nil { return nil, xerrors.Errorf("searching for msg %s: %w", inputMsg, err) } - - ts, err = a.Chain.GetTipSetFromKey(msg.TipSet) - if err != nil { - return nil, xerrors.Errorf("loading tipset %s: %w", msg.TipSet, 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) @@ -1254,7 +1264,6 @@ func (a *StateAPI) StateMsgGasCost(ctx context.Context, inputMsg cid.Cid, tsk ty return nil, err } - gasSpent := big.Sub(big.NewInt(m.GasLimit), r.GasCosts.Refund) return &api.MsgGasCost{ Message: msg, GasUsed: big.NewInt(r.GasUsed), @@ -1263,6 +1272,6 @@ func (a *StateAPI) StateMsgGasCost(ctx context.Context, inputMsg cid.Cid, tsk ty MinerPenalty: r.GasCosts.MinerPenalty, MinerTip: r.GasCosts.MinerTip, Refund: r.GasCosts.Refund, - TotalCost: big.Mul(gasSpent, m.GasFeeCap), + TotalCost: big.Sub(m.RequiredFunds(), r.GasCosts.Refund), }, nil }