ChainSafe / ChainSafe/forest

Fix Ipld serialization in `State*Msg*` RPC API

Open
#3,784 2 comments 0 reactions 0 assignees View on GitHub
Priority: 2 - High Type: Bug
Dominant language
Rust
Stars
697
Forks
200
Avg merge
1d 5h
Merged PRs (30d)
65

Description

**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
```go
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:
```json
{
"id": 0,
"jsonrpc": "2.0",
"method": "Filecoin.StateWaitMsg",
"params": [
{
"/": "bafy2bzacear2xvf6lnxvtyooupaosxgh2bosn7bp35bzz6syofzk7b45gp2es"
},
0
]
}
```

response:
```json
{
"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**

https://github.com/ChainSafe/forest/pull/3783
https://github.com/ChainSafe/forest/issues/3769

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.