Files
James Zaki 73a95bb4a6 Fix λ prize text (#72)
* Fix titles
* Fix text
2026-05-29 11:47:40 +01:00

7.4 KiB

dependencies
dependencies

LP-0015: General cross-program calls via tail calls: external vs internal entrypoints + tooling [CLOSED]

Status: Closed Logos Circle: N/A

This prize is closed without an external λ Prize submission. The work was delivered by the Logos Execution Zone (LEZ) team as part of the core runtime and tooling rather than awarded through this competition.

Overview

This prize is for designing and implementing general cross-program calls (call mid-execution, then continue) while keeping tail calls as the only execution primitive. The system should let a program tail-call another program, have control return later via another tail call, and then continue execution in an internal-only function that cannot be invoked directly by users.

Conceptually, this is about making chained execution feel like a normal “call/return” experience for developers, while preserving the simplicity of a tail-call-only model. This aligns with well-known compilation techniques like continuation-passing style (CPS), where control flow is made explicit and all calls are tail calls.

Motivation

Modelling general calls using tail calls requires awkward patterns because all functions are effectively externally callable. That prevents encapsulation, makes interfaces hard to reason about, and creates security footguns (users can jump into “continuation” handlers directly).

We want a principled mechanism to distinguish public entrypoints from internal continuation steps, ideally using an unforgeable authority mechanism (e.g., a call capability/ticket) so only legitimate chained execution can reach internal functions. Capability-based security literature motivates why unforgeable references/capabilities are useful for enforcing least privilege and interface boundaries.

Success Criteria

Functionality

  • External vs internal functions: Programs can explicitly declare:
    • public entrypoints callable by users, and
    • internal-only functions callable only during chained execution.
  • Non-forgeable internal access: Provide a mechanism (e.g., a runtime-issued call-capability / ticket / proof) such that:
    • internal functions require this capability,
    • users cannot fabricate it,
    • and direct user invocation of internal functions fails deterministically.
  • General calls compile down to tail calls: Demonstrate an execution model where “call B then return to A and continue” is expressed purely with tail calls, consistent with CPS-style compilation intuition.
  • Ergonomic developer tooling: Provide tooling (preferably Rust SDK support) so developers can write general calls naturally, e.g.:
    • call_program!(B::do_thing(args) => then A::continue_internal(ctx)),
    • or an equivalent explicit API that remains readable and auditable.
  • End-to-end demo: Provide a working example with two programs:
    1. User calls A::public_entry()
    2. A tail-calls B::public_entry() (or similar)
    3. B tail-calls back to A::internal_continue()
    4. A continues and finalises Plus a negative test: user tries to call A::internal_continue() directly and it is rejected.
  • Clear interface rules: A concise spec describing:
    • how entrypoints are enumerated/encoded,
    • how internal-only routing is enforced,
    • ordering and determinism guarantees,
    • error semantics.
  • Test coverage: Unit/integration tests for:
    • capability validity checks,
    • replay/duplication handling (if relevant),
    • direct-call prevention,
    • nested/multi-step chains (at least one multi-hop scenario).

Usability

  • Provide a module/SDK (Rust SDK support) that exposes the general-call API so developers can write cross-program call chains without interacting with low-level tail-call plumbing directly.

Reliability

  • An invalid or forged capability token is rejected deterministically — it does not cause undefined behaviour or a silent no-op.
  • A multi-step call chain that aborts mid-execution rolls back all state changes consistently.

Performance

  • Document the compute unit (CU) overhead of each cross-program call hop on LEZ devnet/testnet compared to a direct entrypoint call. Note: LEZ's per-transaction compute budget may change during testnet.

Supportability

  • The mechanism is deployed and tested on LEZ devnet/testnet with the example programs (A and B).
  • End-to-end integration tests run against a LEZ sequencer (standalone mode) and are included in CI.
  • CI must be green on the default branch.
  • A README documents end-to-end usage: how to declare external vs internal entrypoints, compose a cross-program call chain, and run the demo showing accepted and rejected calls.
  • A reproducible end-to-end demo script is provided and works against a real local sequencer with RISC0_DEV_MODE=0.
  • A recorded video demo of the end-to-end flow is included in the submission; the recording must show terminal output (including proof generation) to confirm RISC0_DEV_MODE=0 was active.

Scope

In Scope

  • Mechanism to mark function visibility (external vs internal-only).
  • Runtime/sequencer verification rules to enforce internal-only access.
  • Tooling / SDK support to author general-call patterns that compile to tail-call chains.
  • Example programs and tests demonstrating correctness and UX.

Out of Scope

  • Introducing mid-execution synchronous calls as a new runtime primitive (tail calls must remain the only primitive).
  • A full framework rewrite; this should be a focused extension to enable safe composition.
  • Solving every possible cross-program security policy (e.g., global allowlists). The goal is encapsulation + safe chaining.

Prize Structure

  • Total Prize: $1,200
  • Effort: Large

Eligibility

Open to any individual or team. Submissions must be original work. Teams must hold the rights to all submitted code and agree to license it under MIT or Apache-2.0.

Submission Requirements

  • Public repository (fork of LEZ) containing:
    • implementation (runtime/sequencer checks if required + SDK/tooling),
    • specification document (docs/general-calls-via-tail-c-calls.md),
    • example programs (A and B) + scripts to run the demo,
    • tests runnable in CI.
  • A narrated video walkthrough in which the builder explains what they built and why, walks through the architecture and key implementation decisions, and demonstrates (see demo requirements):
    • the developer-facing API for general calls,
    • the tail-call chain produced at runtime,
    • failure when a user attempts to invoke an internal function directly.

Evaluation Process

Closed. This prize is not accepting submissions. The capability was implemented by the LEZ team; there is no external λ Prize winner or solutions/LP-0015.md entry.

The success criteria and submission requirements above are retained as the original specification of the intended work for historical reference.

Resources

Potential for Subsequent λ Prizes

This prize targets the current LEZ testnet. Should a future testnet version introduce breaking changes, a subsequent λ Prize may be opened to cover the necessary adaptation and redeployment.