shed: Commad to decode messages
This commit is contained in:
parent
c81db5a21c
commit
067de4508b
@ -1291,7 +1291,7 @@ var chainDecodeParamsCmd = &cli.Command{
|
||||
return xerrors.Errorf("getting actor: %w", err)
|
||||
}
|
||||
|
||||
pstr, err := jsonParams(act.Code, abi.MethodNum(method), params)
|
||||
pstr, err := JsonParams(act.Code, abi.MethodNum(method), params)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -1211,7 +1211,7 @@ func ComputeStateHTMLTempl(w io.Writer, ts *types.TipSet, o *api.ComputeStateOut
|
||||
"GetCode": getCode,
|
||||
"GetMethod": getMethod,
|
||||
"ToFil": toFil,
|
||||
"JsonParams": jsonParams,
|
||||
"JsonParams": JsonParams,
|
||||
"JsonReturn": jsonReturn,
|
||||
"IsSlow": isSlow,
|
||||
"IsVerySlow": isVerySlow,
|
||||
@ -1298,7 +1298,7 @@ func sumGas(changes []*types.GasTrace) types.GasTrace {
|
||||
return out
|
||||
}
|
||||
|
||||
func jsonParams(code cid.Cid, method abi.MethodNum, params []byte) (string, error) {
|
||||
func JsonParams(code cid.Cid, method abi.MethodNum, params []byte) (string, error) {
|
||||
methodMeta, found := stmgr.MethodsMap[code][method]
|
||||
if !found {
|
||||
return "", fmt.Errorf("method %d not found on actor %s", method, code)
|
||||
|
@ -45,6 +45,7 @@ func main() {
|
||||
datastoreCmd,
|
||||
ledgerCmd,
|
||||
sectorsCmd,
|
||||
msgCmd,
|
||||
}
|
||||
|
||||
app := &cli.App{
|
||||
|
280
cmd/lotus-shed/msg.go
Normal file
280
cmd/lotus-shed/msg.go
Normal file
@ -0,0 +1,280 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/base64"
|
||||
"encoding/hex"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
|
||||
"github.com/fatih/color"
|
||||
|
||||
"github.com/ipfs/go-cid"
|
||||
"github.com/urfave/cli/v2"
|
||||
"golang.org/x/xerrors"
|
||||
|
||||
"github.com/filecoin-project/go-address"
|
||||
"github.com/filecoin-project/go-state-types/big"
|
||||
|
||||
"github.com/filecoin-project/lotus/chain/stmgr"
|
||||
"github.com/filecoin-project/lotus/chain/types"
|
||||
lcli "github.com/filecoin-project/lotus/cli"
|
||||
"github.com/filecoin-project/specs-actors/v2/actors/builtin/multisig"
|
||||
)
|
||||
|
||||
var msgCmd = &cli.Command{
|
||||
Name: "msg",
|
||||
Usage: "Translate message between various formats",
|
||||
ArgsUsage: "Message in any form",
|
||||
Action: func(cctx *cli.Context) error {
|
||||
if cctx.Args().Len() != 1 {
|
||||
return xerrors.Errorf("expected 1 argument")
|
||||
}
|
||||
|
||||
msg, err := messageFromString(cctx, cctx.Args().First())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
switch msg := msg.(type) {
|
||||
case *types.SignedMessage:
|
||||
return printSignedMessage(cctx, msg)
|
||||
case *types.Message:
|
||||
return printMessage(cctx, msg)
|
||||
default:
|
||||
return xerrors.Errorf("this error message can't be printed")
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
func printSignedMessage(cctx *cli.Context, smsg *types.SignedMessage) error {
|
||||
color.Green("Signed:")
|
||||
color.Blue("CID: %s\n", smsg.Cid())
|
||||
|
||||
b, err := smsg.Serialize()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
color.Magenta("HEX: %x\n", b)
|
||||
color.Blue("B64: %s\n", base64.StdEncoding.EncodeToString(b))
|
||||
jm, err := json.MarshalIndent(smsg, "", " ")
|
||||
if err != nil {
|
||||
return xerrors.Errorf("marshaling as json: %w", err)
|
||||
}
|
||||
|
||||
color.Magenta("JSON: %s\n", string(jm))
|
||||
fmt.Println()
|
||||
fmt.Println("---")
|
||||
color.Green("Signed Message Details:")
|
||||
fmt.Printf("Signature(hex): %x\n", smsg.Signature.Data)
|
||||
fmt.Printf("Signature(b64): %s\n", base64.StdEncoding.EncodeToString(smsg.Signature.Data))
|
||||
|
||||
sigtype, err := smsg.Signature.Type.Name()
|
||||
if err != nil {
|
||||
sigtype = err.Error()
|
||||
}
|
||||
fmt.Printf("Signature type: %d (%s)\n", smsg.Signature.Type, sigtype)
|
||||
|
||||
fmt.Println("-------")
|
||||
return printMessage(cctx, &smsg.Message)
|
||||
}
|
||||
|
||||
func printMessage(cctx *cli.Context, msg *types.Message) error {
|
||||
if msg.Version != 0x6d736967 {
|
||||
color.Green("Unsigned:")
|
||||
color.Yellow("CID: %s\n", msg.Cid())
|
||||
|
||||
b, err := msg.Serialize()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
color.Cyan("HEX: %x\n", b)
|
||||
color.Yellow("B64: %s\n", base64.StdEncoding.EncodeToString(b))
|
||||
|
||||
jm, err := json.MarshalIndent(msg, "", " ")
|
||||
if err != nil {
|
||||
return xerrors.Errorf("marshaling as json: %w", err)
|
||||
}
|
||||
|
||||
color.Cyan("JSON: %s\n", string(jm))
|
||||
fmt.Println()
|
||||
} else {
|
||||
color.Green("Msig Propose:")
|
||||
pp := &multisig.ProposeParams{
|
||||
To: msg.To,
|
||||
Value: msg.Value,
|
||||
Method: msg.Method,
|
||||
Params: msg.Params,
|
||||
}
|
||||
var b bytes.Buffer
|
||||
if err := pp.MarshalCBOR(&b); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
color.Cyan("HEX: %x\n", b.Bytes())
|
||||
color.Yellow("B64: %s\n", base64.StdEncoding.EncodeToString(b.Bytes()))
|
||||
jm, err := json.MarshalIndent(pp, "", " ")
|
||||
if err != nil {
|
||||
return xerrors.Errorf("marshaling as json: %w", err)
|
||||
}
|
||||
|
||||
color.Cyan("JSON: %s\n", string(jm))
|
||||
fmt.Println()
|
||||
}
|
||||
|
||||
fmt.Println("---")
|
||||
color.Green("Message Details:")
|
||||
fmt.Println("Value:", types.FIL(msg.Value))
|
||||
fmt.Println("Max Fees:", types.FIL(msg.RequiredFunds()))
|
||||
fmt.Println("Max Total Cost:", types.FIL(big.Add(msg.RequiredFunds(), msg.Value)))
|
||||
|
||||
api, closer, err := lcli.GetFullNodeAPI(cctx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
defer closer()
|
||||
ctx := lcli.ReqContext(cctx)
|
||||
|
||||
toact, err := api.StateGetActor(ctx, msg.To, types.EmptyTSK)
|
||||
if err != nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
fmt.Println("Method:", stmgr.MethodsMap[toact.Code][msg.Method].Name)
|
||||
p, err := lcli.JsonParams(toact.Code, msg.Method, msg.Params)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
fmt.Println("Params:", p)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func messageFromString(cctx *cli.Context, smsg string) (types.ChainMsg, error) {
|
||||
// a CID is least likely to just decode
|
||||
if c, err := cid.Parse(smsg); err == nil {
|
||||
return messageFromCID(cctx, c)
|
||||
}
|
||||
|
||||
// try baseX serializations next
|
||||
{
|
||||
// hex first, some hay strings may be decodable as b64
|
||||
if b, err := hex.DecodeString(smsg); err == nil {
|
||||
return messageFromBytes(cctx, b)
|
||||
}
|
||||
|
||||
// b64 next
|
||||
if b, err := base64.StdEncoding.DecodeString(smsg); err == nil {
|
||||
return messageFromBytes(cctx, b)
|
||||
}
|
||||
|
||||
// b64u??
|
||||
if b, err := base64.URLEncoding.DecodeString(smsg); err == nil {
|
||||
return messageFromBytes(cctx, b)
|
||||
}
|
||||
}
|
||||
|
||||
// maybe it's json?
|
||||
if _, err := messageFromJson(cctx, []byte(smsg)); err == nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// declare defeat
|
||||
return nil, xerrors.Errorf("couldn't decode the message")
|
||||
}
|
||||
|
||||
func messageFromJson(cctx *cli.Context, msgb []byte) (types.ChainMsg, error) {
|
||||
// Unsigned
|
||||
{
|
||||
var msg types.Message
|
||||
if err := json.Unmarshal(msgb, &msg); err == nil {
|
||||
if msg.To != address.Undef {
|
||||
return &msg, nil
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Signed
|
||||
{
|
||||
var msg types.SignedMessage
|
||||
if err := json.Unmarshal(msgb, &msg); err == nil {
|
||||
if msg.Message.To != address.Undef {
|
||||
return &msg, nil
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return nil, xerrors.New("probably not a json-serialized message")
|
||||
}
|
||||
|
||||
func messageFromBytes(cctx *cli.Context, msgb []byte) (types.ChainMsg, error) {
|
||||
// Signed
|
||||
{
|
||||
var msg types.SignedMessage
|
||||
if err := msg.UnmarshalCBOR(bytes.NewReader(msgb)); err == nil {
|
||||
return &msg, nil
|
||||
}
|
||||
}
|
||||
|
||||
// Unsigned
|
||||
{
|
||||
var msg types.Message
|
||||
if err := msg.UnmarshalCBOR(bytes.NewReader(msgb)); err == nil {
|
||||
return &msg, nil
|
||||
}
|
||||
}
|
||||
|
||||
// Multisig propose?
|
||||
{
|
||||
var pp multisig.ProposeParams
|
||||
if err := pp.UnmarshalCBOR(bytes.NewReader(msgb)); err == nil {
|
||||
i, err := address.NewIDAddress(0)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &types.Message{
|
||||
// Hack(-ish)
|
||||
Version: 0x6d736967,
|
||||
From: i,
|
||||
|
||||
To: pp.To,
|
||||
Value: pp.Value,
|
||||
|
||||
Method: pp.Method,
|
||||
Params: pp.Params,
|
||||
|
||||
GasFeeCap: big.Zero(),
|
||||
GasPremium: big.Zero(),
|
||||
}, nil
|
||||
}
|
||||
}
|
||||
|
||||
// Encoded json???
|
||||
{
|
||||
if msg, err := messageFromJson(cctx, msgb); err == nil {
|
||||
return msg, nil
|
||||
}
|
||||
}
|
||||
|
||||
return nil, xerrors.New("probably not a cbor-serialized message")
|
||||
}
|
||||
|
||||
func messageFromCID(cctx *cli.Context, c cid.Cid) (types.ChainMsg, error) {
|
||||
api, closer, err := lcli.GetFullNodeAPI(cctx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
defer closer()
|
||||
ctx := lcli.ReqContext(cctx)
|
||||
|
||||
msgb, err := api.ChainReadObj(ctx, c)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return messageFromBytes(cctx, msgb)
|
||||
}
|
Loading…
Reference in New Issue
Block a user