Skip to content

Commit 73e89a0

Browse files
authored
Create registry-program.md
1 parent 1cce4bd commit 73e89a0

1 file changed

Lines changed: 273 additions & 0 deletions

File tree

docs/onchain/registry-program.md

Lines changed: 273 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,273 @@
1+
2+
# On-chain Registry Program
3+
4+
This document specifies the SIGNIA on-chain **registry program**. The registry is a minimal Solana program that anchors SIGNIA bundle integrity roots on-chain.
5+
6+
It is intentionally small:
7+
- it stores schema hashes and optional proof roots
8+
- it records publisher identity
9+
- it supports status changes (active/revoked) with authority checks
10+
- it avoids storing large data on-chain
11+
12+
The registry does not:
13+
- store full schemas or manifests
14+
- execute compilation
15+
- validate complex proofs on-chain (verification is done off-chain; on-chain stores anchors)
16+
17+
---
18+
19+
## 1) Goals
20+
21+
1. Provide an immutable on-chain anchor for a schema hash (content-addressed identity).
22+
2. Optionally store proof root and manifest hash for additional linkage.
23+
3. Associate an anchor with a publisher (authority).
24+
4. Support revocation and metadata updates without breaking identity.
25+
5. Maintain a minimal, auditable on-chain surface area.
26+
27+
---
28+
29+
## 2) High-level design
30+
31+
### 2.1 Accounts
32+
33+
The registry uses program-derived addresses (PDAs):
34+
35+
1. `RegistryConfig` (singleton PDA)
36+
- stores admin authority and program configuration
37+
38+
2. `SchemaRecord` (one PDA per schema hash)
39+
- stores anchored hashes and publisher
40+
- stores status flags and timestamps/slots (optional)
41+
42+
### 2.2 Seeds
43+
44+
Recommended PDA seeds (illustrative):
45+
- `RegistryConfig`:
46+
- seeds: `["signia-registry-config"]`
47+
- `SchemaRecord`:
48+
- seeds: `["signia-schema", schema_hash_bytes]`
49+
50+
Rules:
51+
- use fixed ASCII seeds
52+
- include schema hash raw bytes (32 bytes)
53+
- avoid variable-length unbounded seeds
54+
55+
---
56+
57+
## 3) Stored fields
58+
59+
### 3.1 RegistryConfig
60+
Fields:
61+
- `admin`: Pubkey
62+
- `bump`: u8
63+
- `version`: u16
64+
- `flags`: u32 (reserved)
65+
- `reserved`: [u8; N] (future upgrades)
66+
67+
### 3.2 SchemaRecord
68+
Fields:
69+
- `schema_hash`: [u8; 32]
70+
- `proof_root`: [u8; 32] (optional, can be zeroed)
71+
- `manifest_hash`: [u8; 32] (optional, can be zeroed)
72+
- `publisher`: Pubkey
73+
- `created_slot`: u64
74+
- `updated_slot`: u64
75+
- `status`: u8 (0=active, 1=revoked)
76+
- `bump`: u8
77+
- `version`: u16
78+
- `flags`: u32 (reserved)
79+
- `reserved`: [u8; N]
80+
81+
Notes:
82+
- storing slots is optional but practical for indexing and audits.
83+
- use fixed-size arrays to keep account size stable.
84+
85+
---
86+
87+
## 4) Instructions
88+
89+
### 4.1 InitializeConfig
90+
Creates the `RegistryConfig` PDA.
91+
92+
Accounts:
93+
- `payer` (signer)
94+
- `admin` (pubkey, may be payer)
95+
- `config` PDA (writable)
96+
- `system_program`
97+
98+
Rules:
99+
- can only be called once (config must not exist)
100+
101+
### 4.2 RegisterSchema
102+
Creates a `SchemaRecord` PDA for a schema hash.
103+
104+
Inputs:
105+
- `schema_hash` (32 bytes)
106+
- optional `proof_root` (32 bytes or none)
107+
- optional `manifest_hash` (32 bytes or none)
108+
109+
Accounts:
110+
- `payer` (signer)
111+
- `publisher` (signer) — authority recorded in the record
112+
- `config` PDA (read-only)
113+
- `record` PDA derived from schema hash (writable)
114+
- `system_program`
115+
116+
Rules:
117+
- record PDA must not exist
118+
- schema_hash must be exactly 32 bytes
119+
- publisher must sign
120+
- status starts active
121+
122+
### 4.3 UpdateSchemaMetadata
123+
Allows the publisher (or admin, depending on policy) to update optional fields:
124+
- proof_root
125+
- manifest_hash
126+
- flags
127+
128+
Accounts:
129+
- `authority` (signer) — publisher or admin depending on policy
130+
- `config` PDA (read-only)
131+
- `record` PDA (writable)
132+
133+
Rules:
134+
- authority must match publisher OR admin (define policy)
135+
- update `updated_slot`
136+
137+
### 4.4 RevokeSchema
138+
Marks a schema record as revoked.
139+
140+
Accounts:
141+
- `authority` (signer) — publisher or admin depending on policy
142+
- `config` PDA (read-only)
143+
- `record` PDA (writable)
144+
145+
Rules:
146+
- authority must be publisher or admin
147+
- set status to revoked
148+
- update `updated_slot`
149+
150+
### 4.5 TransferPublisher (optional)
151+
Transfers publisher authority to a new pubkey.
152+
153+
Accounts:
154+
- `current_publisher` (signer)
155+
- `new_publisher` (pubkey)
156+
- `record` PDA (writable)
157+
158+
Rules:
159+
- current publisher must sign
160+
- new publisher pubkey is stored in record
161+
162+
---
163+
164+
## 5) Authority and policy
165+
166+
There are two common policies:
167+
168+
### Policy A: Publisher-only updates
169+
- only publisher can update metadata and revoke
170+
- admin exists only for initializing config
171+
172+
Pros:
173+
- stronger decentralization
174+
Cons:
175+
- no recovery if publisher key is lost
176+
177+
### Policy B: Admin override
178+
- publisher can update and revoke
179+
- admin can revoke or update in emergencies
180+
181+
Pros:
182+
- supports emergency response
183+
Cons:
184+
- introduces admin trust
185+
186+
Choose one policy and document it. Default recommendation for early stage:
187+
- Policy B with transparent governance.
188+
189+
---
190+
191+
## 6) Client integration
192+
193+
### 6.1 Deriving record address
194+
Clients derive the record PDA from schema hash bytes:
195+
- seeds: `["signia-schema", schema_hash_bytes]`
196+
197+
Then they fetch `SchemaRecord` and check:
198+
- schema hash matches
199+
- status is active
200+
- publisher matches expected authority (optional)
201+
202+
### 6.2 End-to-end verification flow
203+
1. Obtain SIGNIA bundle (schema.json, manifest.json, proof.json)
204+
2. Run `signia verify` off-chain to recompute:
205+
- schema hash
206+
- proof root
207+
- manifest hash (optional)
208+
3. Query on-chain registry for `SchemaRecord(schema_hash)`
209+
4. Compare on-chain stored hashes to recomputed hashes
210+
5. Accept bundle if:
211+
- record exists
212+
- status is active
213+
- hashes match
214+
215+
---
216+
217+
## 7) Security considerations
218+
219+
- Never store arbitrary user-controlled strings on-chain.
220+
- Prefer fixed-size hashes and pubkeys.
221+
- Validate PDA seeds and account ownership.
222+
- Ensure signer constraints are correct.
223+
- Enforce authority checks on updates and revocations.
224+
- Keep program small to reduce audit surface.
225+
226+
---
227+
228+
## 8) Program upgrades and versioning
229+
230+
- Include `version` fields in accounts.
231+
- Reserve bytes for future upgrades.
232+
- Use feature flags for new behavior.
233+
- If migrating accounts, define migration instructions and keep backward compatibility where possible.
234+
235+
---
236+
237+
## 9) Testing recommendations
238+
239+
- unit tests for PDA derivations
240+
- tests for register/update/revoke flows
241+
- negative tests:
242+
- wrong signer
243+
- wrong PDA
244+
- double initialization
245+
- register existing schema hash
246+
- size and serialization stability tests
247+
248+
---
249+
250+
## 10) Example JSON view (client-side)
251+
252+
This is a conceptual JSON view (not the on-chain representation):
253+
254+
```json
255+
{
256+
"schema_hash": "0123...abcd",
257+
"proof_root": "4567...cdef",
258+
"manifest_hash": "89ab...0123",
259+
"publisher": "Pubkey...",
260+
"status": "active",
261+
"created_slot": 123456789,
262+
"updated_slot": 123456999
263+
}
264+
```
265+
266+
---
267+
268+
## 11) Related documents
269+
270+
- Hashing: `docs/determinism/hashing.md`
271+
- Proof spec: `docs/schemas/proof-v1.md`
272+
- Threat model: `docs/security/security/threat-model.md`
273+
- Trust boundaries: `docs/security/security/trust-boundaries.md`

0 commit comments

Comments
 (0)