Skip to main content

Security-focused DeFi payload validation SDK (zero private keys in-library; explicit dependencies).

Project description

PyPI Python Version Coverage 100% License

English | 🇨🇳 简体中文 | Migration | 📦 Installation | ⚡ Quickstart | 🌐 Integrations | 🏗️ Architecture | 💬 Support

Lirix 2.0 · The EVM-grade execution airlock for AI agents

PyPI version Build Status

Lirix is a fail-closed validation and simulation control plane that stands between untrusted agent payloads and anything that can move value. It is not a signer; it is the execution airlock that forces intent, schema, ABI, RPC evidence, and local EVM simulation through L1–L5 before any broadcast handoff is emitted.

🎯 Why Lirix?

The Web3 agent stack fails in predictable ways: prompt injection becomes malicious calldata, toxic DeFi shapes pass review but fail on-chain, proxies hide real code paths, and RPC views diverge under load. Lirix collapses that attack surface into a single deterministic DAG: validate intent, decode and pierce contracts, reconcile RPC evidence, simulate with state overrides, and only then return an evidence-rich envelope that your orchestrator can retry, rewrite, or reject without guessing.

📦 Installation & Setup

python3 -m venv .venv
source .venv/bin/activate  # Windows: `.venv\\Scripts\\activate`
pip install lirix
lirix init

⚡ Quickstart: Five-Minute Blitz

1) Fail-closed validation and simulation

from typing import Any, Mapping

from lirix import Lirix

guardian = Lirix(rpc_urls=["https://eth-mainnet.g.alchemy.com/v2/…"])
draft: Mapping[str, Any] = {
    "to": "0x0000000000000000000000000000000000000001",
    "data": "0x",
    "value": 0,
}
result = guardian.validate_and_simulate("swap", draft)
print(result["decision"], result["status"], result["agent_feedback"]["reason_code"])
print(result["payload"].get("simulation_ok"))

2) Extract the broadcast handoff

Use Lirix.extract_broadcast_fields(result) only after both decision and status are "approved". The signer should receive the extracted broadcast fields, not the full result envelope.

from lirix import Lirix

broadcast_fields = Lirix.extract_broadcast_fields(result)
# 签名并广播(broadcast_fields)

3) Failure triage

When a request is blocked, inspect agent_feedback.remediation, then agent_feedback.reason_code, then resolve the protocol with resolve_failure_protocol(...) or Lirix.resolve_failure_protocol(...). Stable audit fields include canonical_error_code, failure_type_canonical, canonical_reason_codes, and the replay-facing aliases inside forensic_bundle.

4) E2E regression mirror

pytest -q tests/test_integration/test_real_e2e_paths.py

🌐 Ecosystem Integrations (LangChain & AutoGen)

Rule: validate_and_simulate takes intent: str and payload: Mapping[str, Any]. Always schema-lock model output before it crosses the Lirix boundary.

LangChain

from __future__ import annotations

import json
from typing import Any, Mapping, cast

from langchain_core.tools import tool
from pydantic import BaseModel, ConfigDict, Field

from lirix import Lirix, LirixSecurityException


class LirixValidationRequest(BaseModel):
    model_config = ConfigDict(extra="forbid", str_strip_whitespace=True)

    raw_llm_output: str = Field(..., min_length=1)
    intent: str = Field(..., min_length=1)


class LirixSecurityValidator:
    def __init__(self, guardian: Lirix) -> None:
        self._guardian = guardian

    def validate(self, raw_llm_output: str, intent: str) -> str:
        draft = cast(Mapping[str, Any], json.loads(raw_llm_output))
        # 先做结构化反序列化,再交给 Lirix 执行 fail-closed 校验与模拟
        result = self._guardian.validate_and_simulate(intent, draft)
        # 绝对安全:只提取经过 Lirix 校验并导出的广播字段
        tx_payload = Lirix.extract_broadcast_fields(result)
        return json.dumps({"result": result, "tx_payload": tx_payload}, sort_keys=True, default=str)


guardian = Lirix(rpc_urls=["https://eth-mainnet.g.alchemy.com/v2/…"])
validator = LirixSecurityValidator(guardian=guardian)


@tool("lirix_validate_and_simulate")
def lirix_validate_and_simulate(raw_llm_output: str, intent: str) -> str:
    """在任何广播路径前进行 fail-closed 校验。"""
    return validator.validate(raw_llm_output=raw_llm_output, intent=intent)

AutoGen

from __future__ import annotations

import json
from dataclasses import dataclass
from typing import Any, Mapping, cast

from lirix import Lirix, LirixSecurityException


