aboutsummaryrefslogtreecommitdiffstats
path: root/docs
diff options
context:
space:
mode:
authoreunhhu <[email protected]>2026-09-27 19:45:25 +0100
committereunhhu <[email protected]>2026-09-27 19:45:25 +0100
commitbac70f376ef539a03a25e187f706fe8f9f67f01e (patch)
treedb8339687c2858477e2d23bb61509b85c3dafd99 /docs
parentd72f57af85bb57042332da8bc002a2a0640639a0 (diff)
downloadpure-bac70f376ef539a03a25e187f706fe8f9f67f01e.tar.gz
pure-bac70f376ef539a03a25e187f706fe8f9f67f01e.zip
Record the messenger between two nodes and its latency (089)
The roadmap's E2EE messenger made of the runtime's general parts, with no messenger code in it: sealed, authenticated sessions between nodes (086, 088), Vega on each node's display as a surface (design 010), the app in Vega's examples. Vega's check runs two nodes through a recording relay: a line typed on one display is drawn on the other, frames match the vega command's, and the relay sees no text. A line takes 0.79 ms at p50 and 1.1 ms at p99 from one node's program to the other node's views with stores in RAM, both commits, the HTTP delivery and the seal included (sealing adds nothing measurable); on the Pi's SD card 3.5 ms at p50, the long tail being the card's syncs.
Diffstat (limited to 'docs')
-rw-r--r--docs/research/089-messenger.md80
1 files changed, 80 insertions, 0 deletions
diff --git a/docs/research/089-messenger.md b/docs/research/089-messenger.md
new file mode 100644
index 0000000..a74107d
--- /dev/null
+++ b/docs/research/089-messenger.md
@@ -0,0 +1,80 @@
+# 089 — 메신저: 두 노드, 끝에서 끝까지 봉인, 노드 안의 화면
+
+2026-09-27. 로드맵의 "E2EE 초저지연 메신저"를 런타임 쪽 능력으로 처음 끝까지 이은 것. 앱은 Vega의
+`examples/messenger.aup`이다(앱 기능은 런타임 밖에 둔다). 여기서는 런타임이 무엇을 주고 얼마나 걸리는지를 적는다.
+
+착수 기준:
+
+- 바꿀 결정: 메신저를 이루는 것(봉인한 전달, 보낸 이 인증, 사람이 쓰는 화면, 그 사이의 지연)을 런타임의 일반 능력으로 줄지,
+ 메신저 전용 코드로 만들지. 전용 코드는 쓰지 않는다. 086·088의 봉인 전달과 설계 010의 표면으로 된다는 것을 보인다.
+- 최소 확인: 두 노드가 서로에게 봉인해 보내고, 한쪽 화면에서 친 줄이 다른 쪽 화면에 그려지며, 사이의 중계는 평문을 보지
+ 못한다는 것을 검사로 지킨다. 한 줄이 상대 노드에 보이기까지의 시간을 봉인 유무와 저장 장치별로 잰다.
+- 중단 기준: 메신저를 위해 런타임에 앱 전용 개념(대화, 연락처)을 넣어야 한다면 멈추고 다시 설계한다.
+
+## 이어진 것
+
+| 로드맵이 말한 것 | 무엇으로 |
+|---|---|
+| 끝에서 끝까지 암호(E2EE) | HPKE 봉인(RFC 9180). 전달선마다 세션 하나, 보내는 노드의 키로 auth 모드([088](088-sealed-sessions.md)) |
+| P2P | 노드에서 노드로. 중계·프록시가 사이에 있어도 읽지도 바꾸지도 못한다([086](086-sealed-sends.md)) |
+| 하드웨어 암호 직결 | CPU에 AES 명령이 있으면 AES-128-GCM(이 A76에서 ChaCha20-Poly1305의 2–3배), 없으면 ChaCha20-Poly1305 |
+| 메모리 포렌식 면역 | 연 평문은 요청 티켓이 반납될 때 0으로 지운다. 개인키는 OpenSSL 보안 힙에 둔다(잠김, 코어 덤프 제외, 해제 때 지움) |
+| 화면 | 노드 안의 Vega([설계 010](../design/010-surfaces.md)). 마지막 저장을 제자리에서 읽고, 친 키와 글자는 소유자의 줄로 |
+
+앱은 이렇게 생겼다. 줄 목록 상태, 화면에서 치는 텍스트 입력 `say`, 상대 노드가 보내는 메시지 입력 `heard`, 상대에게 가는
+출력 `said`다. `on say`가 줄을 더하고 `send said`한다. 노드는 이렇게 연결한다.
+
+```sh
+pure-serve --module messenger.pmod --store alice --key alice.key --name alice \
+ --send said=http://bob:8802/inputs/heard --seal said=BOB_KEY --sender bob.said=BOB_KEY \
+ --surface vega-surface.so -- display --symbols ui.vsym --live
+```
+
+런타임에 들어간 메신저 전용 코드는 없다. 대화와 연락처는 앱의 상태이고, 보낸 이는 전달의 출처와 키이며, 화면은 표면이다.
+
+## 검사
+
+Vega의 `tests/check.py`의 `messenger`는 앨리스와 밥의 노드를 띄운다. 각자 제 키를 갖고, 서로에게 봉인하며, 상대만을 보낸
+이로 받는다. 둘 사이에는 기록하는 중계를 둔다. 각 노드에는 Vega가 픽셀 표면으로 들어 있어, 저장마다 한 프레임을 파일로
+그린다.
+
+1. 앨리스의 화면에 녹화한 키로 "hello bob"과 Enter를 친다.
+2. 밥의 노드가 그 줄을 보인다.
+3. 밥은 프로그램으로(HTTP) "hi alice"를 보낸다.
+4. 앨리스의 노드와 화면에 그 줄이 그려진다.
+
+검사는 다음을 확인한다.
+
+- 두 노드의 마지막 프레임이 각 노드의 저장소를 `vega pixels`로 다시 그린 것과 바이트까지 같다.
+- 중계가 본 본문에는 줄의 글자도 필드 이름도 없다.
+- 방향마다 봉인 세션 하나가 있고, 봉인은 보낸 이의 키를 적는다.
+
+Vega 검사 25개 모두와 함께 통과한다.
+
+## 지연
+
+한 프로그램이 앨리스의 노드에 줄 300개를 하나씩 보내고 둘을 잰다. 하나는 앨리스의 노드가 저장해 답할 때까지이고, 다른
+하나는 밥의 노드가 그 줄을 보일 때까지다(밥의 제목 보기를 0.2 ms마다 읽는다). 두 노드는 직접 연결했다. 서버는 코어 0–2를
+쓰고, 변형의 순서는 라운드마다 돌렸다([latency.py](../../research/experiments/015-messenger-latency/latency.py),
+[원시 결과](../../research/experiments/015-messenger-latency/2026-09-27-sd-and-ram-linux-aarch64.jsonl)).
+
+| 저장소 | 봉인 | 앨리스 저장 p50 | 밥에게 보임 p50 | p90 | p99 |
+|---|---|---:|---:|---:|---:|
+| RAM(`/dev/shm`) | 봉인·인증 | 0.34 ms | **0.79 ms** | 0.82–0.83 ms | **1.09–1.13 ms** |
+| RAM | 없음 | 0.33 ms | 0.78 ms | 0.81–0.84 ms | 0.89–1.05 ms |
+| SD 카드(ext4) | 봉인·인증 | 1.64–1.72 ms | 3.45–3.69 ms | 6.7–6.8 ms | 62–78 ms |
+| SD 카드 | 없음 | 1.65–1.84 ms | 3.42–3.72 ms | 6.6–10.0 ms | 62–84 ms |
+
+한 줄이 두 노드의 내구 커밋 두 번, HTTP 전달 하나, 봉인과 열기를 거쳐 상대에게 보이기까지 1 ms 안쪽이다. 봉인의 몫은 잡음
+안이다. SD 카드의 긴 꼬리는 동기화 자체다. 앨리스의 저장 p99가 이미 20–66 ms이고, 밥의 저장이 또 하나를 더한다. 소프트웨어가
+줄일 몫이 아니다. NVMe 같은 장치에서는 RAM 쪽에 가까울 것이다(잴 장치가 아직 없다).
+
+## 한계와 다음
+
+- **전방 비밀성**: 없다. 받는 노드의 키를 훔치면 기록해 둔 세션이 열린다. 받는 키를 돌려 쓰기(서명한 사전 키)가 다음이다.
+- **보낸 이 인증**: auth 모드는 키 누설 사칭(KCI)에 약하다. 받는 노드의 키를 가진 쪽은 그 노드에게 누구로든 보낼 수 있다(088).
+- **오프라인**: 받는 노드가 꺼져 있으면 보내는 노드의 보낼 함(저장된 send)이 기다린다. 두 노드가 동시에 켜져 있어야 간다.
+ 늘 켜진 우편함 노드(봉인한 요청을 열지 않고 맡아 두었다 전하는 것)가 다음 후보다.
+- **여럿**: 한 출력은 한 수신자에게 간다. 연락처가 여럿이면 필드로 수신자를 고르는 전달이 필요하다.
+- **메타데이터**: 출처, 번호, 크기, 보낸 이의 공개키가 중계에 보인다.
+- **화면**: 노드 안의 표면은 키와 글자만 준다. 가리키기(터치로 행 고르기)는 표면 표에 아직 없다.