Skip to content

Fix Ipld serialization in State*Msg* RPC API #3784

@hanabi1224

Description

@hanabi1224

Issue summary

Lotus uses runtime reflection for IPLD serialization in RPC API json responses, it's ignored in forest for now. More investigation is needed to implement it in forest.

Related lotus code

type MsgLookup struct {
	Message   cid.Cid // Can be different than requested, in case it was replaced, but only gas values changed
	Receipt   types.MessageReceipt
	ReturnDec interface{}
	TipSet    types.TipSetKey
	Height    abi.ChainEpoch
}

var returndec interface{}
	if recpt.ExitCode == 0 && len(recpt.Return) > 0 {
		cmsg, err := m.Chain.GetCMessage(ctx, msg)
		if err != nil {
			return nil, xerrors.Errorf("failed to load message after successful receipt search: %w", err)
		}

		vmsg := cmsg.VMMessage()

		switch t, err := stmgr.GetReturnType(ctx, m.StateManager, vmsg.To, vmsg.Method, ts); {
		case errors.Is(err, stmgr.ErrMetadataNotFound):
			// This is not necessarily an error -- EVM methods (and in the future native actors) may
			// return just bytes, and in the not so distant future we'll have native wasm actors
			// that are by definition not in the registry.
			// So in this case, log a debug message and retun the raw bytes.
			log.Debugf("failed to get return type: %s", err)
			returndec = recpt.Return
		case err != nil:
			return nil, xerrors.Errorf("failed to get return type: %w", err)
		default:
			if err := t.UnmarshalCBOR(bytes.NewReader(recpt.Return)); err != nil {
				return nil, err
			}
			returndec = t
		}
	}

	return &api.MsgLookup{
		Message:   found,
		Receipt:   *recpt,
		ReturnDec: returndec,
		TipSet:    ts.Key(),
		Height:    ts.Height(),
	}, nil

func GetReturnType(ctx context.Context, sm *StateManager, to address.Address, method abi.MethodNum, ts *types.TipSet) (cbg.CBORUnmarshaler, error) {
	act, err := sm.LoadActor(ctx, to, ts)
	if err != nil {
		return nil, xerrors.Errorf("(get sset) failed to load actor: %w", err)
	}

	m, found := sm.tsExec.NewActorRegistry().Methods[act.Code][method]
	if !found {
		return nil, fmt.Errorf("unknown method %d for actor %s: %w", method, act.Code, ErrMetadataNotFound)
	}

	return reflect.New(m.Ret.Elem()).Interface().(cbg.CBORUnmarshaler), nil
}

example lotus API call:

request:

{
    "id": 0,
    "jsonrpc": "2.0",
    "method": "Filecoin.StateWaitMsg",
    "params": [
        {
            "/": "bafy2bzacear2xvf6lnxvtyooupaosxgh2bosn7bp35bzz6syofzk7b45gp2es"
        },
        0
    ]
}

response:

{
    "jsonrpc": "2.0",
    "result": {
        "Message": {
            "/": "bafy2bzacear2xvf6lnxvtyooupaosxgh2bosn7bp35bzz6syofzk7b45gp2es"
        },
        "Receipt": {
            "ExitCode": 0,
            "Return": "gxnmiFUCU1RCVs/3Evl82pH2EU27iJjACWtUdZ6JBkmIZWDdZSQ9ieRv0l4paI4=",
            "GasUsed": 82943114,
            "EventsRoot": null
        },
        "ReturnDec": {
            "ActorID": 59016,
            "RobustAddress": "t2knkeevwp64jps7g2sh3bctn3rcmmaclltnpwtdi",
            "EthAddress": [
                117,
                158,
                137,
                6,
                73,
                136,
                101,
                96,
                221,
                101,
                36,
                61,
                137,
                228,
                111,
                210,
                94,
                41,
                104,
                142
            ]
        },
        "TipSet": [
            {
                "/": "bafy2bzaceanaa2pyrqcn43ybv4ig5urvtumte4ftlkoaqudojyjptvtiadq7w"
            }
        ],
        "Height": 1144812
    },
    "id": 0
}

Other information and links

#3783
#3769

Metadata

Metadata

Assignees

No one assigned

    Labels

    Priority: 2 - HighVery important and should be addressed ASAPType: BugSomething isn't working

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions