Cardano-db-sync: testnetのUnicodeによる例外

作成日 2020年09月19日  ·  15コメント  ·  ソース: input-output-hk/cardano-db-sync

testnetネットワークでtags/5.0.0extendedモードのtags/5.0.0 cardano-db-syncが、Unicodeの解析/処理の問題のためにブロック1816809で例外をスローしています。 このブロックを超えて同期することはできません。

[db-sync-node:Info:234667] [2020-09-19 14:23:20.41 UTC] Starting chainSyncClient
[db-sync-node:Info:234667] [2020-09-19 14:23:20.48 UTC] Cardano.Db tip is at slot 6061839, block 1816809
[db-sync-node:Info:234672] [2020-09-19 14:23:20.48 UTC] Running DB thread
[db-sync-node:Info:234672] [2020-09-19 14:23:20.65 UTC] Rolling back to slot 6061839, hash 98414d12d1d1f05210dea6ce4082e1bcbbcfdf56343fd1cb44a8778c4c9ea57a
[db-sync-node:Info:234672] [2020-09-19 14:23:20.66 UTC] Deleting blocks numbered: []
[db-sync-node:Error:234672] [2020-09-19 14:23:21.03 UTC] runDBThread: DbInsertException "TxMetadata" (SqlError {sqlState = "22P05", sqlExecStatus = FatalError, sqlErrorMsg = "unsupported Unicode escape sequence", sqlErrorDetail = "\\u0000 cannot be converted to text.", sqlErrorHint = ""})
[db-sync-node:Error:234667] [2020-09-19 14:23:21.05 UTC] ChainSyncWithBlocksPtcl: DbInsertException "TxMetadata" (SqlError {sqlState = "22P05", sqlExecStatus = FatalError, sqlErrorMsg = "unsupported Unicode escape sequence", sqlErrorDetail = "\\u0000 cannot be converted to text.", sqlErrorHint = ""})
[db-sync-node.Subscription:Error:234663] [2020-09-19 14:23:21.05 UTC] [String "Application Exception: LocalAddress {getFilePath = \"/run/cardano-node/node.socket\"} DbInsertException \"TxMetadata\" (SqlError {sqlState = \"22P05\", sqlExecStatus = FatalError, sqlErrorMsg = \"unsupported Unicode escape sequence\", sqlErrorDetail = \"\\\\u0000 cannot be converted to text.\", sqlErrorHint = \"\"})",String "SubscriptionTrace"]
[db-sync-node.ErrorPolicy:Error:4] [2020-09-19 14:23:21.05 UTC] [String "ErrorPolicyUnhandledApplicationException (DbInsertException \"TxMetadata\" (SqlError {sqlState = \"22P05\", sqlExecStatus = FatalError, sqlErrorMsg = \"unsupported Unicode escape sequence\", sqlErrorDetail = \"\\\\u0000 cannot be converted to text.\", sqlErrorHint = \"\"}))",String "ErrorPolicyTrace",String "LocalAddress {getFilePath = \"/run/cardano-node/node.socket\"}"]

最も参考になるコメント

これは、一時的な修正で現在どのように見えるかです:

[db-sync-node:Info:37] [2020-09-22 10:19:09.66 UTC] insertShelleyBlock: epoch 84, slot 6060000, block 1816721, hash 3ec15354c53deae4eb26a206cc3185f799e80bd09393f279bce7e53a7d633144
[db-sync-node:Warning:37] [2020-09-22 10:19:24.08 UTC] insertTxMetadata: dropped due to a Unicode NUL character.
[db-sync-node:Warning:37] [2020-09-22 10:19:24.08 UTC] insertTxMetadata: dropped due to a Unicode NUL character.
[db-sync-node:Warning:37] [2020-09-22 10:19:24.10 UTC] insertTxMetadata: dropped due to a Unicode NUL character.
[db-sync-node:Warning:37] [2020-09-22 10:19:24.10 UTC] insertTxMetadata: dropped due to a Unicode NUL character.
[db-sync-node:Info:37] [2020-09-22 10:19:24.93 UTC] insertShelleyBlock: epoch 84, slot 6065000, block 1816973, hash 0ab0dd5c36c6eb480b8bbd05508be952c5ed8597a4e422af25bd80a905a9368d

全てのコメント15件

これは首の大きな痛みです。

挿入されているtxmetedataは

(1,S "\NUL\ETX\ETX\ETX\ETX\ETX\ETX\ETX\ETX\ETX\ETX\ETX\ETX\ETX\ETX\ETX\ETX\ETX\ETX\ETX\ETX\ETX\ETX\ETX\ETX\ETX\ETX\ETX\ETX\ETX\ETX\ETX\ETX\ETX\ETX\ETX\ETX\ETX\ETX\ETX\ETX\ETX\ETX\ETX\ETX\ETX\ETX\ETX\ETX\ETX\ETX\ETX\ETX\ETX\ETX\ETX\ETX\ETX\ETX\ETX\ETX\ETX\ETX\ETX")

これはJSONとしてエンコードされています:

"\u0000\u0003\u0003\u0003\u0003\u0003\u0003\u0003\u0003\u0003\u0003\u0003\u0003\u0003\u0003\u0003\u0003\u0003\u0003\u0003\u0003\u0003\u0003\u0003\u0003\u0003\u0003\u0003\u0003\u0003\u0003\u0003\u0003\u0003\u0003\u0003\u0003\u0003\u0003\u0003\u0003\u0003\u0003\u0003\u0003\u0003\u0003\u0003\u0003\u0003\u0003\u0003\u0003\u0003\u0003\u0003\u0003\u0003\u0003\u0003\u0003\u0003\u0003\u0003"

