feat: real resultXdr/resultMetaXdr and FAILED transaction reporting#37
Open
RaoulSchaffranek wants to merge 5 commits into
Open
feat: real resultXdr/resultMetaXdr and FAILED transaction reporting#37RaoulSchaffranek wants to merge 5 commits into
RaoulSchaffranek wants to merge 5 commits into
Conversation
Per the official RPC spec, resultXdr/resultMetaXdr are base64-encoded TransactionResult/TransactionMeta XDR structs, present when the status is SUCCESS or FAILED; the current empty-string stubs are not valid XDR. The new tests decode the receipts with stellar_sdk and check the success result code, the invocation return value reported via sorobanMeta.returnValue (add(2, 3) -> U32(5)), the txFAILED error result for a transaction that invokes a missing contract (with ledger/createdAt shaped consistently with SUCCESS receipts), and that NOT_FOUND responses omit all transaction fields. The three XDR-content tests fail until the feature lands; the NOT_FOUND guard already passes.
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.
The receipt's internal returnValue field is a K-side implementation detail that the server rewrites into resultXdr/resultMetaXdr; assert it never appears in getTransaction responses on any status. The leak is reachable today: if _attach_result_xdr raises, the receipt keeps the raw field and getTransaction serves it as-is. Add a regression test for exactly that trigger: a contract returning empty Bytes. #bytesToHex renders zero-length bytes as "0", which scval_from_json rejects (odd-length hex), so sendTransaction currently returns Internal error and the receipt leaks. The test pins the correct behaviour (sorobanMeta.returnValue = SCV_BYTES of b"") and fails until the encoding is fixed.
Base2String yields "0" for the zero-length case, an odd-length non-hex value that broke the receipt's XDR rewrite for contracts returning empty Bytes. Add a dedicated K rule mapping empty Bytes to the empty string. Also harden _attach_result_xdr: persist the receipt without the internal returnValue field even when the rewrite fails, so a stored receipt never leaks K-internal fields to getTransaction.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
getTransaction previously served empty-string stubs for
resultXdr/resultMetaXdr, which violates the RPC spec (real base64 XDR or omitted) — on SUCCESS receipts written by the semantics and on the FAILED receipts the server records for stuck transactions alike.What changed:
returnValue), extracted from the host stack after the invocation instead of resetting the host first. New#scValToJSONcovers the SCVal surface (ints, bool, void, symbol, string, bytes, addresses, vec, map).resultXdr(base64TransactionResult,txSUCCESS/txFAILED) andresultMetaXdr(base64TransactionMetav3 withsorobanMeta.returnValue) before the receipt is served. XDR construction lives in Python (result_xdr.py,scval.pyadditions) because K cannot build XDR — per the architecture notes this is the sanctioned exception to "formatting belongs in K".resultXdr(txFAILEDwithINVOKE_HOST_FUNCTION_TRAPPED) instead of the stubs, pinningledgerto the latest ledger at failure time andcreatedAtto submission time;resultMetaXdris omitted since a rolled-back run produces no meta.#bytesToHexon empty Bytes returned "0" (odd-length, non-hex), which broke the XDR rewrite for contracts returning empty Bytes. Empty Bytes now encode as the empty string._attach_result_xdris also hardened to persist the receipt without the internalreturnValuefield even if the rewrite fails, so stored receipts never leak K-internal fields.Testing: new integration tests decode the receipts with stellar_sdk and cover the invocation return value via
sorobanMeta.returnValue(add(2, 3) -> U32(5)), the empty-Bytes regression (SCV_BYTES of b""), decodable txSUCCESS results across the whole lifecycle (create account, upload, deploy, invoke), FAILED receipts with a decodable txFAILED result, NOT_FOUND field omission, and thatreturnValuenever appears in responses. Fulltest_server.pysuite passes (31 tests); flake8/isort/black clean, no new mypy errors.