Skip to content
/ tlos Public

TLOS: Topology-Lattice Obfuscation for Smart Contracts

Notifications You must be signed in to change notification settings

igor53627/tlos

Repository files navigation

TLOS: Topology-Lattice Obfuscation for Smart Contracts

Ask DeepWiki

Five-layer obfuscation with a planted LWE puzzle (one-time floor) and a configurable hash-PoW layer.

TLOS is a practical circuit obfuscation framework for EVM. It uses standard LWE with Gaussian noise (σ=25, n=384) for control function hiding, full-rank linear hashing for wire binding, and a planted LWE puzzle that adds a one-time q^128 brute-force floor for recovering the planted solution (lattice estimator ~2^58 for current params). Security is based on standard LWE hardness (~2^112 PQ).

Status (Active Research)

TLOS is an active research prototype exploring layered obfuscation for smart contracts. It is not a production security system and should not be used to protect real value without independent review. The repo remains open to issues and discussion, and we intend to publish iterative updates as we refine the threat model, benchmarks, and parameter choices.

Security note: Low-entropy secrets are dictionary-bound even with the planted puzzle and PoW. The puzzle's "q^128 floor" applies only to recovering the planted solution from (A, b) without guessing; it does not raise offline enumeration cost for weak inputs. PoW is an online throttle unless the success predicate is fully masked with no public side channel.

What is TLOS?

TLOS provides five-layer security for on-chain circuit obfuscation, with configurable PoW throttling:

  1. Topology layer: Structural mixing defeats structural/statistical attacks (heuristic)
  2. LWE layer: Standard LWE with Gaussian noise (σ=25, n=384) hides control functions (~2^112 PQ)
  3. Wire binding layer: Full-rank 64x64 public linear map binds wire values across gates (algebraic binding)
  4. Planted LWE puzzle: One-time q^128 brute-force floor for recovering the planted solution (8.62M gas, 14% of 60M block)
  5. Hash-PoW (Layer 5): Hashcash-style work bound to commit-time randomness; throttles on-chain guessing and binds each guess to its commit (set difficulty to 0 to disable)

PoW-masked accept/reject: Success signal keyed by a PoW-derived mask (e.g., M = H(randao || input || solutionHash || nonce)), so guesses cannot be tested without PoW. This only helps if success cannot be computed from public data without M; any unmasked accept/reject side-channel defeats it. Optional variant: mask the input with M, which makes the effective target per-commit (acceptable for recovery flows). Default keeps the LWE instance fixed.

Hash-PoW Benchmarks (H200, Keccak256)

Measured throughput and derived solve times:

  • Throughput: 1.768782e9 hashes/sec (~1.77 GH/s)
  • D=32: 2.428s per solve (1 GPU)
  • D=40: 621.6s per solve (1 GPU)
  • 1M dictionary @ D=32: ~28.1 days (1 GPU)

Delegated Solver Economics (D=40)

Cost per solve (D=40) ≈ $0.7839 at $0.001261/sec.

Dictionary size N eps = 1% eps = 5% eps = 10%
1M $7,839 $39,193 $78,386
10M $78,386 $391,932 $783,864
100M $783,864 $3,919,319 $7,838,639
1B $7,838,639 $39,193,194 $78,386,389

Expected cost for a uniform secret is ~N/2 solves (~50x the 1% line). Delegated solvers are optional for rare recovery flows; they add latency and a trust trade-off, so they are not a default for frequent authentication.

The wire binding construction is inspired by Ma-Dai-Shi 2025 but is not subspace-evasive in the formal sense - it is a public bijective linear map providing algebraic binding, not cryptographic hiding.

Documentation

  • docs/ARCHITECTURE.md
  • docs/DEPLOYMENT.md
  • docs/FEATURE_FLAGS.md
  • docs/API_ENDPOINTS.md
  • docs/IMPLEMENTATION.md
  • docs/SECURITY.md

Components

Layer Purpose Security
Topology Anti-attack wire patterns (non-pow2 distances, uniform usage) Heuristic (empirical)
Lattice (LWE) Control function hiding via LWE with Gaussian noise (σ=25) ~2^112 PQ (n=384)
Obfuscation Circuit representation hiding Heuristic
Wire Binding Inter-gate wire consistency via full-rank linear hash Algebraic binding
Puzzle One-time floor for planted-solution recovery (not per-guess) Computational (q^128 brute-force)
PoW (configurable) On-chain throttling bound to commit-time randomness (per-commit guesses) Protocol-level

