1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
|
# Urbit Pills: When They're Used
## The Two-Pill System
C Vere uses **two different pills** for different purposes:
### 1. Ivory Pill (Always Loaded)
**When**: At **every startup**, before any ship operations
**Where**: Embedded in the binary as `u3_Ivory_pill[]` byte array
**Size**: ~1.5 MB (jammed)
**Load Time**: ~0.2 seconds (C Vere), ~0.44 seconds (OCaml)
**Boot Sequence**:
```c
u3_king_commence() // King process entry point
→ _king_boot_ivory() // Load ivory pill
→ u3s_cue_xeno() // Deserialize from embedded bytes
→ u3v_boot_lite() // Run lifecycle formula
→ u3v_life() // Execute [2 [0 3] [0 2]]
→ [start event loop] // Continue with normal operations
```
**What It Contains**:
- The **%zuse core** (Hoon standard library)
- Structure: `["ivory" <core>]` (tagged pair)
- All stdlib functions: `++by`, `++so`, `++enjs`, `++dejs`, etc.
**Why It's Needed**:
C Vere's I/O drivers (Ames, Behn, Clay, Dill, Eyre, Iris) need to call Hoon functions:
- Parse HTTP requests
- Format JSON responses
- Hash/sign packets
- Serialize data structures
Rather than reimplementing these in C, Vere loads ivory once and calls into it via `u3v_wish()`:
```c
// C code in Eyre driver needs to format JSON
u3_noun json = u3v_wish("(enjs:format some-data)");
```
This keeps the runtime in sync with Hoon and avoids duplicating the entire stdlib.
### 2. Brass/Solid Pill (Only for New Ships)
**When**: Only when **booting a new ship**
**Where**: Downloaded from `https://bootstrap.urbit.org/git-<hash>.pill`
**Size**: ~8-170 MB (varies by version)
**Load Time**: ~1.5 seconds for solid (C Vere)
**Boot Sequence**:
```c
urbit -F zod // User boots new fake ship
→ _king_boot() // Handle boot command
→ _boothack_pill() // Get pill (download or --pill arg)
→ _king_get_atom("https://bootstrap.urbit.org/...")
→ u3v_boot() // Process boot events
→ Process 5 events: +aeon, +boot, +fate, +hoon, +arvo
→ Result: Full Arvo kernel in u3A->roc
→ [continue with ship operations]
```
**What It Contains**:
- Structure: `[tag [event1 event2 event3 event4 event5]]`
- **Boot events** that build full Arvo when processed:
1. `+aeon`: Start event loop
2. `+boot`: Bootstrap Arvo kernel
3. `+fate`: Produce Hoon bootstrap compiler
4. `+hoon`: Produce compiler source
5. `+arvo`: Produce kernel source
**Result**: A complete Arvo kernel with:
- All vanes (Ames, Behn, Clay, Dill, Eyre, Gall, Iris, Jael, Khan)
- Full poke/peek interface (slot 23)
- Event processing capability
- Persistent state
**Pill Types**:
- **Brass**: Full recompilation of vanes (~170 MB for prod.pill)
- **Solid**: Pre-compiled vanes, faster boot (~8.7 MB)
- **Baby**: Minimal pill for testing
## Summary Table
| Aspect | Ivory | Brass/Solid |
|--------|-------|-------------|
| **When** | Every startup | New ship boot only |
| **Where from** | Embedded in binary | Downloaded/provided |
| **Size** | ~1.5 MB | ~8-170 MB |
| **Contains** | %zuse stdlib | Boot events |
| **Purpose** | I/O driver support | Create Arvo kernel |
| **Result** | Runtime utilities | Full operating system |
| **Frequency** | Always | Once per ship lifetime |
| **Stored in** | `u3A->roc` (lite) | `u3A->roc` (full) |
## Key Insight
**Ivory is not Arvo** - it's just the Hoon stdlib compiled into a pill.
You cannot:
- ❌ Poke ivory with events
- ❌ Run vanes on ivory
- ❌ Use ivory as a ship OS
You can:
- ✅ Call Hoon stdlib functions from C/OCaml
- ✅ Parse/format data using Hoon code
- ✅ Avoid reimplementing stdlib in runtime language
**Brass/Solid creates Arvo** - processing the boot events builds the full OS.
Once processed:
- ✅ Full event processing
- ✅ Poke interface at slot 23
- ✅ All vanes running
- ✅ Persistent state
## Performance Comparison
### Ivory Pill (1.5 MB)
```
C Vere: 0.21 seconds (6.88 MB/s)
OCaml: 0.44 seconds (3.41 MB/s)
Ratio: 2x slower ✅ Acceptable!
```
### Solid Pill (8.7 MB)
```
C Vere: 1.45 seconds (6.0 MB/s)
OCaml: >300 seconds (0.03 MB/s)
Ratio: ~200x slower ❌ Blocker
```
The performance gap grows non-linearly with size/complexity, suggesting algorithmic issues in the OCaml cue implementation (see `ARVO_CHALLENGE.md`).
## For OCaml Implementation
### What We Have ✅
Ivory pill loading:
- Load ivory pill (0.44s vs C's 0.2s = 2x slower, acceptable)
- Validate "ivory" tag (`0x79726f7669` = "ivory")
- Implement `u3v_life()` lifecycle formula `[2 [0 3] [0 2]]`
- ❌ Lifecycle execution fails (Nock exits - still debugging)
### What We Need ⏳
For full Arvo:
1. **Fast cue** for solid pill (currently ~200x slower, blocker)
2. **Process 5 boot events** to build Arvo
3. **Result**: Working Arvo kernel with poke interface
### What Ivory Enables 🎯
Even without full Arvo, ivory pill lets us:
- Test I/O drivers with real Hoon code
- Implement `wish()` to call into Hoon
- Validate jam/cue correctness on real data
- Benchmark Nock performance on stdlib code
But for **full ship operation** with vanes and event processing, we need solid pill boot.
## Bootstrap Flow for New Ship
```
User runs: urbit -F zod
1. King process starts
├─ Load embedded ivory pill (0.2s)
├─ Run u3v_life() on ivory
└─ u3A->roc = %zuse core
2. User command triggers new ship boot
├─ Download brass pill from bootstrap.urbit.org
├─ Cue pill (1.5s for solid, 30s+ for brass)
├─ Extract 5 boot events from pill
└─ Process events sequentially:
├─ +aeon: Initialize event loop
├─ +boot: Bootstrap Arvo
├─ +fate: Create Hoon compiler
├─ +hoon: Load compiler source
└─ +arvo: Load kernel source
3. Result: Full Arvo kernel
├─ u3A->roc now contains complete Arvo
├─ All vanes loaded and running
├─ Poke interface active at slot 23
└─ Ship ready for normal operation
4. Subsequent startups
├─ Load ivory (still needed for I/O)
├─ Load ship state from snapshot/eventlog
└─ No pill download needed
```
## Source Code References
- Ivory embedded: `pkg/vere/ivory/ivory.c:2` (`u3_Ivory_pill[]`)
- Ivory boot: `pkg/vere/king.c:962` (`_king_boot_ivory()`)
- Lifecycle: `pkg/noun/vortex.c:26` (`u3v_life()`)
- Pill download: `pkg/vere/king.c:600` (bootstrap URL generation)
- Boot events: `pkg/vere/king.c:606` (`_boothack_pill()`)
|