f-o-a-m / kepler

A Haskell framework that facilitates writing ABCI applications
https://kepler.dev
Apache License 2.0
34 stars 10 forks source link

Query client bug #210

Closed IvantheTricourne closed 4 years ago

IvantheTricourne commented 4 years ago

I've tried to provide as a minimal an example as possible to replicate this bug, but I'm still not entirely sure what causes it or what might be related.

For the minimal example, I've taken the simple-storage example app and added 2 additional pieces of storage. This work is available on this branch. In this branch I've added the following storage values alongside the existing count store in the app:

  1. Another simple store similar to the count store accessible by a single key containing a list of Texts
  2. A simple key store mapping Text to a newtyped wrapped Text type

The specific failure in my particular use case is hard to replicate, but this is probably because the failure itself varies depending on the order the store contents are declared and also, I'm guessing, related to the specific storage entities themselves (i.e., the type definitions of the key value store and the simple store). In my use case, the failure is a tendermint Resource not found. exception. To be more specific, the data types in my use cases' store were:

  1. Simple store for a record containing newtype wrapped Text types
  2. Simple store for a list of records containing an Address and newtyped wrapped Text type
  3. A key-value store mapping Addresses to a record containing an Address and newtyped wrapped Text type.

In the branch's E2E tests in this commit, the following test failure is reported:

  1) SimpleStorage.Test.E2E, SimpleStorage E2E - via hs-tendermint-client, Can query a foo
       uncaught exception: ErrorCall
       Impossible parse error: too few bytes
       From:    demandInput

       CallStack (from HasCallStack):
         error, called at src/Tendermint/Utils/QueryClient/Class.hs:127:24 in hs-abci-test-utils-0.1.0.0-3paAIgRbs2U3Ar2SVfFmkx:Tendermint.Utils.QueryClient.Class

It should also be noted that the first commit in this branch does not throw this error for the above mentioned unit test (i.e., foos are successfully query-able).

Additionally, if the order of the store contents are changed, the failure also changes. In the current state of the branch, the failure is in a different unit test:

  1) SimpleStorage.Test.E2E, SimpleStorage E2E - via hs-tendermint-client, Can query for a bar
       uncaught exception: ErrorCall
       Impossible parse error: too few bytes
       From:    demandInput

       CallStack (from HasCallStack):
         error, called at src/Tendermint/Utils/QueryClient/Class.hs:127:24 in hs-abci-test-utils-0.1.0.0-3paAIgRbs2U3Ar2SVfFmkx:Tendermint.Utils.QueryClient.Class
IvantheTricourne commented 4 years ago

It seems that the leaf endpoint is being dropped for some the stores:

RPC Request
{
    "jsonrpc": "2.0",
    "params": {
        "height": "-1",
        "path": "/simple_storage", <----------- no /foo
        "data": "2c26b46b68ffc68ff99b453c1d30413413422d706483bfa0f98a5e886266e7ae",
        "prove": false
    },
    "method": "abci_query",
    "id": 638791332021673976
}
RPC Response
{
    "result": {
        "response": {
            "log": "",
            "proof": null,
            "height": "0",
            "value": "AAAABA==",
            "codespace": "",
            "key": "bDVJOiuTeCnJgVw54jr5ZLyE5UMKfcEExwC7wN4rWeM=",
            "code": 0,
            "index": "0",
            "info": ""
        }
    },
    "jsonrpc": "2.0",
    "id": 638791332021673984
}
    Can query a foo FAILED [1]
IvantheTricourne commented 4 years ago

Added some traces to the QueryClient in the utils library, and I found that the proper query paths are only being generated for one store (i.e., the last element of a module's store contents).

type CountStoreContents = '[ (CountKey, Count)
                           , (FooKey, Foo)
                           , (Text, Bar)
                           ]

Notice that for /count and /foo, no debug traces are being printed to console. As a result, only one of these storage endpoints are successfully query-able under the /simple_storage/ endpoint. In this case, the count is query-able but the Foo store isn't.

Simple Storage Endpoints

/bar

StoreLeaf | Leaf value: "bar"
StoreLeaf | Query value: Query {queryData = Base64String "aSdtIGEga2V5", queryPath = "/simple_storage/bar", queryHeight = WrappedVal {unWrappedVal = -1}, queryProve = False}
RPC Request
{
    "jsonrpc": "2.0",
    "params": {
        "height": "-1",
        "path": "/simple_storage/bar",
        "data": "69276d2061206b6579",
        "prove": false
    },
    "method": "abci_query",
    "id": 3221052419716494377
}

/count

RPC Request
{
    "jsonrpc": "2.0",
    "params": {
        "height": "-1",
        "path": "/simple_storage",
        "data": "6c35493a2b937829c9815c39e23af964bc84e5430a7dc104c700bbc0de2b59e3",
        "prove": false
    },
    "method": "abci_query",
    "id": 5008627139545520997
}

/foo

RPC Request
{
    "jsonrpc": "2.0",
    "params": {
        "height": "-1",
        "path": "/simple_storage",
        "data": "2c26b46b68ffc68ff99b453c1d30413413422d706483bfa0f98a5e886266e7ae",
        "prove": false
    },
    "method": "abci_query",
    "id": 8103029188999410850
}
IvantheTricourne commented 4 years ago

Changing title to Query client bug, since it's now clear that the issue is related to query client generation.

martyall commented 4 years ago

The problem is that this should be StoreLeaf and not Leaf in this line https://github.com/f-o-a-m/kepler/blob/master/hs-abci-sdk/src/Tendermint/SDK/BaseApp/Query/Store.hs#L78

I have a fix coming when I merge iavl (will probably be tomorrow), or you can submit a patch now

IvantheTricourne commented 4 years ago

The problem is that this should be StoreLeaf and not Leaf in this line https://github.com/f-o-a-m/kepler/blob/master/hs-abci-sdk/src/Tendermint/SDK/BaseApp/Query/Store.hs#L78

I have a fix coming when I merge iavl (will probably be tomorrow), or you can submit a patch now

That indeed fixed it.