Architecture

+--------------------------------------------------------------+
| Input x + puzzle solution s                                  |
+--------------------------------------------------------------+
                              |
                              v
+--------------------------------------------------------------+
| Layer 4: Verify puzzle ||A s - b||^2 < threshold             |
+--------------------------------------------------------------+
                              |
                              v
+--------------------------------------------------------------+
| Wire binding init: acc0 = H(seed || x || H(s))               |
+--------------------------------------------------------------+
                              |
                              v
+--------------------------------------------------------------+
| Gates 0..N: LWE C&C + binding update                         |
+--------------------------------------------------------------+
                              |
                              v
+--------------------------------------------------------------+
| Verify: accN == expected AND output == expectedOutput        |
+--------------------------------------------------------------+

Gas Costs (Measured on Tenderly)

Total gas below is checkWithPuzzle() (includes the puzzle verification).

Config (n=384) Gates Total Gas % of 60M Block
Conservative 64 4,734,943 7%
Balanced 128 5,917,147 9%
Standard 256 8,981,516 14%
Full 640 18,184,574 30%

Optimizations applied:

  • Seed-derived a vectors: 99.6% storage reduction (11 bytes/gate vs 3083 bytes)
  • Wire binding PRG: 16 coefficients per Keccak256 (320 calls vs 4096)
  • Single mod at end of inner product (vs per-term mod)
  • Batch size 128 (binding updates every 128 gates)
  • n=384 LWE dimension with Gaussian noise (σ=25) for ~2^112 PQ security
  • Layer 4 puzzle: n=128, m=192, q=2039 for a one-time q^128 brute-force floor

Storage

TLOS uses seed-derived a vectors - the public LWE vectors are regenerated on-chain from a circuit seed instead of being stored.

Config (n=384) Gates Storage Old Format Savings
Conservative 64 704 bytes 394 KB 99.6%
Balanced 128 1.4 KB 788 KB 99.6%
Full security 256 2.8 KB 1.58 MB 99.6%

Deployment scheme (Tenderly, receipts):

  1. Deploy circuit data via SSTORE2: 662,099 gas (256 gates) / 1,575,259 gas (640 gates)
  2. Deploy puzzle b via SSTORE2: fixed per-m (384 bytes for n=128, m=192)
  3. Deploy TLOS instance (no data duplication): 1,707,897 gas (256) / 1,707,885 gas (640)
  4. Total deploy: 2,454,436 gas (256) / 3,367,584 gas (640)

View vs Transaction costs:

  • check(input): Free (view function, local simulation)
  • reveal(input, puzzleSolution, nonce) / mint(): 4,734,943-18,184,574 gas (state-changing, executes _evaluate() + puzzle)
    • If PoW is disabled, nonce can be 0

Advantage Over Simple Hash Commitments

Why use TLOS instead of keccak256(secret)? For random 256-bit secrets, Keccak256 is simpler and sufficient. However, TLOS provides significant advantage for low-entropy secrets and multi-bit payloads.

Secret Type Keccak256 Attack (est.) TLOS Attack (GPU)
Random 256-bit ~2^256 hashes min(2^256, ~2^112)
Human password (10^6) Milliseconds ~181 ms
Range 0-100K ~0.1 seconds ~17 ms
4-word phrase Seconds Seconds

Critical limitation: Layer 4 provides only ~0.17 µs per-guess overhead on GPU (5.8M guesses/sec on A100). For low-entropy secrets, dictionary attacks complete in milliseconds to seconds. The "q^128 floor" only applies to recovering the planted solution from (A,b) without guessing the secret.

Attack cost formula:

AttackCost = |Dictionary| × 0.17µs (GPU)
AttackCost = |Dictionary| × 75µs (CPU)

PoW throttles on-chain attempts only; it does not affect offline enumeration. High-entropy secrets are required for security against offline adversaries.

