Remove StateTransplant, modify StateReplay

This commit is contained in:
Aayush Rajasekaran 2020-10-15 22:45:11 -04:00
parent 89f46cb5cc
commit 2fd4a97698
6 changed files with 46 additions and 257 deletions

View File

@ -320,10 +320,9 @@ type FullNode interface {
// 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)
// StateTransplant 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.
StateTransplant(context.Context, types.TipSetKey, cid.Cid) (*InvocResult, error) // If no tipset key is provided, the appropriate tipset is looked up.
// StateReplay searches for where the given message was executed, and replays it in that tipset. StateReplay(context.Context, types.TipSetKey, cid.Cid) (*InvocResult, error)
StateReplay(context.Context, 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)
// StateReadState returns the indicated actor's state. // StateReadState returns the indicated actor's state.

View File

@ -188,8 +188,7 @@ type FullNodeStruct struct {
StateSectorExpiration func(context.Context, address.Address, abi.SectorNumber, types.TipSetKey) (*miner.SectorExpiration, error) `perm:"read"` StateSectorExpiration func(context.Context, address.Address, abi.SectorNumber, types.TipSetKey) (*miner.SectorExpiration, error) `perm:"read"`
StateSectorPartition func(context.Context, address.Address, abi.SectorNumber, types.TipSetKey) (*miner.SectorLocation, error) `perm:"read"` StateSectorPartition func(context.Context, address.Address, abi.SectorNumber, types.TipSetKey) (*miner.SectorLocation, error) `perm:"read"`
StateCall func(context.Context, *types.Message, types.TipSetKey) (*api.InvocResult, error) `perm:"read"` StateCall func(context.Context, *types.Message, types.TipSetKey) (*api.InvocResult, error) `perm:"read"`
StateTransplant 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"`
StateReplay func(context.Context, 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"`
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"`
@ -880,12 +879,8 @@ func (c *FullNodeStruct) StateCall(ctx context.Context, msg *types.Message, tsk
return c.Internal.StateCall(ctx, msg, tsk) return c.Internal.StateCall(ctx, msg, tsk)
} }
func (c *FullNodeStruct) StateTransplant(ctx context.Context, tsk types.TipSetKey, mc cid.Cid) (*api.InvocResult, error) { func (c *FullNodeStruct) StateReplay(ctx context.Context, tsk types.TipSetKey, mc cid.Cid) (*api.InvocResult, error) {
return c.Internal.StateTransplant(ctx, tsk, mc) return c.Internal.StateReplay(ctx, tsk, mc)
}
func (c *FullNodeStruct) StateReplay(ctx context.Context, mc cid.Cid) (*api.InvocResult, error) {
return c.Internal.StateReplay(ctx, mc)
} }
func (c *FullNodeStruct) StateGetActor(ctx context.Context, actor address.Address, tsk types.TipSetKey) (*types.Actor, error) { func (c *FullNodeStruct) StateGetActor(ctx context.Context, actor address.Address, tsk types.TipSetKey) (*types.Actor, error) {

View File

@ -60,7 +60,6 @@ var stateCmd = &cli.Command{
stateSectorCmd, stateSectorCmd,
stateGetActorCmd, stateGetActorCmd,
stateLookupIDCmd, stateLookupIDCmd,
stateTransplantCmd,
stateReplayCmd, stateReplayCmd,
stateSectorSizeCmd, stateSectorSizeCmd,
stateReadStateCmd, stateReadStateCmd,
@ -384,108 +383,6 @@ var stateExecTraceCmd = &cli.Command{
}, },
} }
var stateTransplantCmd = &cli.Command{
Name: "transplant",
Usage: "Play a particular message within a tipset",
ArgsUsage: "[tipsetKey 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 {
if cctx.Args().Len() < 1 {
fmt.Println("usage: [tipset] <message cid>")
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
}
args := cctx.Args().Slice()
mcid, err := cid.Decode(args[len(args)-1])
if err != nil {
return fmt.Errorf("message cid was invalid: %s", err)
}
fapi, closer, err := GetFullNodeAPI(cctx)
if err != nil {
return err
}
defer closer()
ctx := ReqContext(cctx)
var ts *types.TipSet
{
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 {
ts, err = fapi.ChainHead(ctx)
if err != nil {
return err
}
}
}
res, err := fapi.StateTransplant(ctx, ts.Key(), mcid)
if err != nil {
return xerrors.Errorf("transplant call failed: %w", err)
}
fmt.Println("Transplant receipt:")
fmt.Printf("Exit code: %d\n", res.MsgRct.ExitCode)
fmt.Printf("Return: %x\n", res.MsgRct.Return)
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 {
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
},
}
var stateReplayCmd = &cli.Command{ var stateReplayCmd = &cli.Command{
Name: "replay", Name: "replay",
Usage: "Replay a particular message", Usage: "Replay a particular message",
@ -519,7 +416,7 @@ var stateReplayCmd = &cli.Command{
ctx := ReqContext(cctx) ctx := ReqContext(cctx)
res, err := fapi.StateReplay(ctx, mcid) res, err := fapi.StateReplay(ctx, types.EmptyTSK, mcid)
if err != nil { if err != nil {
return xerrors.Errorf("replay call failed: %w", err) return xerrors.Errorf("replay call failed: %w", err)
} }

View File

@ -165,7 +165,6 @@
* [StateSectorGetInfo](#StateSectorGetInfo) * [StateSectorGetInfo](#StateSectorGetInfo)
* [StateSectorPartition](#StateSectorPartition) * [StateSectorPartition](#StateSectorPartition)
* [StateSectorPreCommitInfo](#StateSectorPreCommitInfo) * [StateSectorPreCommitInfo](#StateSectorPreCommitInfo)
* [StateTransplant](#StateTransplant)
* [StateVMCirculatingSupplyInternal](#StateVMCirculatingSupplyInternal) * [StateVMCirculatingSupplyInternal](#StateVMCirculatingSupplyInternal)
* [StateVerifiedClientStatus](#StateVerifiedClientStatus) * [StateVerifiedClientStatus](#StateVerifiedClientStatus)
* [StateVerifiedRegistryRootKey](#StateVerifiedRegistryRootKey) * [StateVerifiedRegistryRootKey](#StateVerifiedRegistryRootKey)
@ -4048,7 +4047,8 @@ Response:
``` ```
### StateReplay ### StateReplay
StateReplay searches for where the given message was executed, and replays it in that 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
@ -4056,6 +4056,14 @@ Perms: read
Inputs: Inputs:
```json ```json
[ [
[
{
"/": "bafy2bzacea3wsdh6y3a36tb3skempjoxqpuyompjbmfeyf34fi3uy6uue42v4"
},
{
"/": "bafy2bzacebp3shtrn43k7g3unredz7fxn4gj533d3o43tqn2p2ipxxhrvchve"
}
],
{ {
"/": "bafy2bzacea3wsdh6y3a36tb3skempjoxqpuyompjbmfeyf34fi3uy6uue42v4" "/": "bafy2bzacea3wsdh6y3a36tb3skempjoxqpuyompjbmfeyf34fi3uy6uue42v4"
} }
@ -4319,98 +4327,6 @@ Response:
} }
``` ```
### StateTransplant
StateTransplant returns the result of executing the indicated message, assuming it was executed in the indicated tipset.
Perms: read
Inputs:
```json
[
[
{
"/": "bafy2bzacea3wsdh6y3a36tb3skempjoxqpuyompjbmfeyf34fi3uy6uue42v4"
},
{
"/": "bafy2bzacebp3shtrn43k7g3unredz7fxn4gj533d3o43tqn2p2ipxxhrvchve"
}
],
{
"/": "bafy2bzacea3wsdh6y3a36tb3skempjoxqpuyompjbmfeyf34fi3uy6uue42v4"
}
]
```
Response:
```json
{
"MsgCid": {
"/": "bafy2bzacea3wsdh6y3a36tb3skempjoxqpuyompjbmfeyf34fi3uy6uue42v4"
},
"Msg": {
"Version": 42,
"To": "f01234",
"From": "f01234",
"Nonce": 42,
"Value": "0",
"GasLimit": 9,
"GasFeeCap": "0",
"GasPremium": "0",
"Method": 1,
"Params": "Ynl0ZSBhcnJheQ==",
"CID": {
"/": "bafy2bzacebbpdegvr3i4cosewthysg5xkxpqfn2wfcz6mv2hmoktwbdxkax4s"
}
},
"MsgRct": {
"ExitCode": 0,
"Return": "Ynl0ZSBhcnJheQ==",
"GasUsed": 9
},
"GasCost": {
"Message": {
"/": "bafy2bzacea3wsdh6y3a36tb3skempjoxqpuyompjbmfeyf34fi3uy6uue42v4"
},
"GasUsed": "0",
"BaseFeeBurn": "0",
"OverEstimationBurn": "0",
"MinerPenalty": "0",
"MinerTip": "0",
"Refund": "0",
"TotalCost": "0"
},
"ExecutionTrace": {
"Msg": {
"Version": 42,
"To": "f01234",
"From": "f01234",
"Nonce": 42,
"Value": "0",
"GasLimit": 9,
"GasFeeCap": "0",
"GasPremium": "0",
"Method": 1,
"Params": "Ynl0ZSBhcnJheQ==",
"CID": {
"/": "bafy2bzacebbpdegvr3i4cosewthysg5xkxpqfn2wfcz6mv2hmoktwbdxkax4s"
}
},
"MsgRct": {
"ExitCode": 0,
"Return": "Ynl0ZSBhcnJheQ==",
"GasUsed": 9
},
"Error": "string value",
"Duration": 60000000000,
"GasCharges": null,
"Subcalls": null
},
"Error": "string value",
"Duration": 60000000000
}
```
### StateVMCirculatingSupplyInternal ### StateVMCirculatingSupplyInternal
StateVMCirculatingSupplyInternal returns an approximation of the circulating supply of Filecoin at the given tipset. StateVMCirculatingSupplyInternal returns an approximation of the circulating supply of Filecoin at the given tipset.
This is the value reported by the runtime interface to actors code. This is the value reported by the runtime interface to actors code.

View File

@ -26,7 +26,7 @@ class Block extends React.Component {
messages = await Promise.all(messages.map(async (msg, i) => { messages = await Promise.all(messages.map(async (msg, i) => {
if (msg.receipt.ExitCode !== 0) { if (msg.receipt.ExitCode !== 0) {
let reply = await this.props.conn.call('Filecoin.StateTransplant', [{Cids: [this.props.cid], Blocks: [header], Height: header.Height}, msg.Cid]) let reply = await this.props.conn.call('Filecoin.StateReplay', [{Cids: [this.props.cid], Blocks: [header], Height: header.Height}, msg.Cid])
if(!reply.Error) { if(!reply.Error) {
reply.Error = "reply: no error" reply.Error = "reply: no error"
} }

View File

@ -346,12 +346,34 @@ func (a *StateAPI) StateCall(ctx context.Context, msg *types.Message, tsk types.
return res, err return res, err
} }
func (a *StateAPI) StateTransplant(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
if err != nil { var ts *types.TipSet
return nil, xerrors.Errorf("loading tipset %s: %w", tsk, err) if tsk == types.EmptyTSK {
mlkp, err := a.StateSearchMsg(ctx, mc)
if err != nil {
return nil, xerrors.Errorf("searching for msg %s: %w", mc, err)
}
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, mc)
m, r, err := a.StateManager.Replay(ctx, ts, msgToReplay)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -362,47 +384,7 @@ func (a *StateAPI) StateTransplant(ctx context.Context, tsk types.TipSetKey, mc
} }
return &api.InvocResult{ return &api.InvocResult{
MsgCid: mc, MsgCid: msgToReplay,
Msg: m,
MsgRct: &r.MessageReceipt,
GasCost: stmgr.MakeMsgGasCost(m, r),
ExecutionTrace: r.ExecutionTrace,
Error: errstr,
Duration: r.Duration,
}, nil
}
func (a *StateAPI) StateReplay(ctx context.Context, mc cid.Cid) (*api.InvocResult, error) {
mlkp, err := a.StateSearchMsg(ctx, mc)
if err != nil {
return nil, xerrors.Errorf("searching for msg %s: %w", mc, err)
}
if mlkp == nil {
return nil, xerrors.Errorf("didn't find msg %s", mc)
}
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)
}
m, r, err := a.StateManager.Replay(ctx, ts, mlkp.Message)
if err != nil {
return nil, err
}
var errstr string
if r.ActorErr != nil {
errstr = r.ActorErr.Error()
}
return &api.InvocResult{
MsgCid: mlkp.Message,
Msg: m, Msg: m,
MsgRct: &r.MessageReceipt, MsgRct: &r.MessageReceipt,
GasCost: stmgr.MakeMsgGasCost(m, r), GasCost: stmgr.MakeMsgGasCost(m, r),