iroha icon indicating copy to clipboard operation
iroha copied to clipboard

Proposal: add ability to reverse query results ordering

Open 0x009922 opened this issue 7 months ago • 1 comments

Use Case

I want to know the hash (only) of the genesis block. Ways to do that:

  1. Use FindBlocks query. However, it starts from the end. E.g. if Iroha has 1500 blocks and I query with offset=0; limit=1, I'll get the latest block.
  • I can get the genesis block by making a query with offset=1499; limit=1, but for that I need to know the block height first. For that, I need to make a separate request, and there is a chance of a race condition: I receive that the height is 1500, I request block at 1499, but block height changes and I get not the first block, but the second one. So I have to retry.
  • I can refine the previous approach by setting a larger limit, e.g. offset=1499; limit=10, thus i will most likely receive the genesis block alongside others if a race condition occurred. However, this is still not optimal.
  1. Use Block Stream with height=0. I can receive the first block and hang up the stream. However:
  • Block stream works in such a way that it will immediately produce a multitude of WebSocket messages with all the blocks it has. If it has 1500 blocks, it will immediately emit all of them via WebSocket, although I, the client, didn't yet ask for them. This is an issue of itself.
  • Block stream emits the entire SignedBlock, while I only need a hash (which I can get thanks to query projections).

In summary, the existing ways are not optimal at all.

Proposal

Introduce a new Sorting field (alongside the only existing sort_by_metadata_key): reverse: bool (false by default). This parameter is generic enough to be applied to any other query.

How it solves the problem

I can simply set reverse=true; offset=0; limit=1 and get the genesis block deterministically, without extra dances.

Downsides

  • ABI breaking change.

Alternatives

  • Put this field as a payload of the FindBlocks query only: FindBlocks { reverse: bool }.

Context

I am not re-building the Explorer (https://github.com/soramitsu/iroha2-block-explorer-backend/issues/79) and am working on the mechanism of how to synchronize blocks with Iroha without access to the block sync. I am trying to cover one of the corner-cases in this process, when Explorer stored some blocks and connects to Iroha with an entirely different blockchain. It is a special case which could be checked by simple comparison of the genesis block only, instead of going through the entire chain and finding the mismatching block.

0x009922 avatar Jun 04 '25 04:06 0x009922

If we could specify a range instead of a count from an offset, we could fetch even a single block.

Could the chain ID be useful in some way for this issue?

s8sato avatar Jun 05 '25 04:06 s8sato

@s8sato sorry for long reply, I missed your message.

If we could specify a range instead of a count from an offset, we could fetch even a single block.

Not sure I understand. It seems possible to fetch a single block with limit=1 now.

Could the chain ID be useful in some way for this issue?

You mean, in order to determine if Explorer connects to an entirely different blockchain? I don't think it is a very robust mechanism. The target of Explorer is to reflect the chain and the state properly. For this, the ultimate source of truth is the chain of block hashes. A user-provided arbitrary chain ID does not guarantee that.

0x009922 avatar Aug 18 '25 05:08 0x009922

I was simply suggesting an alternative expression of the query -- height_range=(1,1) instead of offset=1499; limit=1 -- and I won't insist on it.

Yeah, it makes sense to identify the chain by its genesis block, as stated in the description.

s8sato avatar Aug 19 '25 00:08 s8sato