Merge pull request #4429 from filecoin-project/asr/state-apis
Improve StateMsg APIs
This commit is contained in:
commit
0775c6c9d5
@ -315,12 +315,13 @@ type FullNode interface {
|
|||||||
|
|
||||||
// MethodGroup: State
|
// MethodGroup: State
|
||||||
// The State methods are used to query, inspect, and interact with chain state.
|
// The State methods are used to query, inspect, and interact with chain state.
|
||||||
// All methods take a TipSetKey as a parameter. The state looked up is the state at that tipset.
|
// Most methods take a TipSetKey as a parameter. The state looked up is the state at that tipset.
|
||||||
// A nil TipSetKey can be provided as a param, this will cause the heaviest tipset in the chain to be used.
|
// A nil TipSetKey can be provided as a param, this will cause the heaviest tipset in the chain to be used.
|
||||||
|
|
||||||
// StateCall runs the given message and returns its result without any persisted changes.
|
// StateCall runs the given message and returns its result without any persisted changes.
|
||||||
StateCall(context.Context, *types.Message, types.TipSetKey) (*InvocResult, error)
|
StateCall(context.Context, *types.Message, types.TipSetKey) (*InvocResult, error)
|
||||||
// StateReplay returns the result of executing the indicated message, assuming it was executed in the indicated tipset.
|
// StateReplay replays a given message, assuming it was included in a block in the specified tipset.
|
||||||
|
// If no tipset key is provided, the appropriate tipset is looked up.
|
||||||
StateReplay(context.Context, types.TipSetKey, cid.Cid) (*InvocResult, error)
|
StateReplay(context.Context, types.TipSetKey, cid.Cid) (*InvocResult, error)
|
||||||
// StateGetActor returns the indicated actor's nonce and balance.
|
// StateGetActor returns the indicated actor's nonce and balance.
|
||||||
StateGetActor(ctx context.Context, actor address.Address, tsk types.TipSetKey) (*types.Actor, error)
|
StateGetActor(ctx context.Context, actor address.Address, tsk types.TipSetKey) (*types.Actor, error)
|
||||||
@ -370,8 +371,6 @@ type FullNode interface {
|
|||||||
StateSectorPartition(ctx context.Context, maddr address.Address, sectorNumber abi.SectorNumber, tok types.TipSetKey) (*miner.SectorLocation, error)
|
StateSectorPartition(ctx context.Context, maddr address.Address, sectorNumber abi.SectorNumber, tok types.TipSetKey) (*miner.SectorLocation, error)
|
||||||
// StateSearchMsg searches for a message in the chain, and returns its receipt and the tipset where it was executed
|
// 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)
|
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
|
// 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.
|
// message arrives on chain, and gets to the indicated confidence depth.
|
||||||
StateWaitMsg(ctx context.Context, cid cid.Cid, confidence uint64) (*MsgLookup, error)
|
StateWaitMsg(ctx context.Context, cid cid.Cid, confidence uint64) (*MsgLookup, error)
|
||||||
@ -740,6 +739,7 @@ type InvocResult struct {
|
|||||||
MsgCid cid.Cid
|
MsgCid cid.Cid
|
||||||
Msg *types.Message
|
Msg *types.Message
|
||||||
MsgRct *types.MessageReceipt
|
MsgRct *types.MessageReceipt
|
||||||
|
GasCost MsgGasCost
|
||||||
ExecutionTrace types.ExecutionTrace
|
ExecutionTrace types.ExecutionTrace
|
||||||
Error string
|
Error string
|
||||||
Duration time.Duration
|
Duration time.Duration
|
||||||
|
@ -191,7 +191,6 @@ type FullNodeStruct struct {
|
|||||||
StateReplay func(context.Context, types.TipSetKey, cid.Cid) (*api.InvocResult, error) `perm:"read"`
|
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"`
|
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"`
|
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"`
|
StateWaitMsg func(ctx context.Context, cid cid.Cid, confidence uint64) (*api.MsgLookup, error) `perm:"read"`
|
||||||
StateWaitMsgLimited func(context.Context, cid.Cid, uint64, abi.ChainEpoch) (*api.MsgLookup, error) `perm:"read"`
|
StateWaitMsgLimited func(context.Context, cid.Cid, uint64, abi.ChainEpoch) (*api.MsgLookup, error) `perm:"read"`
|
||||||
StateSearchMsg func(context.Context, cid.Cid) (*api.MsgLookup, error) `perm:"read"`
|
StateSearchMsg func(context.Context, cid.Cid) (*api.MsgLookup, error) `perm:"read"`
|
||||||
@ -892,10 +891,6 @@ func (c *FullNodeStruct) StateReadState(ctx context.Context, addr address.Addres
|
|||||||
return c.Internal.StateReadState(ctx, addr, tsk)
|
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) {
|
func (c *FullNodeStruct) StateWaitMsg(ctx context.Context, msgc cid.Cid, confidence uint64) (*api.MsgLookup, error) {
|
||||||
return c.Internal.StateWaitMsg(ctx, msgc, confidence)
|
return c.Internal.StateWaitMsg(ctx, msgc, confidence)
|
||||||
}
|
}
|
||||||
|
@ -232,6 +232,7 @@ func (sm *StateManager) CallWithGas(ctx context.Context, msg *types.Message, pri
|
|||||||
MsgCid: msg.Cid(),
|
MsgCid: msg.Cid(),
|
||||||
Msg: msg,
|
Msg: msg,
|
||||||
MsgRct: &ret.MessageReceipt,
|
MsgRct: &ret.MessageReceipt,
|
||||||
|
GasCost: MakeMsgGasCost(msg, ret),
|
||||||
ExecutionTrace: ret.ExecutionTrace,
|
ExecutionTrace: ret.ExecutionTrace,
|
||||||
Error: errs,
|
Error: errs,
|
||||||
Duration: ret.Duration,
|
Duration: ret.Duration,
|
||||||
|
@ -498,7 +498,7 @@ func UpgradeFaucetBurnRecovery(ctx context.Context, sm *StateManager, cb ExecCal
|
|||||||
Subcalls: subcalls,
|
Subcalls: subcalls,
|
||||||
},
|
},
|
||||||
Duration: 0,
|
Duration: 0,
|
||||||
GasCosts: vm.ZeroGasOutputs(),
|
GasCosts: nil,
|
||||||
}); err != nil {
|
}); err != nil {
|
||||||
return cid.Undef, xerrors.Errorf("recording transfers: %w", err)
|
return cid.Undef, xerrors.Errorf("recording transfers: %w", err)
|
||||||
}
|
}
|
||||||
@ -799,7 +799,7 @@ func splitGenesisMultisig(ctx context.Context, cb ExecCallback, addr address.Add
|
|||||||
Subcalls: subcalls,
|
Subcalls: subcalls,
|
||||||
},
|
},
|
||||||
Duration: 0,
|
Duration: 0,
|
||||||
GasCosts: vm.ZeroGasOutputs(),
|
GasCosts: nil,
|
||||||
}); err != nil {
|
}); err != nil {
|
||||||
return xerrors.Errorf("recording transfers: %w", err)
|
return xerrors.Errorf("recording transfers: %w", err)
|
||||||
}
|
}
|
||||||
|
@ -209,6 +209,9 @@ func traceFunc(trace *[]*api.InvocResult) func(mcid cid.Cid, msg *types.Message,
|
|||||||
if ret.ActorErr != nil {
|
if ret.ActorErr != nil {
|
||||||
ir.Error = ret.ActorErr.Error()
|
ir.Error = ret.ActorErr.Error()
|
||||||
}
|
}
|
||||||
|
if ret.GasCosts != nil {
|
||||||
|
ir.GasCost = MakeMsgGasCost(msg, ret)
|
||||||
|
}
|
||||||
*trace = append(*trace, ir)
|
*trace = append(*trace, ir)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
@ -701,3 +701,16 @@ func CheckTotalFIL(ctx context.Context, sm *StateManager, ts *types.TipSet) (abi
|
|||||||
|
|
||||||
return sum, nil
|
return sum, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func MakeMsgGasCost(msg *types.Message, ret *vm.ApplyRet) api.MsgGasCost {
|
||||||
|
return api.MsgGasCost{
|
||||||
|
Message: msg.Cid(),
|
||||||
|
GasUsed: big.NewInt(ret.GasUsed),
|
||||||
|
BaseFeeBurn: ret.GasCosts.BaseFeeBurn,
|
||||||
|
OverEstimationBurn: ret.GasCosts.OverEstimationBurn,
|
||||||
|
MinerPenalty: ret.GasCosts.MinerPenalty,
|
||||||
|
MinerTip: ret.GasCosts.MinerTip,
|
||||||
|
Refund: ret.GasCosts.Refund,
|
||||||
|
TotalCost: big.Sub(msg.RequiredFunds(), ret.GasCosts.Refund),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -214,7 +214,7 @@ type ApplyRet struct {
|
|||||||
ActorErr aerrors.ActorError
|
ActorErr aerrors.ActorError
|
||||||
ExecutionTrace types.ExecutionTrace
|
ExecutionTrace types.ExecutionTrace
|
||||||
Duration time.Duration
|
Duration time.Duration
|
||||||
GasCosts GasOutputs
|
GasCosts *GasOutputs
|
||||||
}
|
}
|
||||||
|
|
||||||
func (vm *VM) send(ctx context.Context, msg *types.Message, parent *Runtime,
|
func (vm *VM) send(ctx context.Context, msg *types.Message, parent *Runtime,
|
||||||
@ -361,7 +361,7 @@ func (vm *VM) ApplyImplicitMessage(ctx context.Context, msg *types.Message) (*Ap
|
|||||||
},
|
},
|
||||||
ActorErr: actorErr,
|
ActorErr: actorErr,
|
||||||
ExecutionTrace: rt.executionTrace,
|
ExecutionTrace: rt.executionTrace,
|
||||||
GasCosts: GasOutputs{},
|
GasCosts: nil,
|
||||||
Duration: time.Since(start),
|
Duration: time.Since(start),
|
||||||
}, actorErr
|
}, actorErr
|
||||||
}
|
}
|
||||||
@ -397,7 +397,7 @@ func (vm *VM) ApplyMessage(ctx context.Context, cmsg types.ChainMsg) (*ApplyRet,
|
|||||||
ExitCode: exitcode.SysErrOutOfGas,
|
ExitCode: exitcode.SysErrOutOfGas,
|
||||||
GasUsed: 0,
|
GasUsed: 0,
|
||||||
},
|
},
|
||||||
GasCosts: gasOutputs,
|
GasCosts: &gasOutputs,
|
||||||
Duration: time.Since(start),
|
Duration: time.Since(start),
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
@ -417,7 +417,7 @@ func (vm *VM) ApplyMessage(ctx context.Context, cmsg types.ChainMsg) (*ApplyRet,
|
|||||||
GasUsed: 0,
|
GasUsed: 0,
|
||||||
},
|
},
|
||||||
ActorErr: aerrors.Newf(exitcode.SysErrSenderInvalid, "actor not found: %s", msg.From),
|
ActorErr: aerrors.Newf(exitcode.SysErrSenderInvalid, "actor not found: %s", msg.From),
|
||||||
GasCosts: gasOutputs,
|
GasCosts: &gasOutputs,
|
||||||
Duration: time.Since(start),
|
Duration: time.Since(start),
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
@ -434,7 +434,7 @@ func (vm *VM) ApplyMessage(ctx context.Context, cmsg types.ChainMsg) (*ApplyRet,
|
|||||||
GasUsed: 0,
|
GasUsed: 0,
|
||||||
},
|
},
|
||||||
ActorErr: aerrors.Newf(exitcode.SysErrSenderInvalid, "send from not account actor: %s", fromActor.Code),
|
ActorErr: aerrors.Newf(exitcode.SysErrSenderInvalid, "send from not account actor: %s", fromActor.Code),
|
||||||
GasCosts: gasOutputs,
|
GasCosts: &gasOutputs,
|
||||||
Duration: time.Since(start),
|
Duration: time.Since(start),
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
@ -450,7 +450,7 @@ func (vm *VM) ApplyMessage(ctx context.Context, cmsg types.ChainMsg) (*ApplyRet,
|
|||||||
ActorErr: aerrors.Newf(exitcode.SysErrSenderStateInvalid,
|
ActorErr: aerrors.Newf(exitcode.SysErrSenderStateInvalid,
|
||||||
"actor nonce invalid: msg:%d != state:%d", msg.Nonce, fromActor.Nonce),
|
"actor nonce invalid: msg:%d != state:%d", msg.Nonce, fromActor.Nonce),
|
||||||
|
|
||||||
GasCosts: gasOutputs,
|
GasCosts: &gasOutputs,
|
||||||
Duration: time.Since(start),
|
Duration: time.Since(start),
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
@ -466,7 +466,7 @@ func (vm *VM) ApplyMessage(ctx context.Context, cmsg types.ChainMsg) (*ApplyRet,
|
|||||||
},
|
},
|
||||||
ActorErr: aerrors.Newf(exitcode.SysErrSenderStateInvalid,
|
ActorErr: aerrors.Newf(exitcode.SysErrSenderStateInvalid,
|
||||||
"actor balance less than needed: %s < %s", types.FIL(fromActor.Balance), types.FIL(gascost)),
|
"actor balance less than needed: %s < %s", types.FIL(fromActor.Balance), types.FIL(gascost)),
|
||||||
GasCosts: gasOutputs,
|
GasCosts: &gasOutputs,
|
||||||
Duration: time.Since(start),
|
Duration: time.Since(start),
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
@ -560,7 +560,7 @@ func (vm *VM) ApplyMessage(ctx context.Context, cmsg types.ChainMsg) (*ApplyRet,
|
|||||||
},
|
},
|
||||||
ActorErr: actorErr,
|
ActorErr: actorErr,
|
||||||
ExecutionTrace: rt.executionTrace,
|
ExecutionTrace: rt.executionTrace,
|
||||||
GasCosts: gasOutputs,
|
GasCosts: &gasOutputs,
|
||||||
Duration: time.Since(start),
|
Duration: time.Since(start),
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
144
cli/state.go
144
cli/state.go
@ -60,7 +60,7 @@ var stateCmd = &cli.Command{
|
|||||||
stateSectorCmd,
|
stateSectorCmd,
|
||||||
stateGetActorCmd,
|
stateGetActorCmd,
|
||||||
stateLookupIDCmd,
|
stateLookupIDCmd,
|
||||||
stateReplaySetCmd,
|
stateReplayCmd,
|
||||||
stateSectorSizeCmd,
|
stateSectorSizeCmd,
|
||||||
stateReadStateCmd,
|
stateReadStateCmd,
|
||||||
stateListMessagesCmd,
|
stateListMessagesCmd,
|
||||||
@ -69,7 +69,6 @@ var stateCmd = &cli.Command{
|
|||||||
stateGetDealSetCmd,
|
stateGetDealSetCmd,
|
||||||
stateWaitMsgCmd,
|
stateWaitMsgCmd,
|
||||||
stateSearchMsgCmd,
|
stateSearchMsgCmd,
|
||||||
stateMsgCostCmd,
|
|
||||||
stateMinerInfo,
|
stateMinerInfo,
|
||||||
stateMarketCmd,
|
stateMarketCmd,
|
||||||
stateExecTraceCmd,
|
stateExecTraceCmd,
|
||||||
@ -384,20 +383,27 @@ var stateExecTraceCmd = &cli.Command{
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
var stateReplaySetCmd = &cli.Command{
|
var stateReplayCmd = &cli.Command{
|
||||||
Name: "replay",
|
Name: "replay",
|
||||||
Usage: "Replay a particular message within a tipset",
|
Usage: "Replay a particular message",
|
||||||
ArgsUsage: "[tipsetKey messageCid]",
|
ArgsUsage: "<messageCid>",
|
||||||
|
Flags: []cli.Flag{
|
||||||
|
&cli.BoolFlag{
|
||||||
|
Name: "show-trace",
|
||||||
|
Usage: "print out full execution trace for given message",
|
||||||
|
},
|
||||||
|
&cli.BoolFlag{
|
||||||
|
Name: "detailed-gas",
|
||||||
|
Usage: "print out detailed gas costs for given message",
|
||||||
|
},
|
||||||
|
},
|
||||||
Action: func(cctx *cli.Context) error {
|
Action: func(cctx *cli.Context) error {
|
||||||
if cctx.Args().Len() < 1 {
|
if cctx.Args().Len() != 1 {
|
||||||
fmt.Println("usage: [tipset] <message cid>")
|
fmt.Println("must provide cid of message to replay")
|
||||||
fmt.Println("The last cid passed will be used as the message CID")
|
|
||||||
fmt.Println("All preceding ones will be used as the tipset")
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
args := cctx.Args().Slice()
|
mcid, err := cid.Decode(cctx.Args().First())
|
||||||
mcid, err := cid.Decode(args[len(args)-1])
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("message cid was invalid: %s", err)
|
return fmt.Errorf("message cid was invalid: %s", err)
|
||||||
}
|
}
|
||||||
@ -410,52 +416,7 @@ var stateReplaySetCmd = &cli.Command{
|
|||||||
|
|
||||||
ctx := ReqContext(cctx)
|
ctx := ReqContext(cctx)
|
||||||
|
|
||||||
var ts *types.TipSet
|
res, err := fapi.StateReplay(ctx, types.EmptyTSK, mcid)
|
||||||
{
|
|
||||||
var tscids []cid.Cid
|
|
||||||
for _, s := range args[:len(args)-1] {
|
|
||||||
c, err := cid.Decode(s)
|
|
||||||
if err != nil {
|
|
||||||
return fmt.Errorf("tipset cid was invalid: %s", err)
|
|
||||||
}
|
|
||||||
tscids = append(tscids, c)
|
|
||||||
}
|
|
||||||
|
|
||||||
if len(tscids) > 0 {
|
|
||||||
var headers []*types.BlockHeader
|
|
||||||
for _, c := range tscids {
|
|
||||||
h, err := fapi.ChainGetBlock(ctx, c)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
headers = append(headers, h)
|
|
||||||
}
|
|
||||||
|
|
||||||
ts, err = types.NewTipSet(headers)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
var r *api.MsgLookup
|
|
||||||
r, err = fapi.StateWaitMsg(ctx, mcid, build.MessageConfidence)
|
|
||||||
if err != nil {
|
|
||||||
return xerrors.Errorf("finding message in chain: %w", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
childTs, err := fapi.ChainGetTipSet(ctx, r.TipSet)
|
|
||||||
if err != nil {
|
|
||||||
return xerrors.Errorf("loading tipset: %w", err)
|
|
||||||
}
|
|
||||||
ts, err = fapi.ChainGetTipSet(ctx, childTs.Parents())
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
res, err := fapi.StateReplay(ctx, ts.Key(), mcid)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return xerrors.Errorf("replay call failed: %w", err)
|
return xerrors.Errorf("replay call failed: %w", err)
|
||||||
}
|
}
|
||||||
@ -464,10 +425,25 @@ var stateReplaySetCmd = &cli.Command{
|
|||||||
fmt.Printf("Exit code: %d\n", res.MsgRct.ExitCode)
|
fmt.Printf("Exit code: %d\n", res.MsgRct.ExitCode)
|
||||||
fmt.Printf("Return: %x\n", res.MsgRct.Return)
|
fmt.Printf("Return: %x\n", res.MsgRct.Return)
|
||||||
fmt.Printf("Gas Used: %d\n", res.MsgRct.GasUsed)
|
fmt.Printf("Gas Used: %d\n", res.MsgRct.GasUsed)
|
||||||
|
|
||||||
|
if cctx.Bool("detailed-gas") {
|
||||||
|
fmt.Printf("Base Fee Burn: %d\n", res.GasCost.BaseFeeBurn)
|
||||||
|
fmt.Printf("Overestimaton Burn: %d\n", res.GasCost.OverEstimationBurn)
|
||||||
|
fmt.Printf("Miner Penalty: %d\n", res.GasCost.MinerPenalty)
|
||||||
|
fmt.Printf("Miner Tip: %d\n", res.GasCost.MinerTip)
|
||||||
|
fmt.Printf("Refund: %d\n", res.GasCost.Refund)
|
||||||
|
}
|
||||||
|
fmt.Printf("Total Message Cost: %d\n", res.GasCost.TotalCost)
|
||||||
|
|
||||||
if res.MsgRct.ExitCode != 0 {
|
if res.MsgRct.ExitCode != 0 {
|
||||||
fmt.Printf("Error message: %q\n", res.Error)
|
fmt.Printf("Error message: %q\n", res.Error)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if cctx.Bool("show-trace") {
|
||||||
|
fmt.Printf("%s\t%s\t%s\t%d\t%x\t%d\t%x\n", res.Msg.From, res.Msg.To, res.Msg.Value, res.Msg.Method, res.Msg.Params, res.MsgRct.ExitCode, res.MsgRct.Return)
|
||||||
|
printInternalExecutions("\t", res.ExecutionTrace.Subcalls)
|
||||||
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
@ -1424,60 +1400,6 @@ 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{
|
var stateCallCmd = &cli.Command{
|
||||||
Name: "call",
|
Name: "call",
|
||||||
Usage: "Invoke a method on an actor locally",
|
Usage: "Invoke a method on an actor locally",
|
||||||
|
@ -156,7 +156,6 @@
|
|||||||
* [StateMinerRecoveries](#StateMinerRecoveries)
|
* [StateMinerRecoveries](#StateMinerRecoveries)
|
||||||
* [StateMinerSectorCount](#StateMinerSectorCount)
|
* [StateMinerSectorCount](#StateMinerSectorCount)
|
||||||
* [StateMinerSectors](#StateMinerSectors)
|
* [StateMinerSectors](#StateMinerSectors)
|
||||||
* [StateMsgGasCost](#StateMsgGasCost)
|
|
||||||
* [StateNetworkName](#StateNetworkName)
|
* [StateNetworkName](#StateNetworkName)
|
||||||
* [StateNetworkVersion](#StateNetworkVersion)
|
* [StateNetworkVersion](#StateNetworkVersion)
|
||||||
* [StateReadState](#StateReadState)
|
* [StateReadState](#StateReadState)
|
||||||
@ -2989,7 +2988,7 @@ Response:
|
|||||||
|
|
||||||
## State
|
## State
|
||||||
The State methods are used to query, inspect, and interact with chain state.
|
The State methods are used to query, inspect, and interact with chain state.
|
||||||
All methods take a TipSetKey as a parameter. The state looked up is the state at that tipset.
|
Most methods take a TipSetKey as a parameter. The state looked up is the state at that tipset.
|
||||||
A nil TipSetKey can be provided as a param, this will cause the heaviest tipset in the chain to be used.
|
A nil TipSetKey can be provided as a param, this will cause the heaviest tipset in the chain to be used.
|
||||||
|
|
||||||
|
|
||||||
@ -3100,6 +3099,18 @@ Response:
|
|||||||
"Return": "Ynl0ZSBhcnJheQ==",
|
"Return": "Ynl0ZSBhcnJheQ==",
|
||||||
"GasUsed": 9
|
"GasUsed": 9
|
||||||
},
|
},
|
||||||
|
"GasCost": {
|
||||||
|
"Message": {
|
||||||
|
"/": "bafy2bzacea3wsdh6y3a36tb3skempjoxqpuyompjbmfeyf34fi3uy6uue42v4"
|
||||||
|
},
|
||||||
|
"GasUsed": "0",
|
||||||
|
"BaseFeeBurn": "0",
|
||||||
|
"OverEstimationBurn": "0",
|
||||||
|
"MinerPenalty": "0",
|
||||||
|
"MinerTip": "0",
|
||||||
|
"Refund": "0",
|
||||||
|
"TotalCost": "0"
|
||||||
|
},
|
||||||
"ExecutionTrace": {
|
"ExecutionTrace": {
|
||||||
"Msg": {
|
"Msg": {
|
||||||
"Version": 42,
|
"Version": 42,
|
||||||
@ -3974,45 +3985,6 @@ Inputs:
|
|||||||
|
|
||||||
Response: `null`
|
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
|
||||||
StateNetworkName returns the name of the network the node is synced to
|
StateNetworkName returns the name of the network the node is synced to
|
||||||
|
|
||||||
@ -4075,7 +4047,8 @@ Response:
|
|||||||
```
|
```
|
||||||
|
|
||||||
### StateReplay
|
### StateReplay
|
||||||
StateReplay returns the result of executing the indicated message, assuming it was executed in the indicated tipset.
|
StateReplay replays a given message, assuming it was included in a block in the specified tipset.
|
||||||
|
If no tipset key is provided, the appropriate tipset is looked up.
|
||||||
|
|
||||||
|
|
||||||
Perms: read
|
Perms: read
|
||||||
@ -4123,6 +4096,18 @@ Response:
|
|||||||
"Return": "Ynl0ZSBhcnJheQ==",
|
"Return": "Ynl0ZSBhcnJheQ==",
|
||||||
"GasUsed": 9
|
"GasUsed": 9
|
||||||
},
|
},
|
||||||
|
"GasCost": {
|
||||||
|
"Message": {
|
||||||
|
"/": "bafy2bzacea3wsdh6y3a36tb3skempjoxqpuyompjbmfeyf34fi3uy6uue42v4"
|
||||||
|
},
|
||||||
|
"GasUsed": "0",
|
||||||
|
"BaseFeeBurn": "0",
|
||||||
|
"OverEstimationBurn": "0",
|
||||||
|
"MinerPenalty": "0",
|
||||||
|
"MinerTip": "0",
|
||||||
|
"Refund": "0",
|
||||||
|
"TotalCost": "0"
|
||||||
|
},
|
||||||
"ExecutionTrace": {
|
"ExecutionTrace": {
|
||||||
"Msg": {
|
"Msg": {
|
||||||
"Version": 42,
|
"Version": 42,
|
||||||
|
@ -347,11 +347,33 @@ func (a *StateAPI) StateCall(ctx context.Context, msg *types.Message, tsk types.
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (a *StateAPI) StateReplay(ctx context.Context, tsk types.TipSetKey, mc cid.Cid) (*api.InvocResult, error) {
|
func (a *StateAPI) StateReplay(ctx context.Context, tsk types.TipSetKey, mc cid.Cid) (*api.InvocResult, error) {
|
||||||
ts, err := a.Chain.GetTipSetFromKey(tsk)
|
msgToReplay := mc
|
||||||
|
var ts *types.TipSet
|
||||||
|
if tsk == types.EmptyTSK {
|
||||||
|
mlkp, err := a.StateSearchMsg(ctx, mc)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, xerrors.Errorf("loading tipset %s: %w", tsk, err)
|
return nil, xerrors.Errorf("searching for msg %s: %w", mc, err)
|
||||||
}
|
}
|
||||||
m, r, err := a.StateManager.Replay(ctx, ts, mc)
|
if mlkp == nil {
|
||||||
|
return nil, xerrors.Errorf("didn't find msg %s", mc)
|
||||||
|
}
|
||||||
|
|
||||||
|
msgToReplay = mlkp.Message
|
||||||
|
|
||||||
|
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)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
ts = a.Chain.GetHeaviestTipSet()
|
||||||
|
}
|
||||||
|
|
||||||
|
m, r, err := a.StateManager.Replay(ctx, ts, msgToReplay)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@ -362,9 +384,10 @@ func (a *StateAPI) StateReplay(ctx context.Context, tsk types.TipSetKey, mc cid.
|
|||||||
}
|
}
|
||||||
|
|
||||||
return &api.InvocResult{
|
return &api.InvocResult{
|
||||||
MsgCid: mc,
|
MsgCid: msgToReplay,
|
||||||
Msg: m,
|
Msg: m,
|
||||||
MsgRct: &r.MessageReceipt,
|
MsgRct: &r.MessageReceipt,
|
||||||
|
GasCost: stmgr.MakeMsgGasCost(m, r),
|
||||||
ExecutionTrace: r.ExecutionTrace,
|
ExecutionTrace: r.ExecutionTrace,
|
||||||
Error: errstr,
|
Error: errstr,
|
||||||
Duration: r.Duration,
|
Duration: r.Duration,
|
||||||
@ -1266,52 +1289,3 @@ func (a *StateAPI) StateNetworkVersion(ctx context.Context, tsk types.TipSetKey)
|
|||||||
|
|
||||||
return a.StateManager.GetNtwkVersion(ctx, ts.Height()), nil
|
return a.StateManager.GetNtwkVersion(ctx, ts.Height()), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
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
|
|
||||||
}
|
|
||||||
|
Loading…
Reference in New Issue
Block a user