testnet
ネットワークでtags/5.0.0
、 extended
モードの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\"}"]
これは首の大きな痛みです。
挿入されている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
を削除することで、この問題を回避する回避策があります。
最も参考になるコメント
これは、一時的な修正で現在どのように見えるかです: