VeilSwap
← All posts
インフラ2026-11-048 min read

サイトが落ちている間、あなたの資金はどこにあるのか

2026年10月23日、ホストが22分38秒にわたって停電しました。失われた注文はありません。入金アドレスは当社ではなく流動性ベンダーのものだからです。あわせて、あの503ページが実際に何を返すのか、オリジンが消えている間に対応ページが何を表示できるのかを実測しました。

2026年10月23日、veilswap.io を動かすホストが停電しました。カーネルログは08:48:05 UTCで途切れ、次の起動の最初の記録は09:10:43——その間22分38秒、オリジンサーバーは存在しませんでした。この窓から得られる2つの事実は、どんな安心材料より価値があります。第一に、08:40〜09:30 UTCの間に作成された注文は0件で、送金の途中で落ちた人はいませんでした。第二に、データベースは以前の全行を保ったまま戻りました。現在147件、期限切れ119、支払い済み21、失敗5、返金済み2です。障害はキャッシュに隠されていません。利用者が実際に尋ねるのはもっと小さくて難しい問いです——ページが開かないとき、資金はどこにあり、この注文をまだ確認できるのか。本ページは両方に実測で答えます。

そのメンテナンスページの正体。 名前を veilswap-maintenance とする Cloudflare の Worker で、オリジンには一切触れません。fetch ハンドラにパス分岐はなく、ページ要求もAPI要求もPOSTも、同じ 2,393 バイトの HTML を受け取ります。2026年11月4日10:04 UTCの実測:HTTP 503、content-type は text/html、cache-control は no-store, must-revalidate、retry-after 300、そして目印のヘッダー x-veilswap-maint: 1。5回のサンプルでTTFBは48〜125ミリ秒でした。応答はエッジで生成され、エッジから出ないからです。Accept-Language を zh-CN にすると同じページが 2,396 バイト、lang は zh-CN になります。POST も 503 です——メソッドも見ていません。

