Kava-Labs / kava

DeFi for Crypto.
Apache License 2.0
440 stars 365 forks source link

go-ethereum: `eth_getBlockByHash` returns incorrect hash #1653

Closed byte-bandit closed 1 year ago

byte-bandit commented 1 year ago

Hi,

I'm trying to query KAVA RPC endpoints for blocks by hash and am running into some very weird behaviour. Essentially, while the RPC endpoints are reporting the correct hash, the go-ethereum client will return an incorrect one.

Looking at the implementation, we can see that the hash reported by the RPC endpoint is completely disregarded. You can see the struct the payload is being parsed into here, it's missing a field for the hash.

Instead, the block hash will be calculated on demand and cached (see here and here).

Interestingly enough, this approach works for every other chain I tried (eth-main, matic-main, bnb-main - even op-main when using op-geth), but it doesn't seem to be working for Kava - no matter which endpoint provider I try.

I've added a snipped that should help you reproduce what I'm seeing. Let me know if there's any further input that I can give, I'd greatly appreciate any help you can give.

Steps to reproduce

The thirdweb endpoints are rate limited, I suggest to use your own ones should you have them available, though the observed behaviour is identical across different endpoint providers.

package main

import (
    "context"
    "fmt"
    "log"
    "time"

    "github.com/ethereum/go-ethereum/common"
    "github.com/ethereum/go-ethereum/ethclient"
)

type test struct {
    targetChain string
    rpcEndpoint string
    hashes      []string
}

func main() {
    ctx := context.Background()

    for _, v := range []test{
        {
            targetChain: "kava-main",
            rpcEndpoint: "https://kava-evm.rpc.thirdweb.com",
            hashes: []string{
                "0x76966b1d12b21d3ff22578948b05a42b3da5766fcc4b17ea48da5a154c80f08b",
                "0xc2a7d272b89e1824c36919a85404fa61e3a95904ffd55c55f34694628759b734",
                "0x8b26e3d0979bbfdda0f4147a22ab850c0cf4e730b71d5ba1111cafc113210bdf",
                "0xe8d934dc88c1e87f3f92b23e8d522aee5ded8d94a668fc1a575ae5fca3153218",
                "0xcdcaea65fa52ca40f3234b508e74980d28039ae15a94b9496570e21be03502cd",
            },
        },
        {
            targetChain: "eth-main",
            rpcEndpoint: "https://ethereum.rpc.thirdweb.com",
            hashes: []string{
                "0x344843f004f457ac2b99b90d94d860b8733a2a1be085b9d025a1643872b4e836",
                "0x79477d360a61aaee7878d5a182bef2f87724e022c60c920e067b5b5091d00a65",
                "0xdd0bcf73ddd749f10565402bfcee803a4a1bbcf5ea835301df918fb682c26cfb",
                "0x4d60e3533409cfca434fbd17e1868a1a95d3240c899f72d985fc16df80a684f7",
                "0xf2441931110cb9f6166fe6edd2b8c4f226e6eecfa90ea17c7ccd49631684e10a",
            },
        },
        {
            targetChain: "bnb-main",
            rpcEndpoint: "binance.rpc.thirdweb.com",
            hashes: []string{
                "0xdf31c16fe5244f9533a7754c3fd498aedc70f62c00501e9a506312d5e8f293c3",
                "0x6b29195acde612e9dbf0c4140b79597eeb9c7efa362dc3ba5b1d131d262fd886",
                "0x3d6629cf7a6b6b0bdc98f16a406f81b430d8659973513c33292ce10afc7a6fcc",
                "0x6064a3c55048ac5c78ffb185637bd703fa3580b674495f7c22908169f9b35e84",
                "0x901e384bebc0b14279b06848ab36151c1267bb4ad531cb6de7f1619e4b1bcb9a",
            },
        },
        {
            targetChain: "matic-main",
            rpcEndpoint: "polygon.rpc.thirdweb.com",
            hashes: []string{
                "0x1e84cefdc52f0f4b5dacfaad8a61b09b52b5e0d92067b86080b8781a6e628b71",
                "0xe1eaa01d6e3e89ed751aff7bb4e20508a93abfc3b91a1078f4e153c791fb2562",
                "0xf75b09c21fa10e90bc2fcfb678090d778a168e6c5f733fd070b406a54f13e66c",
                "0xede2fe63d74af21dbd2793b72d3e9536d2b087c25f508595637979164196e26c",
                "0xb5e9e7a659b637454bbae73de089579c1bdb6c7e1b65a70c0d62545c798e9de0",
            },
        },
    } {
        if err := run(ctx, v.targetChain, v.rpcEndpoint, v.hashes); err != nil {
            panic(err)
        }
    }
}

func run(ctx context.Context, chain string, rpc string, hashes []string) error {
    log.Default().Printf("🤖 Running block retrieval tests on chain '%s' ...", chain)
    c, err := ethclient.Dial(rpc)
    if err != nil {
        return fmt.Errorf("fail to dial: %w", err)
    }

    for i, v := range hashes {
        time.Sleep(time.Second)
        want := common.HexToHash(v)
        bk, err := c.BlockByHash(ctx, want)
        if err != nil {
            return fmt.Errorf("fail to get block by hash: %w", err)
        }
        have := bk.Hash()

        if want != have {
            log.Default().Printf(`🔴 [%d/%d] FAIL - Want: "%s", Have: "%s"`, i+1, len(hashes), want, have)
            continue
        }
        log.Default().Printf(`🟢 [%d/%d] PASS - Want: "%s", Have: "%s"`, i+1, len(hashes), want, have)
    }

    return nil
}
DracoLi commented 1 year ago

Hi @byte-bandit, The EVM block hash on the Kava chain is the same as the tendermint block hash since Kava uses tendermint as the consensus engine. This means if you try to calculate the hash using the block contents (ie go-ethereum), then it will unfortunately not match the actual block hash as the block hash is derived differently. However, other than the hash mismatch, the other content obtained from BlockByHash should be correct.

byte-bandit commented 1 year ago

@DracoLi Thanks for your insights, that makes sense. Yes, I can confirm that only the hash itself is a mismatch, all other information seems to remain correct. I think it's clear that going forward, we'll have to trust the hash reported by the endpoint instead of calculating ourselves.

Closing this as resolved.