# What Is the Equivalence Principle in GenLayer?

> Discover the equivalence principle in GenLayer a consensus mechanism allowing validators to agree on nondeterministic operations. Learn how it separates execution for verification.

- Repository: [GenLayer Labs/genlayer-project-boilerplate](https://github.com/genlayerlabs/genlayer-project-boilerplate)
- Tags: deep-dive
- Published: 2026-08-20

---

**The equivalence principle in GenLayer is a consensus mechanism that enables validators to agree on nondeterministic operations—such as web requests and LLM calls—by separating execution into a leader function that performs the operation and a validator function that verifies the result meets predefined acceptance criteria.**

GenLayer is a blockchain platform that allows smart contracts to execute nondeterministic operations, creating unique consensus challenges. The `genlayerlabs/genlayer-project-boilerplate` repository demonstrates how the equivalence principle solves this by establishing a validation framework for variable outputs. This architectural pattern ensures that despite running operations with potentially different results across nodes, the network can reach deterministic consensus.

## How the Equivalence Principle Works

The core mechanism, documented in [`CLAUDE.md`](https://github.com/genlayerlabs/genlayer-project-boilerplate/blob/main/CLAUDE.md), divides nondeterministic execution into two distinct phases. When a contract calls an operation like `gl.nondet.web.render` or `gl.nondet.exec_prompt`, the system cannot guarantee identical results across all validator nodes. The equivalence principle resolves this by requiring explicit validation logic.

### The Leader Function

The **leader function** executes the actual nondeterministic operation. This function runs once to produce a result that will be proposed to the network. For example, it might fetch web data or query an LLM, returning output that could vary slightly between executions due to network latency, API changes, or model variations.

### The Validator Function

The **validator function** receives the leader's output and applies acceptance rules to determine if the result is valid. If the validator returns `True`, the network accepts the result and stores it on-chain. If it returns `False`, the transaction reverts. This separation ensures that while execution may vary, consensus depends on whether the output satisfies objective criteria.

## Implementation Methods

GenLayer provides two primary approaches for applying the equivalence principle, depending on the complexity of your validation requirements.

### Convenience Helpers

For common validation patterns, GenLayer offers built-in helpers through the `gl.eq_principle` module:

- **`gl.eq_principle.strict_eq()`** – Requires exact equality between the leader's result and what validators reproduce, suitable for deterministic JSON outputs or structured data.
- **`gl.eq_principle.prompt_comparative()`** – Accepts answers that are "similar enough" for comparative queries.
- **`gl.eq_principle.prompt_non_comparative()`** – Designed for subjective assessments where exact matching isn't required.

These helpers abstract the leader/validator pattern into single function calls.

### Custom Leader and Validator Functions

For complex validation logic, developers define separate leader and validator functions and invoke them via `gl.vm.run_nondet()`. This approach offers full control over what constitutes an acceptable result.

```python
def leader() -> str:
    # Perform a nondeterministic web fetch

    return gl.nondet.web.get("https://example.com/api").body

def validator(leader_output: str) -> bool:
    # Simple rule: output must be valid JSON and contain a "status" field

    try:
        data = json.loads(leader_output)
        return "status" in data
    except Exception:
        return False

# Run the nondeterministic operation with explicit validation

result = gl.vm.run_nondet(leader, validator)

```

## Real-World Example from football_bets.py

The [`contracts/football_bets.py`](https://github.com/genlayerlabs/genlayer-project-boilerplate/blob/main/contracts/football_bets.py) file demonstrates the equivalence principle using the `strict_eq` helper. In the `_check_match` method at line 54, the contract fetches match results and uses an LLM to extract scores:

```python
def _check_match(self, resolution_url: str, team1: str, team2: str) -> dict:
    def get_match_result() -> str:
        web_data = gl.nondet.web.render(resolution_url, mode="text")
        task = f"""
        Extract the match result for:
        Team 1: {team1}
        Team 2: {team2}

        Web content:
        {web_data}

        Respond in JSON:
        {{
            "score": str,
            "winner": int
        }}
        """
        result = gl.nondet.exec_prompt(task, response_format="json")
        return json.dumps(result, sort_keys=True)

    # The strict_eq helper ensures every validator receives the exact same JSON string.

    result_json = json.loads(gl.eq_principle.strict_eq(get_match_result))
    return result_json

```

Here, `get_match_result` serves as the leader function, while `gl.eq_principle.strict_eq` handles the validator logic internally, ensuring consensus by requiring identical JSON strings across all nodes.

## Summary

- The equivalence principle separates nondeterministic execution into leader and validator functions to achieve blockchain consensus.
- **Leader functions** execute variable operations like web requests or LLM calls.
- **Validator functions** verify that outputs meet predefined acceptance criteria before on-chain storage.
- Use **`gl.eq_principle`** helpers for standard validation patterns like strict equality or semantic similarity.
- Use **`gl.vm.run_nondet()`** for custom validation logic requiring explicit leader and validator definitions.
- The pattern is documented in [`CLAUDE.md`](https://github.com/genlayerlabs/genlayer-project-boilerplate/blob/main/CLAUDE.md) and implemented in production contracts like [`contracts/football_bets.py`](https://github.com/genlayerlabs/genlayer-project-boilerplate/blob/main/contracts/football_bets.py).

## Frequently Asked Questions

### What happens if the validator rejects the leader's output?

If the validator function returns `False` or fails to validate the leader's result, the transaction reverts and the result is not stored on-chain. This prevents nondeterministic or invalid data from being committed to the blockchain state, maintaining network integrity.

### Can I use the equivalence principle with any type of nondeterministic operation?

Yes, the equivalence principle applies to any operation that may produce different results across validators, including `gl.nondet.web.render` for web scraping, `gl.nondet.exec_prompt` for LLM interactions, or other external API calls. Both convenience helpers and custom validation support these varied use cases.

### What is the difference between strict_eq and prompt_comparative validation?

`gl.eq_principle.strict_eq()` requires byte-for-byte identical output from all validators, making it suitable for structured data like JSON. `gl.eq_principle.prompt_comparative()` uses semantic comparison to determine if answers are equivalent in meaning rather than identical in text, which is necessary for LLM-generated content that may vary in phrasing while conveying the same information.

### When should I use custom leader/validator functions instead of helpers?

Use custom leader and validator functions via `gl.vm.run_nondet()` when your validation logic requires domain-specific rules, partial data extraction, or complex conditional checks that go beyond equality or semantic comparison. The convenience helpers are optimized for common patterns, while custom functions provide full programmatic control over acceptance criteria.