現れるまで10秒、消えるまで10秒。 スイッチは Worker ではなくルートです。veilswap.io/__maint-probe/* をスクリプトに紐づけると10秒以内に有効になり(t+5秒で404、t+10秒で503)、削除も同じでした(t+5秒で503、t+10秒で404)。重要なのは、この循環の半分しか自動化されていない点です。監視スクリプトが5分ごとに走り、ホスト内部からオリジンを確認し(ポート3001はファイアウォールでDROPされているため、外部からの curl は常に000)、アプリが200を返したらメンテナンスルートを削除します。追加は手作業です。これが正直に認めるべき欠落であり、あの誠実な503ページが必ず出るとは言えない理由です。誰もルートを張らなければ、訪問者が見るのは Cloudflare の 522 で、522 は何も説明しません。

メンテナンス中、注文ページはスケルトンだけになる。 /order/<id> は 32,795 バイトの空殻で、状態は HTML に含まれず、ブラウザが /api/order/<id> から取得します。メンテナンスルートが有効なとき、そのAPIパスも同じ 503 HTML を返します——推測ではなく実測です。Worker に /api 用の分岐がないからです。クライアント側のロジックはコンポーネントに書かれています:応答が ok でなければ即座に戻り、5秒ごとにポーリングを続けます。注文オブジェクトは null のままなので、画面は灰色のプレースホルダーに留まります。エラー文言もラベルも説明もありません。その本文を JSON パーサーに渡せば、先に例外になります。これは意図した取引です。停止中に書き込みを止めることで、仮設環境が実注文を作らないようにしています。代価も明確で、オリジンが落ちている間は照会するものが本当にありません。オフライン照会にはデータベースの複製が別の場所に必要で、当社にはそれがありません。

コインはその機械の上にあったことはありません。 VeilSwap はノンカストディアルで、コードはその言葉を文字どおりにしています。注文の入金アドレスは、見積りを行った流動性ベンダーが返した payinAddress です。当社はその鍵を持ちません。だからオリジンが落ちても入金アドレスは機能し続けます——ベンダー自身のインフラが監視しており、停止中に送られた入金は当社ではなくベンダーが計上します。当社が持つのは1行のレコードです:注文ID、ベンダー注文ID、金額、アドレス、状態。その行が後にページへ戻る種になります。同時に、唯一本当に悪いケースも説明します——注文IDを失うことです。それがなければ行を探すのは難しく、フロー内で「両替に影響はない」と言える唯一の画面が404のフォールバックです。

3つの障害、3つの症状。 オリジン停止:エッジからの503、全パス、48〜125ミリ秒、メンテナンスの文言。オリジンは生きていてベンダーAPIが落ちている:/api/order は200を返し、DBに残る最後の状態と pollError フィールドを含み、注文ページには「状態同期が遅れています」という琥珀色のバナーが出ます。ポーリングは続き、終端状態を捏造しません。あなたの回線が落ちている:何も解決せず、このホストから測った1.11秒という見積り時間は基準になりません。切り分けが重要なのは、助言が正反対だからです。1つ目は待ってリンクを保持。2つ目は再送しない——入金はすでにベンダーで計上されているかもしれません。3つ目は経路を変えるのであって、注文を変えるのではありません。

状態はどうやって自力で戻るのか。 cron が5分ごとに vs_sweep.sh を実行し(ログに ok:true と各カウンタを記録)、終端でない全注文を、作成時に保存したベンダー注文IDで再ポーリングします。ローカル時計は作成から30分。ベンダーがまだ入金待ちと言えば、その行は local_timeout の印を付けて期限切れになります——本日147件のうち87件がこの印を持っています。2回目の走査は6時間遡り、ローカルで失効したが後にベンダーが入金を確認した注文を支払い済みに戻します。ベンダーがまったく見つけられない注文は24時間で強制失効します。正直な注記:この6時間の復旧経路で記録された実例は現時点で0件です。実績ではなく仕組みとして扱ってください。

ハッシュは、あなたが見ている間だけ存在する。 完了した注文が返すのは状態、ベンダー状態、金額、アドレス、validUntil で、トランザクションハッシュは含まれません。2026年11月4日に支払い済み注文で実測したとおりで、データベースのスキーマにもハッシュ列はありません。したがって注文が終端状態になると、ハッシュは当社側から消えます。残るのはベンダーの記録とあなたのウォレットだけです。ここには隠さず指摘すべき小さな矛盾があります。メンテナンスページは「復旧後、注文リンクは同じ状態とトランザクションハッシュを表示します」と約束しています。状態は表示されます。ハッシュは表示されません。送金した瞬間に自分のウォレットから、あるいは確認中のうちに注文ページから txid を控えてください。

障害の日にやるべき6つ。 1つ、注文リンクを保持する。それが唯一の鍵です。2つ、ウォレットを閉じる前に自分のウォレットから入金 txid を控える。3つ、同じ支払いに対して2つ目の注文を作らない——元のアドレスは今も機能します。4つ、画面が灰色だからと再送しない。まずチェーンを確認する(BTC、TRC20、ZEC、LTC には公開エクスプローラーがあります。XMR にはないので、モネロはベンダーアドレスの動きが唯一の外部確認手段です)。5つ、復旧したらリンクを10分あけて2回開く——動く状態が生きている状態です。6つ、それでもおかしければ、注文リンクと txid を添えて [email protected] へ。このメールボックスは別のインフラで動いており、オリジン障害の影響を受けません。 (ZcashとMonero 2026比較)

当社が約束しないこと。 あの誠実な503ページが必ず出るとは約束しません。ルートを張るのが今も手作業だからです。オフラインでの注文照会も約束しません。データベースはオリジン上の1部しかなく、毎日04:00 UTCのバックアップは復旧のためのもので、照会に供するものではないからです。開いたままのページが再起動を越えるとも約束しません。ポーリング先は、たった今落ちたオリジンそのものだからです。成り立つのはもっと狭く、検証できることです。入金アドレスはベンダーのもの、注文行は WAL 付き SQLite に残る、ポーリングはベンダーIDで再開する、完了した両替はチェーン上の事実で、当社もベンダーも書き換えられません。ページとチェーンが食い違うときは、チェーンが正しい。

Frequently asked questions

サイトが落ちている間、資金はどこにありますか?

注文に対して流動性ベンダーが発行した入金アドレスにあり、当社はその鍵を一度も持っていません。したがって当社側の障害では動きません。停止中に送った入金はベンダーが計上し、オリジン復旧後に当社の注文行がベンダーの注文IDでポーリングを再開します。

メンテナンスページが出ている間、注文状況を確認できますか?

できません。メンテナンス Worker にはパス分岐がなく、/api/order/<id> もトップページと同じ HTML 503 を返します(2026年11月4日実測)。注文ページは灰色のスケルトンに戻り、5秒ごとに再試行します。これは意図的で、停止中に書き込みを止めることで、仮設環境が実注文を作らないようにしています。

入金したのに、なぜ注文が期限切れになるのですか?

当社のローカル時計は注文作成から30分ですが、ベンダーは独自の期限を持ち、当社の期限が過ぎてもまだ待っていることがあります。行は local_timeout の印を付けて期限切れになり、その後6時間の遡及確認でベンダーが入金を報告した時点で支払い済みに戻ります。その間に再送しないでください。正直な注記:この復旧経路で記録された実例は現時点で0件なので、実績ではなく仕組みとして扱ってください。

Ready to swap?

No account · No KYC · No email

Exchange now
サイトが落ちている間、あなたの資金はどこにあるのか — VeilSwap