@dataclass(frozen=True)
class AutoGenLirixBridge:
    guardian: Lirix

    def __call__(self, raw_llm_output: str, intent: str) -> Mapping[str, Any]:
        draft = cast(Mapping[str, Any], json.loads(raw_llm_output))
        try:
            # 先执行意图校验、ABI 解码与沙盒模拟,确认是否满足 fail-closed 门槛
            result = self.guardian.validate_and_simulate(intent, draft)
            return {
                "status": "approved",
                "result": result,
                # 绝对安全:只提取经过 Lirix 校验并导出的广播字段
                "tx_payload": Lirix.extract_broadcast_fields(result),
            }
        except LirixSecurityException as exc:
            # 回退机制:当 Lirix 拦截到攻击时,将重写指令回传给 Agent
            return {"status": "blocked", "resolution_for_agent": exc.resolution_for_agent}


autogen_lirix = AutoGenLirixBridge(guardian=Lirix(rpc_urls=["https://eth-mainnet.g.alchemy.com/v2/…"]))

🏗️ Architecture & Security Trace

Public Lirix (lirix/_facade.py) composes HookManager, ClientPipelineProtocol, and LirixPipelineOrchestrator into a one-way pipeline with session and trace FSM semantics. Hooks extend policy at the perimeter; they do not bypass the core.

flowchart LR
  A[LLM / Tool output] --> B[Payload Mapping]
  B --> C{L1 Intent}
  C -- pass --> D{L2 Schema}
  D -- pass --> E{L3 DeFi / ABI}
  E -- pass --> F{L4 RPC Quorum}
  F -- pass --> G{L5 Sandbox + Policy}
  G -- pass --> H[Approved envelope]
  H --> I[Your signer + broadcast]

  C -- fail-closed --> X[Block + structured agent_feedback]
  D -- fail-closed --> X
  E -- fail-closed --> X
  F -- fail-closed --> X
  G -- fail-closed --> X
  1. L1 — Intent firewall with injection-resistant allowlists.
  2. L2 — Schema boundary with strict payload typing.
  3. L3 — DeFi / ABI decoding plus proxy piercing.
  4. L4 — Multi-node RPC reconciliation with evidence.
  5. L5 — Local EVM simulation plus shadow policy audit.

HookManager gives you RBAC, sandbox routing, OTel export, and pre/post-flight policy hooks without forking the kernel. The rule is simple: the kernel stays deterministic; the perimeter stays customizable.

Developer paths

  • validate_only / async_validate_only — L1–L3 + evidence.
  • simulate_only / async_simulate_only — L4–L5, with optional prior validation gate.
  • validate_and_simulate / async_validate_and_simulate — full DAG.
  • atomic_multicall — multicall packing with L1–L3 alignment.
  • Layer types — import from lirix.layers; hooks and exceptions from lirix.core.

Progressive migration flags

LirixConfig exposes hook_contract_mode, policy_lifecycle_mode, and rpc_evidence_mode. Move hook_contract_mode from shadow to enforce only after the hook evidence is clean and the v2 rails are verified.

Project layout

lirix/
├── lirix/        # core defense layers + facade
├── tests/        # verification + adversarial coverage
├── docs/         # audit + architecture SSOT
└── SECURITY.md   # disclosure policy

Full tree: docs/STRUCTURE.md. Control plane table: docs/architecture_control_plane.md.

🛡️ Security Model

Triple-Zero: Zero-Key · Zero-Telemetry · Zero-Trust — see SECURITY.md.

💬 Support & FAQ

  • General: Discussions / Issues
  • Security: do not open public issues; follow SECURITY.md.

Q: Why no private key?
A: Lirix validates and simulates; you sign. Separation of duties is the model.

Q: externally-managed-environment?
A: Use a venv; never pip install --break-system-packages.


🇨🇳 Lirix 2.0 · 面向 AI Agent 的 EVM 级执行气闸

一句话定义: Lirix 是夹在「不可信模型输出」与「私钥 / 广播」之间的 fail-closed 校验 + 模拟控制平面。它不是钱包,也不是 Signer;它是 EVM-grade execution airlock,要求意图、Payload、RPC 证据与本地 EVM 模拟逐层通过 L1–L5 单向 DAG,然后才吐出可交接的广播字段。

🎯 为什么需要 Lirix?

Web3 Agent 的常见死法非常一致:Prompt 注入 变成恶意 calldata,有毒 DeFi 形状 在审查时看似合理、上线后却 Revert 或失血,Proxy / Router 把真实执行路径藏起来,RPC 视图还会在高压下分叉。Lirix 把这些风险压成一条确定性 DAG:先校验意图与结构,再做 ABI 解码与 Proxy 穿透,必要时进行多节点 RPC 对账,并配合 State Overrides 做沙盒模拟,最后输出带 security_tracereplay_bundle 的证据信封——由你的编排器决定重试、改写,还是直接硬拒绝。

