near / read-rpc

Read-only NEAR RPC centralized-like performant solution
16 stars 4 forks source link

(rpc-server): Implement method `next_light_client_block` #275

Open khorolets opened 3 weeks ago

khorolets commented 3 weeks ago

About the next_light_client_block method

This is one of the undocumented methods that exists in the native JSON-RPC. It is created to support Light Clients (while quite exciting understanding is not required to implement the method). One of the main users of this method is Rainbow Bridge.

As of now, on the ReadRPC side we proxy this method to a regular native JSON-RPC node. I did some research and it looks like we can totally implement the support on our side and avoid yet another proxy.

Technical details

/// Returns the next light client block, given the hash of the last block known to the light client.
/// There are three cases:
///  1. The last block known to the light client is in the same epoch as the tip:
///     - Then return the last known final block, as long as it's more recent that the last known
///  2. The last block known to the light client is in the epoch preceding that of the tip:
///     - Same as above
///  3. Otherwise, return the last final block in the epoch that follows that of the last block known
///     to the light client

This is a docstring from the view_client_actor.rs around the logic behind this JSON-RPC method.

The logic itself can be seen here: https://github.com/near/nearcore/blob/337a81e4b8f323fd64cc83cf379d51fd80e912da/chain/client/src/view_client_actor.rs#L974-L1006

Recap from what I see:

  1. The signature of this method accepts latest_block_hash: CryptoHash (we have a data in the database to convert it into block height)
  2. We need the BlockHeader of the given block (source: Lake S3)
  3. We need the latest epoch id (a) (Redis)
  4. We need the head (b) (final or optimistic block from Redis)
  5. Compare a with b.epoch_id OR a.next_epoch_id with b.epoch_id
    • Build LightClientBlockView of the b (head) and return it
    • This is ambiguous to me, I haven't researched that far if we have all of the data to make it
  6. If 5 is false build the LightClientBlockView for the last final block of the epoch a.next_epoch_id

References:

frolvanya commented 3 weeks ago

It feels like we don't have enough data for now to create a new light block:

I've tried to trace the definition of next block using nearblocks.io, but as you can see from the code, next_block_inner_hash is a hash sum of two hashes (next_block_header.inner_lite_bytes() and next_block_header.inner_rest_bytes()), so I can't revert this operation in order to find out what was the next block. It might be a good idea to add a print statement in a nearcore and run it locally, but I believe that I don't have access keys and data to do this

Here's a result of next_block_inner_hash when calling http post https://rpc.mainnet.near.org/ jsonrpc=2.0 method=next_light_client_block params:='{"last_block_hash": "3WcKXMqUshXkTeWzrmcVJryybPsK4H21jfYyweg4zrNr"}' id=dontcare two times in a row (I was using a block from the last epoch): 1) "next_block_inner_hash": "4cxVmcNH7YyA9SSExhoJTQNbnUSJDAWGeuQiW1FtgdYz" 2) "next_block_inner_hash": "4kMURpXgADtY8VTyyLJTWuN3FfGyNFwvpUnrmC2ehHgh"