paritytech / json-rpc-interface-spec

29 stars 3 forks source link

`chainHead_follow`: seeking clarification on`spec.apis` keys #82

Closed jsdw closed 1 year ago

jsdw commented 1 year ago

When we pass withRuntime, we are given runtime details in a couple of places that look something like (taken from the spec; see https://paritytech.github.io/json-rpc-interface-spec/api/chainHead_unstable_follow.html#about-the-runtime):

{
    "specName": "westend",
    "implName": "parity-westend",
    "specVersion": 9122,
    "implVersion": 0,
    "transactionVersion": 7,
    "apis": {
        "0xdf6acb689907609b": 3
        "0x37e397fc7c91f5e4": 1,
        "0x40fe3ad401f8959a": 5,
        "0xd2bc9897eed08f15": 3,
        "0xf78b278be53f454c": 2,
        "0xaf2c0297a23e6d3d": 1,
        "0x49eaaf1b548a0cb0": 1,
        "0x91d5df18b0d2cf58": 1,
        "0xed99c5acb25eedf5": 3,
        "0xcbca25e39f142387": 2,
        "0x687ad44ad37f03c2": 1,
        "0xab3c0572291feb8b": 1,
        "0xbc9d89904f5b923f": 1,
        "0x37c8bb1350a9a2a8": 1
    }
}

About the keys in apis, the spec says:

Each key is an opaque string indicating the API

Before making a runtime call (using chainHead_unstable_call), you should make sure that this list contains the entry point API corresponding to the call and with a known version number.

Given that the keys are opaque and it's not specified how to construct them, how should I perform this check?

In Substrate, the keys in the apis field consists of the hexadecimal-encoded 8-bytes blake2 hash of the name of the API. For example, the TaggedTransactionQueue API is 0xd2bc9897eed08f15.

Does smoldot do this too? Should we specify how the keys are generated so that there is a known way for clients to perform the check without knowing which specific implementation they are talking to?

Open to thoughts and opinions :)

tomaka commented 1 year ago

Given that the keys are opaque and it's not specified how to construct them, how should I perform this check?

Well, if you need to call for example TaggedTransactionQueue_validate_transaction, you check whether the list contains 0xd2bc9897eed08f15.

The reason why I mention that they're opaque strings is that in principle there's no such thing as "a runtime API". That's purely a runtime-side concept, not a client-side concept. If the client wants to call TaggedTransactionQueue_validate_transaction, it checks whether 0xd2bc9897eed08f15 is in the list.

The fact that the API name in the list is the hash of the camel case part of the function name is an implementation detail of the runtime. It makes sense for the JSON-RPC client to check whether hash("TaggedTransactionQueue") is in the list, however I think it's a bad idea to do something like if isInApisList(&function_name[..function_name.iter().position('_')]).

Does smoldot do this too?

It's not smoldot or Substrate that does this, it's the runtime. Smoldot and Substrate just get the list from the runtime and pass it straight to the JSON-RPC client. In principle it wouldn't be a bad idea to send the unhashed strings to the JSON-RPC client, as it would make things more simple, but there's no way whatsoever for the client to be able to know the unhashed versions, because again it's purely a runtime-side concept.

jsdw commented 1 year ago

That makes perfect sense, thank you for the information!

So we'll know what to look for because that's what the runtime is currently doing, but of course the runtime may decide to change what it returns here at some point and then the client would need updating to match (but I'm assuming that the chances of that happening are very slim, since changing the shape of the info that tells you about versions of things would be quite unhelpful!).