diff --git a/packages/stargate/src/queries/queryclient.ts b/packages/stargate/src/queries/queryclient.ts index d5052478..c835a816 100644 --- a/packages/stargate/src/queries/queryclient.ts +++ b/packages/stargate/src/queries/queryclient.ts @@ -230,7 +230,7 @@ export class QueryClient { } const searchHeight = height + 1; - let nextHeader: Header; + let nextHeader: Header | undefined; let headersSubscription: Stream | undefined; try { headersSubscription = this.tmClient.subscribeNewBlockHeader(); @@ -239,28 +239,26 @@ export class QueryClient { } if (headersSubscription) { - // get the header for height+1 - nextHeader = await firstEvent(headersSubscription); // TODO: fall back on polling if this returns a too high header - } else { + const firstHeader = await firstEvent(headersSubscription); + // The first header we get might not be n+1 but n+2 or even higher. In such cases we fall back on a query. + if (firstHeader.height === searchHeight) { + nextHeader = firstHeader; + } + } + + while (!nextHeader) { // start from current height to avoid backend error for minHeight in the future - let header = (await this.tmClient.blockchain(height, searchHeight)).blockMetas + const correctHeader = (await this.tmClient.blockchain(height, searchHeight)).blockMetas .map((meta) => meta.header) .find((h) => h.height === searchHeight); - while (!header) { + if (correctHeader) { + nextHeader = correctHeader; + } else { await sleep(1000); - header = (await this.tmClient.blockchain(height, searchHeight)).blockMetas - .map((meta) => meta.header) - .find((h) => h.height === searchHeight); } - nextHeader = header; - } - - if (nextHeader.height !== searchHeight) { - throw new Error( - `Query requires header at height ${searchHeight} for proof verification, but next header was ${nextHeader.height}`, - ); } + assert(nextHeader.height === searchHeight, "Got wrong header. This is a bug in the logic above."); return nextHeader; } }