📦 安装与初始化

python3 -m venv .venv
source .venv/bin/activate  # Windows:`.venv\\Scripts\\activate`
pip install lirix
lirix init

⚡ 快速上手:五分钟闪电战

1) fail-closed 校验与模拟

from typing import Any, Mapping

from lirix import Lirix

guardian = Lirix(rpc_urls=["https://eth-mainnet.g.alchemy.com/v2/…"])
draft: Mapping[str, Any] = {
    "to": "0x0000000000000000000000000000000000000001",
    "data": "0x",
    "value": 0,
}
result = guardian.validate_and_simulate("swap", draft)
print(result["decision"], result["status"], result["agent_feedback"]["reason_code"])
print(result["payload"].get("simulation_ok"))

2) 提取广播交接字段

只有当 decisionstatus 都是 "approved" 时,才允许调用 Lirix.extract_broadcast_fields(result)。签名器只接收提取后的广播字段,绝不接收完整 result envelope。

from lirix import Lirix

broadcast_fields = Lirix.extract_broadcast_fields(result)
# 签名并广播(broadcast_fields)

3) 失败排查

被阻断时,按顺序查看 agent_feedback.remediationagent_feedback.reason_code,再用 resolve_failure_protocol(...)Lirix.resolve_failure_protocol(...) 定位。稳定审计字段包括 canonical_error_codefailure_type_canonicalcanonical_reason_codes,以及 forensic_bundle 中面向回放的别名字段。

4) E2E 回归镜像

pytest -q tests/test_integration/test_real_e2e_paths.py

🌐 生态集成(LangChain 与 AutoGen)

规则: validate_and_simulate 只接受 intent: strpayload: Mapping[str, Any]。模型输出必须先做 JSON / schema-lock,再跨过 Lirix 边界。

LangChain

from __future__ import annotations

import json
from typing import Any, Mapping, cast

from langchain_core.tools import tool
from pydantic import BaseModel, ConfigDict, Field

from lirix import Lirix, LirixSecurityException


class LirixValidationRequest(BaseModel):
    model_config = ConfigDict(extra="forbid", str_strip_whitespace=True)

    raw_llm_output: str = Field(..., min_length=1)
    intent: str = Field(..., min_length=1)


class LirixSecurityValidator:
    def __init__(self, guardian: Lirix) -> None:
        self._guardian = guardian

    def validate(self, raw_llm_output: str, intent: str) -> str:
        draft = cast(Mapping[str, Any], json.loads(raw_llm_output))
        # 先做结构化反序列化,再交给 Lirix 执行 fail-closed 校验与模拟
        result = self._guardian.validate_and_simulate(intent, draft)
        # 绝对安全:只提取经过 Lirix 校验并导出的广播字段
        tx_payload = Lirix.extract_broadcast_fields(result)
        return json.dumps({"result": result, "tx_payload": tx_payload}, sort_keys=True, default=str)


guardian = Lirix(rpc_urls=["https://eth-mainnet.g.alchemy.com/v2/…"])
validator = LirixSecurityValidator(guardian=guardian)


@tool("lirix_validate_and_simulate")
def lirix_validate_and_simulate(raw_llm_output: str, intent: str) -> str:
    """在任何广播路径前进行 fail-closed 校验。"""
    return validator.validate(raw_llm_output=raw_llm_output, intent=intent)

AutoGen

from __future__ import annotations

import json
from dataclasses import dataclass
from typing import Any, Mapping, cast

from lirix import Lirix, LirixSecurityException


@dataclass(frozen=True)
class AutoGenLirixBridge:
    guardian: Lirix

    def __call__(self, raw_llm_output: str, intent: str) -> Mapping[str, Any]:
        draft = cast(Mapping[str, Any], json.loads(raw_llm_output))
        try:
            # 先执行意图校验、ABI 解码与沙盒模拟,确认是否满足 fail-closed 门槛
            result = self.guardian.validate_and_simulate(intent, draft)
            return {
                "status": "approved",
                "result": result,
                # 绝对安全:只提取经过 Lirix 校验并导出的广播字段
                "tx_payload": Lirix.extract_broadcast_fields(result),
            }
        except LirixSecurityException as exc:
            # 回退机制:当 Lirix 拦截到攻击时,将重写指令回传给 Agent
            return {"status": "blocked", "resolution_for_agent": exc.resolution_for_agent}


