You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Receipts now carry a real base64 TransactionResult in resultXdr and
TransactionMeta v3 in resultMetaXdr instead of empty-string stubs.
The semantics record the contract call's return value: uncheckedCallTx
no longer resets the host after the call, so #recordAndRespond can read
the returned ScVal off the hostStack, serialise it into the receipt's
internal returnValue field (JSON-encoded via the new #scValToJSON), and
reset the host afterwards. The server rewrites that field into the
spec-mandated XDR structs (new result_xdr.py builders, scval_from_json
decoder), since K cannot construct XDR. An invocation's return value is
reported as sorobanMeta.returnValue in the meta, matching stellar-rpc.
Failed transactions now store a txFAILED TransactionResult in the
FAILED receipt (resultMetaXdr is omitted: a rolled-back run produces no
meta), keeping ledger/createdAt encoded as on SUCCESS receipts.
Fees and ledger-entry change sets in the synthesised structs are
zero/empty because komet-node does not track them; documented in
docs/notes.md.
Copy file name to clipboardExpand all lines: docs/architecture.md
+1-2Lines changed: 1 addition & 2 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -89,7 +89,7 @@ All of the server's input and output artifacts live in one directory, the *io di
89
89
|---|---|---|---|
90
90
|`state.kore`| persistent |`NodeInterpreter`| the full K world-state configuration — accounts, contract code (including uploaded wasm `ModuleDecl`s), contract storage, ledger metadata — serialized in KORE. Read before each run and rewritten after a successful one. |
91
91
|`metadata.json`| persistent | the K semantics |`{"latest_ledger": N}` — the server ledger counter, bumped by 1 per committed transaction. |
92
-
|`receipts/receipt_<hash>.json`| persistent | the semantics (on success) or the server (on failure) | one stored receipt per transaction, keyed by tx hash, answering `getTransaction`. Each is `{status, ledger, createdAt, envelopeXdr, resultXdr, resultMetaXdr}`. |
92
+
|`receipts/receipt_<hash>.json`| persistent | the semantics and the server (on success — the server rewrites the semantics' internal `returnValue` field into `resultXdr`/`resultMetaXdr`), or the server alone (on failure) | one stored receipt per transaction, keyed by tx hash, answering `getTransaction`. Each is `{status, ledger, createdAt, envelopeXdr, resultXdr, resultMetaXdr?}`. |
93
93
|`traces/trace_<hash>.jsonl`| persistent | the semantics | one execution trace per transaction, keyed by tx hash — the instruction-level records, one JSON object per line. `traceTransaction` returns this file's contents. |
94
94
|`requests/request_<n>.json`| persistent | the server | an archive of each incoming JSON-RPC request, numbered by a monotonic counter, kept for debugging. |
95
95
|`request.json`| transient | the server | the request envelope for the call in flight (`method`, `id`, `now`, and method-specific fields). The semantics remove it once they respond. |
@@ -175,7 +175,6 @@ sequenceDiagram
175
175
176
176
## What's not yet implemented
177
177
178
-
-`resultXdr` / `resultMetaXdr` in `getTransaction` responses (contract return values)
179
178
-`simulateTransaction` (dry-run without state mutation)
180
179
-`getEvents`, `getLedgerEntries`, `getFeeStats` and other read-only RPC methods
181
180
-`ExtendFootprintTTL` and `RestoreFootprint` operations
the contract call's return `ScVal`, JSON-encoded by `#scValToJSON` (or `null` when the
88
+
transaction made no contract call), read off the `<hostStack>` before the host is reset,
87
89
3. responds with `{hash, status: "PENDING", latestLedger, latestLedgerCloseTime}`.
88
90
91
+
The internal `returnValue` field never reaches an RPC client: the Python server immediately rewrites it into the spec-mandated `resultXdr`/`resultMetaXdr` base64 XDR fields (`_attach_result_xdr` in `server.py`), because K cannot construct XDR. To keep the return value observable here, `uncheckedCallTx` (unlike komet's `callTx`) does not `#resetHost` after the call; `#recordAndRespond` serialises the stack top and resets the host instead.
92
+
89
93
The trace is not part of the receipt — the executing steps already appended it to `traces/trace_<hash>.jsonl`. Reaching `#finalizeTx` means the steps completed without getting stuck, so the status is `SUCCESS`. A failed transaction gets stuck before this point, `response.json` is never written, and the Python server records the `FAILED` receipt instead.
`resultXdr` and `resultMetaXdr` are currently empty stubs. The receipt carries no trace — use `traceTransaction` with the same hash to fetch it.
144
+
`resultXdr`is a base64 `TransactionResult` (code `txSUCCESS` or `txFAILED`) and `resultMetaXdr`a base64 `TransactionMeta` v3; when the transaction invoked a contract, its return value is reported as `sorobanMeta.returnValue` inside the meta. Both are synthesised by the server (`result_xdr.py`) from the envelope and the return value the semantics recorded in the receipt — see [node-semantics.md](node-semantics.md). Fees and ledger-entry change sets in these structs are zero/empty (komet-node does not track them). `resultMetaXdr` is omitted on `FAILED` receipts — a failed run rolls back and produces no meta. The receipt carries no trace — use `traceTransaction` with the same hash to fetch it.
145
145
146
146
---
147
147
148
148
## Failure fallback
149
149
150
-
A failed transaction leaves the semantics stuck without writing `response.json`, so `interpreter.run` returns `None`. Only `sendTransaction` executes a transaction, so it is the only method that reaches this path. The server then synthesises the response in Python: it writes a `FAILED``receipts/receipt_<hash>.json` (so a later `getTransaction` finds it), without bumping the ledger, and returns `PENDING`. This is the only response content the server builds itself.
150
+
A failed transaction leaves the semantics stuck without writing `response.json`, so `interpreter.run` returns `None`. Only `sendTransaction` executes a transaction, so it is the only method that reaches this path. The server then synthesises the response in Python: it writes a `FAILED``receipts/receipt_<hash>.json` (so a later `getTransaction` finds it) with a `txFAILED``resultXdr` and no `resultMetaXdr`, without bumping the ledger, and returns `PENDING`. `ledger` on a `FAILED` receipt pins the latest ledger at failure time (the chain does not advance) and `createdAt` the submission time, with the same encoding as on `SUCCESS` receipts.
151
+
152
+
On the success path the server also post-processes the receipt the semantics wrote: `_attach_result_xdr` replaces the receipt's internal `returnValue` field (a JSON-encoded SCVal, or `null`) with the spec-mandated `resultXdr`/`resultMetaXdr` base64 XDR, which K cannot construct. These are the only response contents the server builds itself.
0 commit comments