Cardano-wallet: Listing transaction when node is still in the Byron era may fail with 500

Created on 28 Jul 2020  路  13Comments  路  Source: input-output-hk/cardano-wallet

Context

| Information | - |
| --- | --- |
| Version | Close to Shelley Mainnet release |
| Platform | |
| Installation | |

With #1869, we use a TimeInterpreter from the node for time and slotting conversions. The conversions fails if "Past the Horizon". From genesis to close to the fork, the node will have a limited horizon.

Steps to Reproduce

  1. Have a node and wallet which is running Byron;Shelley, but which has not yet reached Shelley. (E.g. on Cardano mainnet when first syncing from genesis)
  2. List transactions with a time range were one of the dates are far ahead of the node tip (which is continuously syncing).

Expected behavior

  1. I get a response, or a helpful error

Actual behavior

  1. (Theorized) 500: Something went wrong

Note: This shouldn't happen when the node is in Shelley.


Resolution


QA

BUG LOW HIGH

All 13 comments

That is the case indeed on mainnet currently:

$ cardano-wallet-byron transaction list --port 8886 <wid> --start 2016-11-21T10:15:00Z --end 2020-08-29T10:15:00Z
Something went wrong
[cardano-wallet.network:Error:160925] [2020-07-29 12:54:20.88 UTC] Time interpreter queried past the horizon. Query is:
PastHorizon [("runQueryqBind qBind qBind qBind UTCTimeToRel 2016-11-21 10:15:00 UTC
"Eras are:
EraSummary {eraStart = Bound {boundTime = RelativeTime {getRelativeTime = 0s}, boundSlot = SlotNo {unSlotNo = 0}, boundEpoch = EpochNo {unEpochNo = 0}}, eraEnd = EraEnd (Bound {boundTime = RelativeTime {getRelativeTime = 89856000s}, boundSlot = SlotNo {unSlotNo = 4492800}, boundEpoch = EpochNo {unEpochNo = 208}}), eraParams = EraParams {eraEpochSize = EpochSize {unEpochSize = 21600}, eraSlotLength = SlotLength {getSlotLength = 20s}, eraSafeZone = StandardSafeZone 4320 NoLowerBound}}
,EraSummary {eraStart = Bound {boundTime = RelativeTime {getRelativeTime = 89856000s}, boundSlot = SlotNo {unSlotNo = 4492800}, boundEpoch = EpochNo {unEpochNo = 208}}, eraEnd = EraEnd (Bound {boundTime = RelativeTime {getRelativeTime = 90288000s}, boundSlot = SlotNo {unSlotNo = 4924800}, boundEpoch = EpochNo {unEpochNo = 209}}), eraParams = EraParams {eraEpochSize = EpochSize {unEpochSize = 432000}, eraSlotLength = SlotLength {getSlotLength = 1s}, eraSafeZone = StandardSafeZone 129600 NoLowerBound}}
S
CallStack (from HasCallStack):
r  runQuery, called at src/Ouroboros/Consensus/HardFork/History/Qry.hs:302:44 in ouroboros-consensus-0.1.0.0-6XEysmm3YiIHtxLyZm7Gh9:Ouroboros.Consensus.HardFork.History.Qry
c  interpretQuery, called at src/Cardano/Wallet/Primitive/Slotting.hs:336:26 in cardano-wallet-core-2020.7.28-2S8ptXuDYMoINYRfmCELX3:Cardano.Wallet.Primitive.Slotting
L  runQuery, called at src/Cardano/Wallet/Primitive/Slotting.hs:297:5 in cardano-wallet-core-2020.7.28-2S8ptXuDYMoINYRfmCELX3:Cardano.Wallet.Primitive.Slotting
o  mkTimeInterpreter, called at src/Cardano/Wallet/Shelley/Network.hs:486:14 in cardano-wallet-shelley-2020.7.28-INn5Nk3l47eEkqQmtWRPJ3:Cardano.Wallet.Shelley.Network
c  _timeInterpreterQuery, called at src/Cardano/Wallet/Shelley/Network.hs:311:33 in cardano-wallet-shelley-2020.7.28-INn5Nk3l47eEkqQmtWRPJ3:Cardano.Wallet.Shelley.Network
   timeInterpreter, called at src/Cardano/Wallet/Network.hs:153:7 in cardano-wallet-core-2020.7.28-2S8ptXuDYMoINYRfmCELX3:Cardano.Wallet.Network

As "expected", though the server should really catch this error and return something more meaningful to users.

@piotr-iohk I'm not sure how to reproduce this properly (I don't have a byron wallet on mainnet).

@KtorZ the error is catched and rethrown:

https://github.com/input-output-hk/cardano-wallet/blob/b5b292b5a9f0ddccc0fc5d9e98bf3bf80f1a9d13/lib/shelley/src/Cardano/Wallet/Shelley/Network.hs#L478-L488

So:

  1. what's the expected status code? 400?
  2. what's a more meaningful message?

I'm not sure how to reproduce this properly (I don't have a byron wallet on mainnet).