autogen_lirix = AutoGenLirixBridge(guardian=Lirix(rpc_urls=["https://eth-mainnet.g.alchemy.com/v2/…"]))

🏗️ 架构与安全追踪

对外 Lirixlirix/_facade.py)把 HookManagerClientPipelineProtocolLirixPipelineOrchestrator 组合成一条单向流水线;会话与追踪由 FSM 约束。Hook 是隔离契约面,只能扩展策略,不能绕过核心层

flowchart LR
  A[LLM / 工具输出] --> B[Payload 映射]
  B --> C{L1 意图}
  C -- pass --> D{L2 Schema}
  D -- pass --> E{L3 DeFi / ABI}
  E -- pass --> F{L4 RPC Quorum}
  F -- pass --> G{L5 沙盒 + Policy}
  G -- pass --> H[Approved 信封]
  H --> I[你的签名与广播]

  C -- fail-closed --> X[阻断 + 结构化 agent_feedback]
  D -- fail-closed --> X
  E -- fail-closed --> X
  F -- fail-closed --> X
  G -- fail-closed --> X
  1. L1 — 意图防火墙,拦截注入型 Payload。
  2. L2 — Schema 边界,严格类型化 Payload。
  3. L3 — DeFi / ABI 解码与 Proxy 穿透。
  4. L4 — 多节点 RPC 对账与证据收集。
  5. L5 — 本地 EVM 模拟与影子策略审计。

HookManager 提供 RBAC、沙盒路由、OTel 导出与前后置策略钩子,而不会把核心内核拆散。原则很简单:内核保持确定性,外围保持可定制。

开发路径

  • validate_only / async_validate_only — L1–L3 + evidence。
  • simulate_only / async_simulate_only — L4–L5,可按配置在前面挂验证门。
  • validate_and_simulate / async_validate_and_simulate — 全 DAG 路径。
  • atomic_multicall — 与 L1–L3 对齐的 multicall 打包。
  • Layer 类型 — 从 lirix.layers 导入;Hook 与异常从 lirix.core 导入。

渐进式迁移开关

LirixConfig 暴露 hook_contract_modepolicy_lifecycle_moderpc_evidence_mode。只有当 hook 证据干净、v2 轨道验证通过后,才把 hook_contract_modeshadow 切到 enforce

项目结构

lirix/
├── lirix/        # 核心防线层 + 门面
├── tests/        # 验证与对抗覆盖
├── docs/         # 审计与架构单一真相源
└── SECURITY.md   # 披露政策

完整目录见 docs/STRUCTURE.md。控制面表见 docs/architecture_control_plane.md

🛡️ 安全模型

Triple-Zero:零密钥 · 零遥测 · 零信任 — 详见 SECURITY.md

💬 支持与 FAQ

  • 普通讨论: Discussions / Issues
  • 安全问题: 不要开公开 Issue;请遵循 SECURITY.md

Q:为什么没有私钥?
A:Lirix 负责校验与模拟, 负责签名。职责分离是设计本身。

Q:遇到 externally-managed-environment 怎么办?
A:先建 venv,永远不要直接 pip install --break-system-packages


PyPI Python Version Coverage 100% License

© 2026 lokii-D — see LICENSE.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

lirix-2.0.0.tar.gz (118.7 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

lirix-2.0.0-py3-none-any.whl (125.1 kB view details)

Uploaded Python 3

File details

Details for the file lirix-2.0.0.tar.gz.

File metadata

  • Download URL: lirix-2.0.0.tar.gz
  • Upload date:
  • Size: 118.7 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.12.13

File hashes

Hashes for lirix-2.0.0.tar.gz
Algorithm Hash digest
SHA256 3b3022275fcb88fcd920f1082825da7278ec83d503842e51575d508c9db6d0fd
MD5 616e14c7067732b00887c644a871d724
BLAKE2b-256 58ade8b58cc038cc13f2fda7ecc6f840ee38022993eba4b7339f276813f6bbce

See more details on using hashes here.

File details

Details for the file lirix-2.0.0-py3-none-any.whl.

File metadata

  • Download URL: lirix-2.0.0-py3-none-any.whl
  • Upload date:
  • Size: 125.1 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.12.13

File hashes

Hashes for lirix-2.0.0-py3-none-any.whl
Algorithm Hash digest
SHA256 765c81a8b023c42c68bb52fa9782fc7979c74803024806750de34e33a718ebbf
MD5 bda879d3706037f0c587f4de5104b63d
BLAKE2b-256 c7399137dab4a15072935c7bb89ad9256195fbbeaf66f4d3ecc3398835664c30

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page