C-2 Validator Independence


C-1/C-3/C-4 は「ノードがレコードを読む側」の独立性でした。C-2 はバリデータ――署名アクションを検証し、バッチにしてチェーンへ書く側――を扱います。論点は3つ:#16 誰でもバリデータになれるか(承認)#17 単一バリデータが署名アクションを検閲できるか#18 別バリデータが公開入力から同じキューを再構築できるか。ここは正直に言うと、3つのうち2つは明確に検証済み、1つ(#18)は設計通り――調べ切った結果、再構築できないのが意図的な設計だと確認できた項目です。

やさしく言うと

バリデータは、ユーザーが署名した手紙を束ねて公共の掲示板(チェーン)に貼る公証人のような役です。誰でも公証人になれるか(#16)、ある公証人が貼るのを拒んでも別の人が貼れるか(#17)、そして貼られる前の順番待ちの列を外部から同じに再現できるか(#18)――を確かめます。

ユーザー署名アクションEIP-712

誰でも登録・誰でも提出承認ゲート無し

検閲不能/確定順序は再現可保留列は open door

結果:登録も提出も全段で許可不要、署名アクションは誰でも(本人でも)提出できるので単一バリデータは検閲できない。確定したアクションの順序は再構築可能(C-3)。ただし保留中の列を公開入力だけから厳密に再現する公開 gossip は無く、ここは open door として残します。

このページは検証台帳C-2 項目の詳細記録です。#16・#17 を検証済みとし、#18(保留キュー再構築)は「設計通り」(意図的に再構築不可)として、正直に区別して記録します。

1. 主張(検証対象)

#16 バリデータ参加(クライアント作成・インスタンス登録・バッチ送信)が許可不要であること。#17 署名アクションを単一バリデータが検閲できないこと。#18 別バリデータが公開入力から同じキューを再構築できること。

2. 検証方法

1

#16 提出経路の呼び出しゲートを読む

デプロイ済み契約(live V1)の processActions、および createClientregisterInstance に、運営による承認ゲートがあるかをソースで確認。

2

#17 検閲できる単一点があるか

署名アクションを「誰が提出できるか」を確認。特定バリデータに限定されるなら検閲点、誰でも(本人でも)提出できるなら検閲不能。client 側のピアミラー機構も確認。

3

#18 保留キューの入口と共有方法

保留アクションがどこから入り、外部バリデータがそれを公開入力から再構築できるか(公開 gossip/mempool の有無)を確認。

3. 判定

バリデータ参加は全段で許可不要。署名アクションは誰でも提出でき、単一バリデータは検閲できない。確定順序は再構築可能。
createClientregisterInstanceprocessActions のいずれにも承認ゲートが無く、安全性は各アクションの EIP-712 署名。保留キューを公開入力だけから厳密再構築することは意図的にできない設計で、#18 は「設計通り」(中央集権の穴ではない)。

  • #16 許可不要 createClientpublic)・registerInstance(ゲート無)・processActions(caller 無制限)。validatorId は帰属パラメータのみ。私の instanceId 232(本番レジストリ上・owner=自ノードの validator 0x4fe9…380D)が自己登録の実例で、さらにランダム住所からの登録 simulate が新 id(475)を返す=今も許可不要をライブ実証。
  • #17 検閲耐性 署名アクションは誰でも・本人でも提出可(安全性は EIP-712 署名)。さらに client 側のピアミラーvalidated_by_peer/”peer mirror submitted”)が冗長化し、単一バリデータは検閲不能。
  • #18 部分 確定順序はオンチェーンで canonical=再構築可(C-3)。一方保留キューは各ノード API→TxQueue でピア間ミラーされるが、任意外部からの厳密再構築用の公開 gossip は無し=open door。
この検証が示すこと/まだ示せないこと

示せたこと:バリデータ層は許可不要かつ検閲耐性あり。クライアント作成→インスタンス登録→バッチ送信のどこにも運営の承認ゲートは無く、提出は msg.sender 無制限で各アクションの署名だけが効く。あるバリデータが出さなくても、別ピアやユーザー本人が提出でき、ピアミラーが自動で冗長化します。

まだ示せないこと(open door)= #18:保留中のアクション列を公開入力だけから外部が厳密に再構築することはできません。理由は2つあり、いずれも設計上の意図です:(1) 公開 API で吸い出せない――/txqueue/status は認証必須かつ自分の senderId 分のみ返す(監査修正 Round 5 API MED-1:誰でも連番 id を列挙して署名済みペイロード〔受信者・金額・予約チップ〕を吸い出すのを防ぐプライバシー保護)。(2) グローバルな保留 mempool が存在しない――保留は各ノードの TxQueue にローカルに入り、FE が署名アクションを複数ピアへ fan-out して競争提出する方式で、全体像を持つ単一主体がいない。したがって #18 は「中央集権の穴」ではなく、プライバシー+分散提出による意図的な非再構築です。確定後(オンチェーン)の順序は C-3 で再構築可能、検閲耐性(#17)はこの欠如と独立に成立。文字どおりの「厳密再構築」要件は原理的に未達ですが、それが意図的な健全設計と確認できたため #18 は「設計通り」に分類します(欠陥ではない)。両ノードの運用者が同一である点も C-1C-3 と共通。

結論:§19 #16・#17 は満たされ、#18 は「確定順序=再構築可/保留キュー=公開再構築は未達」の部分。検閲耐性(#17)は提出経路が開いていることに由来し、#18 の保留 gossip 欠如とは独立に成立します。契約は live V1(commit a26e0063)、client は e2074718 時点・2026-06-23。

4. receipt(公開証明)

提出経路と登録の許可不要性(デプロイ済み契約のソース):

対象 可視性/ゲート 意味
processActions(validatorId, packedActions, sigs, …) external payable
(caller 無制限)
誰でもバッチ提出可。validatorId は帰属、安全性は "Sigs don't cover all actions"(EIP-712)
createClient(…) public(ゲート無) クライアント作成は許可不要
registerInstance(clientId, apiUrl, validatorAddress) ゲート無
nextInstanceId++
インスタンス登録は許可不要。instanceOwner[id]=msg.sender
updateInstance / deactivate / activate instanceOwner==msg.sender 自分のインスタンスのみ変更可(正当な所有権ゲート)

processActions 内の msg.sender チェックは内部 self-call ガードのみで、外部呼び出しを制限しません:

CawActions.sol  processActions(...) external payable   # 呼び出しゲート無し
  require(c.actionsSeen == actionCount, "Sigs don't cover all actions")  # 署名で担保
  require(msg.sender == address(this), "Only self")    # 内部 self-call のみ(外部制限ではない)

#16 のライブ実証:本番 CawClientManager(L1 Sepolia, 0xA5C515…1424C7a)への eth_call(state 変更なし)。無関係なランダム住所を from に登録を simulate し、新 id が返れば誰でも登録できる証拠です:

# 本番 CawClientManager(L1 Sepolia)への eth_call
nextInstanceId()                       # → 475(474 件登録済みの稼働レジストリ)
instanceOwner(232)                     # → 0x4fe9…380D(私の node1 validator=232 は自分の自己登録)
registerInstance(1,…) from=0x…DeAdBeef # → 475(新 id 返却)=client 1 存在・caller ゲート無し=今も許可不要

#17 のピアミラー(単一バリデータが出さなくても別ピアが提出):

ValidatorService/index.ts   status: 'validated_by_peer'                 # ピアが検証
  "action already on chain (peer mirror submitted) — marking done"        # 別ピアが提出して冗長化

#18 の線引き(確定順序と保留キュー):

確定順序(オンチェーン)C-3 で再構築可 ✓
保留キュー(API→TxQueue)公開 gossip 無し=open door

5. 注記・限界

#18 が本項目最大の open doorです。保留列を公開入力だけから厳密再構築することは原理的にできませんが、これは2つの設計意図によります:(1) /txqueue/status は認証必須+自分の senderId 分のみ返す(監査修正によるプライバシー保護)、(2) グローバル保留 mempool が無く、各ノード TxQueue+FE の複数ピア fan-out で分散提出される。よって中央集権の穴ではなく、意図的な非再構築です。確定後の順序は C-3 で再構築可能で、検閲耐性(#17)はこの欠如とは独立に成立します。

なお validatorId には手数料の帰属がぶら下がるため、提出には経済的インセンティブの設計が絡みますが、提出そのものを構造的に妨げるゲートは無い(本人提出も可)という事実が #17 の根拠です。

対象はオンチェーンのアクション。DM・画像はオフチェーン、Base L2 シーケンサ依存、両ノード運用者が同一である点は C-1C-3 と共通の open door です。

開いた門は、閉じた門より証明が要る。
誰でも入れることを示し、誰も閉め出せないことを示し、まだ見通せない奥の列は、見通せないと正直に書く。

C-1 / C-3 / C-4 covered the independence of the side that reads the record. C-2 is about the validator — the side that verifies signed actions, batches them, and writes them to the chain. Three questions: #16 can anyone become a validator (approval), #17 can a single validator censor signed actions, and #18 can a different validator reconstruct the same queue from public inputs. Honestly: two of the three are clearly verified, and one (#18) is by design — examined and found to be an intentional design, not a defect.

In plain terms

A validator is like a notary who bundles user-signed letters and posts them to a public board (the chain). We check whether anyone can become a notary (#16), whether someone else can still post a letter if one notary refuses (#17), and whether an outsider can reconstruct the exact waiting line before posting (#18).

user-signed actionEIP-712

anyone registers / submitsno approval gate

uncensorable / settled order reproduciblepending line is an open door

The result: registration and submission are permissionless at every stage, and because signed actions can be submitted by anyone (including the user), no single validator can censor. The settled action order is reconstructable (C-3). But there is no public gossip to reconstruct the pending line exactly from public inputs — that remains an open door.

This page is the detailed record for item C-2 of the Verification Ledger. It marks #16 and #17 as verified and classifies #18 (pending-queue reconstruction) as “by design” (intentionally non-reconstructable, not a defect).

1. Claim (what is verified)

#16 that validator participation (client creation, instance registration, batch submission) is permissionless; #17 that a single validator cannot censor signed actions; #18 that a different validator can reconstruct the same queue from public inputs.

2. Method

1

#16 read the call gates on the submission path

Confirm in source whether the deployed (live V1) processActions, and createClient / registerInstance, have any operator approval gate.

2

#17 is there a single point that can censor

Confirm who can submit a signed action. Restricted to a specific validator = a censorship point; submittable by anyone (including the user) = uncensorable. Also check the client-side peer-mirror mechanism.

3

#18 the pending queue’s entry and sharing

Confirm where pending actions enter and whether an external validator can reconstruct them from public inputs (is there a public gossip/mempool).

3. Verdict

Validator participation is permissionless at every stage. Signed actions can be submitted by anyone, so a single validator cannot censor. The settled order is reconstructable.
None of createClient / registerInstance / processActions has an approval gate; security rests on each action’s EIP-712 signature. Reconstructing the pending queue exactly from public inputs is intentionally not possible by design — #18 is “by design” (not a centralization gap).

  • #16 permissionless createClient (public), registerInstance (no gate), processActions (caller unrestricted). validatorId is an attribution param only. My instanceId 232 (on the production registry, owner = my node’s validator 0x4fe9…380D) is a real self-registration, and a register simulation from an unrelated random address returns a fresh id (475) — still permissionless, confirmed live.
  • #17 uncensorable Signed actions can be submitted by anyone, including the user (security is the EIP-712 signature). The client-side peer mirror (validated_by_peer / “peer mirror submitted”) adds redundancy, so a single validator cannot censor.
  • #18 partial The settled order is canonical on-chain = reconstructable (C-3). The pending queue enters via each node’s API → TxQueue and is mirrored among peers, but there is no public gossip for exact external reconstruction = open door.
What this proves / what it does not yet prove

Proven: the validator layer is permissionless and censorship-resistant. There is no operator approval gate anywhere from client creation to instance registration to batch submission; submission is msg.sender-unrestricted and only each action’s signature counts. If one validator withholds, another peer or the user can submit, and the peer mirror adds redundancy automatically.

Not yet proven (open door) = #18: an outsider cannot reconstruct the pending action line exactly from public inputs. There are two reasons, both intentional design: (1) the public API won’t dump it/txqueue/status requires auth and returns only your own senderIds (audit fix Round 5 API MED-1: a privacy protection so no one can enumerate sequential ids and dump signed payloads — recipients, amounts, scheduled tips); (2) there is no global pending mempool — pending actions live in each node’s local TxQueue, and the FE fans each signed action out to several peers that race to submit, so no single party holds the whole picture. So #18 is not a centralization gap but an intentional non-reconstructability from privacy + distributed submission. The settled (on-chain) order is reconstructable via C-3, and censorship resistance (#17) holds independently. Since the literal “exact reconstruction” requirement is unattainable in principle and this is an intentional sound design, we classify #18 as “by design” (not a defect). That both nodes share one operator is the same open door as C-1 / C-3.

Conclusion: §19 #16 and #17 are met; #18 is partial — settled order reconstructable, pending-queue public reconstruction not yet. Censorship resistance (#17) follows from the open submission path and holds independently of the pending-gossip gap. Contracts at live V1 (commit a26e0063); client at e2074718, 2026-06-23.

4. Receipt (public proof)

The submission path and registration permissionlessness (deployed-contract source):

Target Visibility / gate Meaning
processActions(validatorId, packedActions, sigs, …) external payable
(caller unrestricted)
Anyone can submit a batch. validatorId is attribution; security is "Sigs don't cover all actions" (EIP-712)
createClient(…) public (no gate) Client creation is permissionless
registerInstance(clientId, apiUrl, validatorAddress) no gate
nextInstanceId++
Instance registration is permissionless. instanceOwner[id]=msg.sender
updateInstance / deactivate / activate instanceOwner==msg.sender Only your own instance can be changed (a legitimate ownership gate)

The msg.sender checks inside processActions are internal self-call guards only; they do not restrict external callers:

CawActions.sol  processActions(...) external payable   # no call gate
  require(c.actionsSeen == actionCount, "Sigs don't cover all actions")  # secured by signatures
  require(msg.sender == address(this), "Only self")    # internal self-call only (not an external restriction)

#16 live demonstration: an eth_call to the production CawClientManager (L1 Sepolia, 0xA5C515…1424C7a), no state change. Simulating registration with an unrelated random address as from; a fresh id returned proves anyone can register:

# eth_call to the production CawClientManager (L1 Sepolia)
nextInstanceId()                       # → 475 (a live registry with 474 instances)
instanceOwner(232)                     # → 0x4fe9…380D (my node1 validator = instanceId 232 is my own registration)
registerInstance(1,…) from=0x…DeAdBeef # → 475 (fresh id) = client 1 exists, no caller gate = still permissionless

#17’s peer mirror (another peer submits if one validator withholds):

ValidatorService/index.ts   status: 'validated_by_peer'                 # validated by a peer
  "action already on chain (peer mirror submitted) — marking done"        # another peer submitted, adding redundancy

#18’s boundary (settled order vs pending queue):

settled order (on-chain)reconstructable via C-3 ✓
pending queue (API→TxQueue)no public gossip = open door

5. Notes & limits

#18 is this item’s biggest open door. The pending line can’t be reconstructed exactly from public inputs — but for two intentional design reasons: (1) /txqueue/status requires auth and returns only your own senderIds (a privacy fix from the audit), and (2) there is no global pending mempool — actions live in each node’s TxQueue and the FE fans them out to several peers for distributed submission. So this is not a centralization gap but intentional non-reconstructability. The settled order is reconstructable via C-3, and censorship resistance (#17) holds independently.

Note that validatorId carries fee attribution, so submission involves economic-incentive design; but the fact that nothing structurally blocks submission (self-submission is allowed) is the basis for #17.

The scope is the on-chain action stream. DMs and images off-chain, the Base L2 sequencer, and both nodes sharing one operator are the same open doors as C-1 / C-3.

An open gate needs more proof than a closed one.
Show that anyone may enter, show that no one can be shut out, and say plainly when the line further in is not yet visible.
Copyright ©  CAW JAPAN.com All Rights Reserved.
PAGE TOP
夜の薔薇園へ