Forgot to write down a step: The node (and wallet) needs to be syncing in the byron part of the chain. Once it reaches the hard-fork to Shelley, no time interpreter queries will fail anymore.

_Description updated._

Btw, when the wallet and node is still in Byron, cardano-wallet network information will not contain the next_epoch and node_tip fields 鈥斅燼 way to tell.

@hasufell, possible to reproduce also on current testnet:

cardano-node run \
    --config ~/relay/testnet-config.json \
        --topology ~/relay/testnet-topology.json \
    --database-path ./db \
    --socket-path ~/relay/node.socket \
    --host-addr 0.0.0.0 \
    --port 9999
  • start wallet
cardano-wallet serve --port 8090 \
  --node-socket ~/relay/node.socket \
  --testnet ~/relay/testnet-byron-genesis.json  \
  --database ./wallet-db
  • while the node is still syncing through Byron era (it should for a while, there are 70+ byron epochs there), create a Byron wallet:
curl  -vX POST http://localhost:8090/v2/byron-wallets \
  -H "Content-Type: application/json; charset=utf-8" \
  -d '{
"style" : "random",
"name": "Byron1",
"mnemonic_sentence": ["rotate", "machine", "travel", "safe", "expire", "leopard", "wink", "vault", "borrow", "digital", "wisdom", "harsh"],
"passphrase": "Secure Passphrase"
}' --http1.1  |  jq
  • and then try to list txs from that wallet using end query parameter that is in the future:
curl http://localhost:8090/v2/byron-wallets/9914f38ab2bd7f9c67c31ae15399d778c3224fc3/transactions?end=2020-08-29T10:15:00Z


Something went wrong

LGTM.

curl -v http://localhost:8090/v2/byron-wallets/9914f38ab2bd7f9c67c31ae15399d778c3224fc3/transactions?end=2020-08-29T10:15:00Z

< HTTP/1.1 503 Service Unavailable

{
  "code": "past_horizon",
  "message": "Tried to convert something that is past the horizon (due to uncertainty about the next hard fork). Wait for the node to finish syncing to the hard fork. Depending on the blockchain, this process can take an unknown amount of time."
}

@hasufell @KtorZ I don't suppose we can have automated test for this? (current integration set-up wouldn't allow for such a test or would be flaky I guess as we're testing past hard-fork). Is there perhaps a way to have a test "lower" in the code? If not then maybe I'll create a manual scenario...

@piotr-iohk it is indeed a bit tricky to run an integration on this; we do have a callback triggered when the cluster is up and in the byron era, before triggering the hardfork, but the wallet server isn't started yet at this stage. We could, start it and run a subset of the specs, and then proceed as normal.

That's a bit of busywork for just testing an error message though, yet; that is an error which can only happen / makes sense testing in a real context and that can only be tested at an integration level.

I see now that there is a similar situation like in the original bug also with listing pools.
So, while node is syncing through Byron era and we try to list stake-pools we get:

GET http://localhost:8090/v2/stake-pools?stake=1000000000

The response was:
Code = 500,
Message = Something went wrong

In the log there is:

[2020-08-31 09:55:07.56 UTC] [RequestId 3] [GET] /v2/stake-pools?stake=1000000000
[cardano-wallet.network:Error:68] [2020-08-31 09:55:07.56 UTC] Time interpreter queried past the horizon: PastHorizon {pastHorizonCallStack = [("runQuery",SrcLoc {srcLocPackage = "ouroboros-consensus-0.1.0.0-4d7eQOlpbeAI6Fba7E3tDP", srcLocModule = "Ouroboros.Consensus.HardFork.History.Qry", srcLocFile = "src/Ouroboros/Consensus/HardFork/History/Qry.hs"

@hasufell shall I create a separate bug or perhaps it is easy enough to address under this issue?

@piotr-iohk let me check

So the issue is in:

https://github.com/input-output-hk/cardano-wallet/blob/ba4295974c34ec2f0991d3cfccc7035bc79705b2/lib/shelley/src/Cardano/Wallet/Shelley/Network.hs#L478-L488

This API is hard to change, but it'll likely leak IO Exceptions in other places too.

LGTM. Both listing tx and listing sp while node is in the Byron era result in a nice 503 error:

{"code":"past_horizon"
,"message":"Tried to convert something that is past the horizon (due to uncertainty about the next hard fork). Wait for the node to finish syncing to the hard fork. Depending on the blockchain, this process can take an unknown amount of time."}
Was this page helpful?
0 / 5 - 0 ratings