Concrete Use Cases

  • Password-gated vaults: Human phrase unlocks funds
  • On-chain treasure hunts: Riddle answer reveals GPS coordinates or URL
  • Number guessing games: Hide value in 0-100K range without enumeration
  • Multi-code access: OR of N event codes (any code unlocks)
  • Hidden game parameters: Tournament seeds revealed at game start

When to Use Keccak256 Instead

For random 256-bit secrets with no payload beyond TRUE/FALSE, simple Keccak256 commitments are better (cheaper, simpler, no security loss).

Security Properties

Security is based on standard LWE hardness with Gaussian noise (σ=25). The lattice estimator confirms ~2^112 PQ security for n=384, q=65521, m=2560. See paper/tlos-paper.pdf for full analysis.

Layer 4 Puzzle Parameters

Parameter Value
Secret dimension n 128
Samples m 192
Modulus q 2039
Secret distribution Uniform mod q
Error distribution Uniform {-2,-1,0,1,2}
Threshold 800
Search space q^128 brute-force (lattice estimator ~2^58)
Verification gas 8.62M (Tenderly, 14% of 60M block)

Puzzle recovery cost (one-time): Brute-force search over q^128 is computationally infeasible. The lattice estimator suggests ~2^58 security for current parameters. This does not change low-entropy dictionary asymptotics.

What Wire Binding Provides

  • Mix-and-match prevention: Gates cannot be evaluated with inconsistent inputs
  • Execution trace binding: Full evaluation history is committed
  • Algebraic binding: Full-rank 64x64 matrix provides unique preimage (bijective map)

What Wire Binding Does NOT Provide

  • Cryptographic hiding: The linear map is public and invertible
  • Collision resistance: Trivial to find x given Ax = y
  • Key extraction resistance: Still relies on LWE layer for CF hiding

What TLOS Does NOT Provide

  • iO security: Obfuscations of equivalent circuits are not indistinguishable
  • VBB security: Virtual black-box is impossible in general
  • Long-term secret protection: Not recommended for secrets requiring decades of protection

Quick Start

# Clone
git clone https://github.com/igor53627/tlos.git
cd tlos

# Build contracts
forge build

# Generate circuit data
cargo run --bin generate_tlos -- --secret 0x... --seed 42

# Run benchmarks on Tenderly
source ~/.zsh_secrets
forge script scripts/BenchmarkTLOS.s.sol --rpc-url "$TENDERLY_RPC" --broadcast --unlocked -vvv

Repository Structure

tlos/
├── contracts/
│   ├── TLOSWithPuzzleV5.sol  # Production: 5-layer TLOS (PoW default; difficulty configurable)
│   ├── WeakLWEPuzzleV7.sol   # Production puzzle (n=128, m=192, q^128 brute-force floor)
│   └── interfaces/
│       └── IHoneypot.sol     # Commit-reveal interface
├── src/                       # Rust implementation
│   ├── circuit.rs            # Circuit/gate structures (Layer 1)
│   ├── lwe.rs                # LWE encoding (Layer 2, Gaussian noise, σ=25)
│   ├── wire_binding.rs       # Wire binding implementation (Layer 3)
│   ├── generator.rs          # Deployment generator
│   ├── security/             # Security estimation
│   │   └── lattice_estimator.rs  # lattice-estimator CLI wrapper
│   └── bin/
│       └── generate_tlos.rs  # CLI binary
├── test/                      # Foundry tests (168 tests)
│   ├── TLOSWithPuzzleV5.t.sol    # Production contract tests (61 tests)
│   ├── TLOSWithPuzzleV5Harness.sol  # Test harness for isolated testing
│   ├── PuzzleVariants.t.sol      # Puzzle V7 tests (7 tests)
│   └── *.t.sol               # Example contract tests
├── scripts/
│   ├── BenchmarkTLOS.s.sol   # Tenderly benchmark
│   └── attacks/              # Attack scripts organized by layer
│       ├── layer1-topology/  # SAT/oracle-guided attacks (Rust)
│       ├── layer2-lwe/       # Lattice attacks (Python)
│       ├── layer3-binding/   # Mix-and-match attacks (Python)
│       ├── layer4-puzzle/    # Brute-force attacks (Python/GPU)
│       └── estimators/       # Security estimation tools
├── docs/
│   ├── layers/               # Per-layer technical documentation
│   │   ├── layer1-topology/  # Circuit mixing (heuristic)
│   │   ├── layer2-lwe/       # LWE encryption (~2^112 PQ)
│   │   ├── layer3-binding/   # Wire binding (algebraic)
│   │   └── layer4-puzzle/    # Planted LWE puzzle (q^128 brute-force)
│   ├── SECURITY.md           # Security model
│   └── wire-binding.md       # Wire binding details
├── paper/
│   ├── tlos-paper.pdf        # Full paper (source of truth)
│   └── tlos.pdf              # Short paper
└── examples/
    ├── TLOSDeadManSwitch.sol # Inheritance: Heartbeat + hidden heir codes
    ├── TLOSRecovery.sol      # Wallet: Phrase-based recovery with puzzle
    ├── TLOSSealedAuction.sol # Gaming: Sealed-bid auction with puzzle
    ├── TLOSStopLoss.sol      # DeFi: Hidden stop-loss triggers
    └── TLOSTreasureHunt.sol  # Honeypot: Commit-reveal + puzzle (educational)