もちろんこれは有効なUTF8ではないため、データベースはそれを拒否します。

さらに悪いことに、上記は、示されているようにHaskell TextライブラリによってUTF8としてエンコードされますが、PostgreSQLはそれを拒否します。

これが首の大きな痛みであるということを繰り返し述べさせてください。

問題の文字列は、Haskell TextライブラリによってUTF8にデコードされてから、 SqlError例外をスローするPostgresに渡されます。 この例外をキャッチしようとしましたが、例外をキャッチできないようです。

例外をキャッチしてログに記録できます。

[db-sync-node:Warning:37] [2020-09-21 00:26:18.77 UTC] insertTxMetadata: Failed to insert (1,S "\NUL...\ETX")
SqlError {sqlState = "22P05", sqlExecStatus = FatalError, sqlErrorMsg
 = "unsupported Unicode escape sequence", sqlErrorDetail = "\\u0000 cannot be converted to text.", sqlErrorHint = ""}

しかし、2番目の例外があります:

[db-sync-node:Error:37] [2020-09-21 00:26:18.77 UTC] runDBThread: SqlError {sqlState = "25P02", sqlExecStatus = FatalError, sqlErrorMsg = "current transaction is aborted, commands ignored until end of transaction
 block", sqlErrorDetail = "", sqlErrorHint = ""}

これは、挿入する前にJSONをより完全に検証する必要があることを示しています。

無効なUTF8をPostgreSQLに保存できますが、 byteaデータとしてのみ、 jsonbとしてではなく、以前のPostgresのJSONクエリサポートを利用できません。

手動のUTF8デコードを試しました。

decodeUtf8IO :: ByteString -> IO (Either Text.UnicodeException Text)
decodeUtf8IO = try . evaluate . Text.decodeUtf8With Text.strictDecode

それも同じ問題を抱えています。

差出人: https

PostgreSQL文字列ではnullバイトは無効です。 どちらもゼロコードポイントではありません。

現在、これはHaskell / Persistentがpostgresに送信するためにこれをシリアル化する方法によるものだと考えています。 現在、この理論を検証しようとしています。

Aeson.encodeは、すでにNUL文字を\u0000エスケープしており、Persistentはこれを拒否します。

このためのきちんとした修正を思い付くのは簡単ではありません。

私はこれを調べていましたが、これらのプロパティが保持されているようです。

  • "\u0000\u0003\u0003\u0003\u0003\u0003\u0003\u0003\u0003\u0003\u0003\u0003\u0003\u0003\u0003\u0003\u0003\u0003\u0003\u0003\u0003\u0003\u0003\u0003\u0003\u0003\u0003\u0003\u0003\u0003\u0003\u0003\u0003\u0003\u0003\u0003\u0003\u0003\u0003\u0003\u0003\u0003\u0003\u0003\u0003\u0003\u0003\u0003\u0003\u0003\u0003\u0003\u0003\u0003\u0003\u0003\u0003\u0003\u0003\u0003\u0003\u0003\u0003\u0003"はUTF-8としてかなり有効です。これは、UTF-8では\u0000を直接表すことができるためです。
  • \u0000は、 text変換できないため、 jsonbには使用できません。

それをJSONにエンコードし、次にTextにエンコードしてから、不正な文字シーケンスを検出し、不正なシーケンスが含まれている場合はJSONオブジェクトを拒否する唯一の一時的な解決策。 また、 \u0000が、拒否する必要がある唯一のシーケンスであるかどうかも疑問に思います。

2つの列を格納できませんでしたか? bytea、およびテキスト以外の文字が含まれていない場合はJSONを使用できるため、誰でも必要なものを自由に使用できます。

@erikd \u0000制限は、Postgresが従う他のすべてのルールとともにここに明確に記載さ

リークのある抽象化を回避するには、正確な値(ユーザーが指定した値)を保存する必要があります。 これは大まかに言って、元の意味を何らかの形で保持するblob(= DBに構造がない)またはJSON文字列値のいずれかを意味します。たとえば、DB内のbase64でエンコードされた文字列値(したがって、 base64から実際の値に変換するため)。

一時的な回避策の修正(Postgresに挿入できないメタデータオブジェクトを単に削除する)がmasterにマージされました。

これは、一時的な修正で現在どのように見えるかです:

[db-sync-node:Info:37] [2020-09-22 10:19:09.66 UTC] insertShelleyBlock: epoch 84, slot 6060000, block 1816721, hash 3ec15354c53deae4eb26a206cc3185f799e80bd09393f279bce7e53a7d633144
[db-sync-node:Warning:37] [2020-09-22 10:19:24.08 UTC] insertTxMetadata: dropped due to a Unicode NUL character.
[db-sync-node:Warning:37] [2020-09-22 10:19:24.08 UTC] insertTxMetadata: dropped due to a Unicode NUL character.
[db-sync-node:Warning:37] [2020-09-22 10:19:24.10 UTC] insertTxMetadata: dropped due to a Unicode NUL character.
[db-sync-node:Warning:37] [2020-09-22 10:19:24.10 UTC] insertTxMetadata: dropped due to a Unicode NUL character.
[db-sync-node:Info:37] [2020-09-22 10:19:24.93 UTC] insertShelleyBlock: epoch 84, slot 6065000, block 1816973, hash 0ab0dd5c36c6eb480b8bbd05508be952c5ed8597a4e422af25bd80a905a9368d

Dockerが修復されているかどうか、および修復されたバージョンは何ですか

修正されていませんが、 5.0.x (ただし、 5.0.2をお勧めします)には、Unicode NUL文字を含むtx_metadataを削除することで、この問題を回避する回避策があります。

このページは役に立ちましたか?
0 / 5 - 0 評価