Skip to content

Commit cbfc111

Browse files
docs: convert architecture ASCII diagrams to mermaid
Replace the three ASCII diagrams in architecture.md with mermaid, each in the form that fits: a flowchart for the component/data-flow overview, a lifecycle flowchart for state management, and a sequence diagram for the end-to-end request flow. All three validated against mermaid 11. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
1 parent d8aebfc commit cbfc111

1 file changed

Lines changed: 81 additions & 56 deletions

File tree

docs/architecture.md

Lines changed: 81 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -6,23 +6,37 @@ komet-node is a local Stellar testnet whose execution engine is the [K formal se
66

77
The split between Python and K follows one rule: K does everything that is part of the Soroban/Stellar protocol, and Python does only what K structurally cannot. The compiled K semantics are a *one-shot interpreter* — one invocation runs one request to completion and exits, with no network, no memory between invocations, and no decoder for Stellar's binary XDR format. Python supplies exactly those three missing pieces: it is the long-running process that holds the HTTP socket, it keeps the world state on disk between invocations, and it decodes the XDR envelope (and parses uploaded wasm). Everything else — RPC method dispatch, the transaction store, ledger-sequence accounting, status determination, and JSON-RPC response formatting — runs inside the K semantics (`node.md`).
88

9-
```
10-
Stellar client
11-
│ JSON-RPC request (base64 XDR transaction)
12-
13-
StellarRpcServer ← server.py (long-running http.server; holds the socket + state files)
14-
15-
├─ TransactionEncoder ← transaction.py
16-
│ XDR → request envelope (+ kasmer steps for wasm uploads)
17-
18-
└─ NodeInterpreter ← interpreter.py
19-
request.json + state.kore → llvm_interpret → response.json
20-
21-
K semantics (LLVM backend) ← kdist/node.md + soroban-semantics
22-
reads request.json, dispatches the RPC method, updates the
23-
world state + bookkeeping files, writes response.json
24-
25-
state.kore · metadata.json · transactions.json (persisted in the io dir)
9+
```mermaid
10+
flowchart TB
11+
client(["Stellar client"])
12+
13+
subgraph py["Python — StellarRpcServer process (long-running)"]
14+
direction TB
15+
server["server.py — StellarRpcServer<br/>HTTP/JSON-RPC, owns the socket"]
16+
encoder["transaction.py — TransactionEncoder<br/>XDR → request envelope<br/>(+ kasmer steps for wasm uploads)"]
17+
interp["interpreter.py — NodeInterpreter<br/>runs the LLVM interpreter"]
18+
server -->|"1 — build envelope"| encoder
19+
server -->|"2 — run(envelope)"| interp
20+
end
21+
22+
subgraph ksem["K semantics — LLVM backend (kdist/node.md + soroban-semantics)"]
23+
node["dispatch RPC method · run steps via KASMER<br/>update bookkeeping · format response"]
24+
end
25+
26+
subgraph iodir["io dir (on disk)"]
27+
direction LR
28+
state[("state.kore")]
29+
meta[("metadata.json")]
30+
txs[("transactions.json")]
31+
end
32+
33+
client -->|"JSON-RPC (base64 XDR)"| server
34+
interp -->|"request.json + state.kore"| node
35+
node -->|"response.json"| interp
36+
node <-->|"read / write"| meta
37+
node <-->|"read / write"| txs
38+
interp <-->|"round-trip"| state
39+
server -->|"JSON-RPC response"| client
2640
```
2741

2842
---
@@ -79,21 +93,21 @@ Server state is split across the *io dir* (the directory containing the state fi
7993

8094
The world state stays in KORE (rather than a JSON snapshot) because an uploaded wasm module is a `ModuleDecl` that the semantics cannot reconstruct from bytes — only `wasm2kast` (Python) can produce it. The RPC bookkeeping, by contrast, is plain data and lives in the two JSON sidecar files, which the semantics read and write directly via the file-system hooks.
8195

82-
```
83-
startup (state.kore absent):
84-
→ NodeInterpreter.empty_config() builds the idle K configuration in KORE
85-
and runs it through llvm_interpret (no krun, no kast conversion)
86-
→ server writes state.kore, and seeds metadata.json ({latest_ledger: 0})
87-
and transactions.json ({})
88-
89-
per successful transaction:
90-
→ the semantics execute the steps, append a SUCCESS receipt to
91-
transactions.json, bump latest_ledger in metadata.json, and write
92-
response.json; NodeInterpreter persists the new state.kore
93-
94-
per failed (stuck) transaction:
95-
→ no response.json is produced; state.kore is left unchanged and the
96-
ledger is not bumped. The server synthesises a FAILED receipt.
96+
```mermaid
97+
flowchart TB
98+
boot(["server start"]) --> exists{"state.kore exists?"}
99+
exists -->|"no"| init["empty_config() builds the idle K config in KORE<br/>write state.kore · seed metadata.json {latest_ledger: 0} · transactions.json {}"]
100+
exists -->|"yes"| reuse["use existing state.kore<br/>seed sidecar files only if missing"]
101+
init --> ready(["ready for requests"])
102+
reuse --> ready
103+
104+
ready --> tx(["transaction submitted"])
105+
tx --> run["semantics run the decoded steps"]
106+
run --> stuck{"steps completed<br/>without getting stuck?"}
107+
stuck -->|"yes — SUCCESS"| ok["append SUCCESS receipt → transactions.json<br/>bump latest_ledger → metadata.json<br/>write response.json · persist new state.kore"]
108+
stuck -->|"no — FAILED"| fail["no response.json<br/>state.kore and ledger left unchanged<br/>server synthesises a FAILED receipt"]
109+
ok --> ready
110+
fail --> ready
97111
```
98112

99113
Because all three files live on disk, the server can be stopped and restarted without losing the world state, the ledger counter, or the transaction store. To resume a session, point `--state-file` at a saved `state.kore` (its sidecar files are read if present). To start fresh, delete the files.
@@ -102,30 +116,41 @@ Because all three files live on disk, the server can be stopped and restarted wi
102116

103117
## Request flow (end to end)
104118

105-
```
106-
1. Client: POST {"method": "sendTransaction", "params": {"transaction": "<base64 XDR>"}}
107-
108-
2. StellarRpcServer.handle_rpc:
109-
- TransactionEncoder.build_tx_request("sendTransaction", id, xdr, now, force_trace=False)
110-
→ ( request envelope {method, id, now, txHash, envelopeXdr, trace, steps},
111-
program_steps ) # program_steps is None unless the tx uploads wasm
112-
113-
3. NodeInterpreter.run(state_file, io_dir, envelope, program_steps):
114-
- writes request.json
115-
- (wasm only) splices the upload steps into the <program> cell, in KORE
116-
- llvm_interpret on state.kore → the semantics handle the request
117-
118-
4. node.md:
119-
- insert-handleRequestFile → #dispatch → #dispatchMethod("sendTransaction")
120-
- run steps → record a SUCCESS receipt in transactions.json
121-
- bump latest_ledger in metadata.json
122-
- write response.json: {hash, status: "PENDING", latestLedger, latestLedgerCloseTime}
123-
124-
5. NodeInterpreter persists the new state.kore and returns response.json verbatim.
125-
126-
6. Client: POST {"method": "getTransaction", "params": {"hash": "<hash>"}}
127-
→ the semantics look up transactions.json and return
128-
{status: SUCCESS, ledger, createdAt, envelopeXdr, trace, ...}
119+
```mermaid
120+
sequenceDiagram
121+
autonumber
122+
actor Client
123+
participant Server as StellarRpcServer
124+
participant Enc as TransactionEncoder
125+
participant Interp as NodeInterpreter
126+
participant K as node.md (K semantics)
127+
participant FS as io dir files
128+
129+
Note over Client,FS: Submit
130+
Client->>Server: sendTransaction { transaction: base64 XDR }
131+
Server->>Enc: build_tx_request(...)
132+
Enc-->>Server: request envelope (+ program_steps if wasm upload)
133+
Server->>Interp: run(state_file, io_dir, envelope, program_steps)
134+
Interp->>FS: write request.json
135+
Note right of Interp: wasm only — splice upload steps into the program cell, in KORE
136+
Interp->>K: llvm_interpret on state.kore
137+
Note over K: insert-handleRequestFile → dispatch → dispatchMethod
138+
K->>FS: run steps, append SUCCESS receipt to transactions.json
139+
K->>FS: bump latest_ledger in metadata.json
140+
K->>FS: write response.json { status: PENDING, ... }
141+
K-->>Interp: updated configuration
142+
Interp->>FS: persist new state.kore
143+
Interp-->>Server: response.json (verbatim)
144+
Server-->>Client: { hash, status: PENDING, latestLedger, ... }
145+
146+
Note over Client,FS: Poll for the result
147+
Client->>Server: getTransaction { hash }
148+
Server->>Interp: run(read-only envelope)
149+
Interp->>K: llvm_interpret on state.kore
150+
K->>FS: look up hash in transactions.json
151+
K-->>Interp: response.json
152+
Interp-->>Server: response.json
153+
Server-->>Client: { status: SUCCESS, ledger, createdAt, envelopeXdr, trace, ... }
129154
```
130155

131156
---

0 commit comments

Comments
 (0)