Example Contracts

The examples/ directory contains demonstration contracts showing TLOS integration patterns for various use cases. These are for education only - see warnings in each file.

Example Use Case Layers Used Puzzle Production Ready
TLOSWithPuzzleV5 Production 1-5 (all) Yes [OK]
TLOSDeadManSwitch Inheritance 4 (puzzle) Yes [X] Demo only
TLOSRecovery Wallet recovery 4 (puzzle) Yes [X] Needs phrase entropy
TLOSSealedAuction Sealed-bid auction 4 (puzzle) Yes [X] Demo only
TLOSStopLoss Stop-loss trigger 2 (circuit) No [X] Demo only
TLOSTreasureHunt Honeypot 4 (puzzle) Yes [X] Educational

Layer key:

  • Layer 1: Topology mixing (structural)
  • Layer 2: LWE control function hiding (n=384, σ=25 for production)
  • Layer 3: Wire binding (algebraic)
  • Layer 4: Planted LWE puzzle (one-time q^128 brute-force floor for planted-solution recovery)
  • Layer 5: Hash-based PoW (commit-time randomness binding; difficulty configurable)

Testing

TLOS has comprehensive test coverage with 168 tests across all layers:

# Run all tests
forge test

# Run with gas reporting
forge test --gas-report

# Run specific test file
forge test --match-path test/TLOSWithPuzzleV5.t.sol

Key test files:

  • test/TLOSWithPuzzleV5.t.sol - 61 tests for the production contract (deployment, puzzle, wire binding, cross-layer, commit-reveal, gas benchmarks)
  • test/PuzzleVariants.t.sol - 7 tests for the production puzzle V7 (n=128, q^128 brute-force)
  • test/TLOSWithPuzzleV5Harness.sol - Exposes internal functions for isolated layer testing

Security Disclaimer

TLOS security is based on the standard LWE problem with Gaussian noise and the planted LWE puzzle.

  • The ~2^112 PQ estimate (for n=384, σ=25) is confirmed by the lattice estimator
  • Layer 4 puzzle adds a one-time q^128 brute-force floor for recovering the planted solution; lattice estimator ~2^58 for current params
  • Brute-force search over q^128 is computationally infeasible
  • We encourage independent cryptanalysis
  • Attack scripts organized by layer in scripts/attacks/ - see scripts/attacks/README.md
  • Do not use for high-value, long-lived secrets until further analysis is available

Development Dependencies

For programmatic security estimation, set up the lattice-estimator:

# Clone the estimator (requires SageMath)
git clone https://github.com/malb/lattice-estimator estimator
export PYTHONPATH="$PYTHONPATH:$(pwd)/estimator"

# Add the CLI to PATH
export PATH="$PATH:$(pwd)/scripts"

# Verify installation
lattice-estimator-cli 384 65521 \
    --s-dist '{"distribution":"uniform_mod"}' \
    --e-dist '{"distribution":"discrete_gaussian","stddev":25.0}' \
    --m 2560

Then run the ignored tests to validate security parameters:

cargo test -- --ignored

References

License

MIT

About

TLOS: Topology-Lattice Obfuscation for Smart Contracts

Resources

Security policy

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Contributors 3

  •  
  •  
  •