The Sovereign, Programmable Oracle Ecosystem.
TaaS is a decentralized oracle protocol that allows developers to define, simulate, and deploy verifiable, logic-driven data pipelines — called Recipes — that execute identically in simulation and production. It moves beyond simple price feeds to support complex, multi-step, conditional logic with cryptographic proof at every step.
Traditional oracles deliver a single data point — a price, a score, a boolean. TaaS delivers verifiable programs.
A TaaS Recipe is a Directed Acyclic Graph (DAG) of steps. Each step can fetch data from multiple sources, apply logic, transform results, and gate execution on conditions. The final output — whatever the recipe computes — is signed by a threshold committee using GG20 TSS ECDSA, making it cryptographically verifiable on any EVM chain.
Examples of what a Programmable Oracle can do:
- Fetch BTC price from Binance, CoinGecko, and CMC → compute the median → sign: "BTC price is $84,250 (consensus of 3 sources)"
- Watch a football match → wait for it to finish → return the score → sign: "Manchester City 2 – 1 Arsenal (verified by 2 sources, state-guarded against cancellation)"
- Fetch ETH price → check if it is below a DeFi position's liquidation threshold → sign: "Position #1337 should be liquidated: TRUE"
- Simulate a user's prediction market intent entirely offline before submitting anything on-chain
This monorepo is a complete, production-hardened implementation of the TaaS protocol. Here is what exists across each package:
The high-performance oracle node. It owns the full execution pipeline.
- VEE (Verifiable Execution Engine): Orchestrates multi-source data fetching, UCM-driven normalization, and aggregation (MEDIAN, CONSENSUS, UNION)
- GG20 TSS Signing: Threshold ECDSA with 1-party direct fallback. Results are signed with a cryptographic key that is tied to the node's on-chain identity
- WASM Executor: Sandboxed execution of recipe logic modules (wasmi, 1M fuel cap, 1MB output limit)
- TDS (Transparent Data Swarm): Reed-Solomon (Galois-8) erasure coding + SHA-256 Merkle tree proofs for decentralized storage of recipe data and attestation history
- P2P Network: libp2p Swarm with Noise + Yamux transport, mDNS + Kademlia DHT, GossipSub for TSS state and execution relay
- UCM (Unified Capability Manifest): Schema-validated capability definitions covering crypto, sports (football, basketball), and an extensible plugin architecture
- Encrypted Storage: Transparent AES-256-GCM wrapping over all storage writes — secrets never touch disk in plaintext
- Quota Manager: Per-source per-minute rate tracking with circuit breakers and P2P fallback relay
- Worker Supervisor: Lifecycle management of TypeScript Logic Host sidecars with kill-on-drop and Prometheus metric forwarding
The shared execution engine, used by both the gateway and the SDK's local simulator.
RecipeExecutor: DAG traversal in dependency order, parallel branch execution, context passing between nodesNormalizer: Multi-source aggregation (MEDIAN, CONSENSUS, UNION) with schema-driven field mappingSDKValidator: Static analysis — cycle detection, input validation, schema enforcement
The on-chain and economic layer. The Node does not fetch data — that is the Gateway's job.
- SentinelOrchestrator: Watches on-chain events (contract requests, deadline triggers) and dispatches execution to the Gateway
- AuditService (Challenger): Re-executes recipes independently and submits on-chain dispute proofs when results mismatch
- PresenceService: Broadcasts EIP-712 signed presence attestations so the Gateway can track active, staked nodes
- NodeHealthService: Monitors stake balance, detects slashing events, sends registration heartbeats
- VRFService: Generates verifiable randomness for committee selection
- BLSKeyService: Manages BLS keys for aggregate attestation submission (gas-optimized proof bundling)
- StorageService: Serves TDS shards via gRPC on
:50052
The developer-facing SDK. Allows building, testing, and deploying Recipes without understanding the internals.
Recipe.define(): Fluent DSL for defining oracle recipes with typed inputsStep.data.fetch(): Fetch from any registered data source by capability IDStep.logic.*: Boolean logic, comparisons, conditional branchingmyRecipe.test(): Local execution with mock data — no gateway neededmyRecipe.compile(): Converts the recipe handler into a protocol DAG JSONTruthGatewayClient.simulate(): Sends the compiled recipe to a live Gateway node for end-to-end simulationSDKValidator.analyzeDAG(): Static cycle detection and schema validation
On-chain infrastructure:
RecipeRegistry: Maps recipe IDs to TDS CIDs, anchoring off-chain logic to the chainTruthRegistry: Accepts TSS-signed attestations, stores verified truth on-chainDisputeRegistry: Handles challenger submissions and slashing logic
Developer (taas-sdk)
│
│ 1. Define a Recipe (DSL)
│ Recipe.define({ name: "...", inputs: {...}, handler: async (inputs) => { ... } })
│
│ 2. Test locally with mock data
│ myRecipe.test({ threshold: 55000 }, { mocks: { "crypto.price": () => 60000 } })
│
│ 3. Compile to Protocol DAG
│ const blueprint = await myRecipe.compile()
│ // → { nodes: [...], edges: [...], inputs: {...}, schema: {...} }
│
│ 4. Simulate on a live Gateway (optional before deployment)
│ const result = await client.simulate(blueprint, inputs)
│
▼
TaaS Gateway (Rust — taas-gateway)
│
│ 5. Receive recipe DAG via POST /recipe/execute [TODO: ORACLE-1]
│
│ 6. Execute each node via RecipeExecutor (taas-core-rs)
│ • Fetch nodes → sidecar plugins (Binance, SportDB, SportMonks...)
│ • Logic nodes → WASM Executor (wasmi sandbox)
│ • State guards → UCM-driven pre-condition checks
│
│ 7. Normalize and aggregate results
│ • MEDIAN for pricing (removes outlier manipulation)
│ • CONSENSUS for match data (plurality across sources)
│ • UNION for event lists (merge across sources)
│
│ 8. Sign output via GG20 TSS or direct ECDSA
│ → 0x{r}{s}{v} Ethereum-compatible signature
│
│ 9. Store attestation receipt to TDS
│ → Reed-Solomon shards distributed across peers
│ → SHA-256 Merkle proof per shard
│
▼
TaaS Node (TypeScript — taas-nodes)
│
│ 10. SentinelOrchestrator detects on-chain request event
│ 11. AuditService independently re-executes and validates
│ 12. Submit signed attestation on-chain via viem
│ → TruthRegistry.recordTruth(recipeId, result, signature)
│ 13. BLSKeyService aggregates signatures for gas-efficient proof
│
▼
Smart Contract (taas-contracts)
│
│ 14. TruthRegistry stores the verified, signed data point on-chain
│ 15. Your DeFi protocol / prediction market / insurance contract reads it
| Category | Capabilities |
|---|---|
| Crypto | crypto.price — Multi-source median price (Binance, CoinGecko, CMC) |
| Football | Score, Statistics, Events, Goals, Cards (Yellow/Red), Status, Lineup, Substitutions |
| Basketball | Score with period breakdown (NBA focus) |
| Football Meta | League standings, upcoming matches, top scorers, team details, player bio |
| Extensible | Any TypeScript plugin registered in core/data/plugin-manifest.json |
Taas/
├── taas-gateway/ Rust oracle node (VEE, TSS, TDS, P2P, WASM)
│ ├── rust/hot-core/ Core Rust binary
│ ├── rust/tds/ Reed-Solomon + Merkle storage library
│ ├── rust/crates/ gateway-worker, gateway-signer, gateway-cache
│ ├── ts/sidecar/ TypeScript Logic Host (plugin dispatcher)
│ └── core/data/ UCM manifest (capabilities.json, plugin-manifest.json)
│
├── taas-core-rs/ Shared Rust/WASM execution engine
│ └── src/
│ ├── executor.rs RecipeExecutor — DAG traversal
│ ├── normalizer.rs Multi-source aggregation
│ └── lib.rs WASM bindings for SDK simulator
│
├── taas-nodes/ TypeScript on-chain / economic layer
│ └── src/services/ Sentinel, Audit, Presence, VRF, BLS, Storage
│
├── taas-sdk/ Developer SDK
│ ├── src/core/ TaasClient, IntentBuilder, FluentAPI, Simulator
│ └── examples/ 20+ recipe examples (crypto, sports, DeFi)
│
├── taas-contracts/ Solidity contracts (Registry, Dispute, Truth)
├── taas-abis/ Generated ABI types
├── taas-interfaces/ Shared TypeScript types
├── taas-proto/ gRPC protobuf definitions
└── shadow-wallet/ Key management tooling
git clone https://github.com/friehub/Taas.git && cd Taas
pnpm install
pnpm buildcd taas-gateway
# First run: initialize vault and generate identity key
./taas-gateway init
# Start the node
REDIS_URL=redis://127.0.0.1:6379 ./taas-gateway startimport { Recipe, Step, Truth, TruthGatewayClient } from '@taas/sdk';
// 1. Define
const btcAlert = Recipe.define({
name: "BTC Above 75k",
outcomeType: "BINARY",
inputs: {
threshold: Step.input.number("Price Threshold").range(1000, 1_000_000)
},
async handler(inputs) {
const price = Truth.crypto.price({ symbol: "BTC" });
return Step.logic.gt(price, inputs.threshold);
}
});
// 2. Test locally
const localResult = await btcAlert.test(
{ threshold: 75000 },
{ mocks: { "crypto.price": () => 84250 } }
);
console.log(localResult.truth); // "YES"
// 3. Compile and simulate on live Gateway
const blueprint = await btcAlert.compile();
const client = new TruthGatewayClient("http://localhost:8080");
const result = await client.simulate(blueprint, { threshold: 75000 });
console.log(result.truth); // 0 (TRUE) or 1 (FALSE)
console.log(result.signature); // 0x... TSS signatureimport { Recipe, Step, Truth, TruthGatewayClient } from '@taas/sdk';
const matchResult = Recipe.define({
name: "Chelsea vs Arsenal Final Score",
outcomeType: "STRUCTURED",
inputs: {
matchId: Step.input.string("Match ID")
},
async handler(inputs) {
return Truth.sports.football.score({ matchId: inputs.matchId });
}
});
const blueprint = await matchResult.compile();
const client = new TruthGatewayClient("http://localhost:8080");
const result = await client.simulate(blueprint, { matchId: "1234567" });
// → { home_score: 2, away_score: 1, status: "Finished", signature: "0x..." }Why Rust for the Gateway? The VEE needs to handle hundreds of concurrent fetch-normalize-sign pipelines. Rust's ownership model and async runtime (Tokio) give us zero-copy data paths, bounded memory, and no GC pauses on critical signing paths.
Why a TypeScript sidecar for plugins? Data source adapters are inherently I/O-bound and change frequently. TypeScript plugins can be hot-deployed without recompiling the Rust core. The gRPC boundary between them provides isolation: a crashing plugin cannot take down the entire node.
Why GG20 TSS instead of a single private key? A single key is a single point of failure and a single point of compromise. GG20 distributes the signing key across a committee — no single node ever holds the full key, and the committee threshold prevents any minority group from signing on behalf of the network.
Why Reed-Solomon + Merkle for storage? Attestation receipts must be available forever. Reed-Solomon allows reconstruction of any file even if a fraction of storage nodes go offline. Merkle proofs allow any peer to verify a single shard without downloading the whole file.
See the detailed audit files for exact source locations:
- taas-gateway/todo.md — 42 identified flaws and fixes (Critical → Low)
- taas-nodes/todo.md — Node role definition, 4 security bugs, 7 feature gaps
Key items pending before full programmable oracle v1:
POST /recipe/executeendpoint on the Gateway (accepts full DAG, returns signed result)- TDS node configuration moved to
gateway.toml(currently hardcoded to localhost) - Admin API authentication on
:9090 - TSS key persistence bug fix (
save_keyis dead code — node identity resets on restart) - SportMonks API key must be moved from source code to Vault
- Normalizer JSONPath filter expression support (
jsonpath-rustcrate) - Sidecar auto-restart on crash
| Package | Language | Description |
|---|---|---|
taas-gateway |
Rust | Oracle node — VEE, TSS, TDS, P2P, WASM |
taas-core-rs |
Rust/WASM | Shared recipe executor and normalizer |
taas-nodes |
TypeScript | On-chain layer — Sentinel, Challenger, staking |
@taas/sdk |
TypeScript | Developer SDK — Recipe DSL, simulator, compiler |
@taas/interfaces |
TypeScript | Shared type definitions |
@taas/proto |
Protobuf | gRPC service definitions |
@taas/abis |
Solidity/TS | Generated contract ABIs |