|
| 1 | +services: |
| 2 | + app: |
| 3 | + configs: |
| 4 | + - source: run.sh |
| 5 | + target: /root/run.sh |
| 6 | + - source: oracle.py |
| 7 | + target: /root/oracle.py |
| 8 | + volumes: |
| 9 | + - /var/run/dstack.sock:/var/run/dstack.sock |
| 10 | + build: |
| 11 | + context: . |
| 12 | + dockerfile_inline: | |
| 13 | + FROM ubuntu:24.04@sha256:b59d21599a2b151e23eea5f6602f4af4d7d31c4e236d22bf0b62b86d2e386b8f |
| 14 | + RUN apt-get update && apt install -y curl python3 python3-pip |
| 15 | + RUN pip3 install --break-system-packages ecdsa requests dstack-sdk |
| 16 | + WORKDIR /root |
| 17 | + # Helios 0.11.0 |
| 18 | + RUN curl -L 'https://github.com/a16z/helios/releases/download/0.11.0/helios_linux_amd64.tar.gz' | tar -xzC . |
| 19 | + CMD ["bash", "/root/run.sh"] |
| 20 | + platform: linux/amd64 |
| 21 | + |
| 22 | +configs: |
| 23 | + run.sh: |
| 24 | + content: | |
| 25 | + RPC=$${ETH_RPC_URL:-https://ethereum-rpc.publicnode.com} |
| 26 | + echo "Using execution RPC: $$RPC" |
| 27 | +
|
| 28 | + /root/helios ethereum \ |
| 29 | + --network mainnet \ |
| 30 | + --execution-rpc "$$RPC" \ |
| 31 | + --fallback https://sync-mainnet.beaconcha.in \ |
| 32 | + --rpc-bind-ip 0.0.0.0 & |
| 33 | +
|
| 34 | + echo "Waiting for Helios to sync..." |
| 35 | + for i in $$(seq 1 30); do |
| 36 | + if curl -s localhost:8545 -X POST -H "Content-Type: application/json" \ |
| 37 | + -d '{"jsonrpc":"2.0","method":"eth_blockNumber","params":[],"id":1}' | grep -q result; then |
| 38 | + echo "Helios synced!" |
| 39 | + break |
| 40 | + fi |
| 41 | + sleep 2 |
| 42 | + done |
| 43 | +
|
| 44 | + python3 /root/oracle.py |
| 45 | +
|
| 46 | + oracle.py: |
| 47 | + content: | |
| 48 | + import json, hashlib, requests |
| 49 | + from ecdsa import SigningKey, NIST256p |
| 50 | +
|
| 51 | + HELIOS = "http://localhost:8545" |
| 52 | + CHECKPOINT_API = "https://sync-mainnet.beaconcha.in" |
| 53 | + DAI = "0x6b175474e89094c44da98b954eedeac495271d0f" |
| 54 | +
|
| 55 | + # Try to connect to TEE environment |
| 56 | + client = None |
| 57 | + try: |
| 58 | + from dstack_sdk import TappdClient |
| 59 | + client = TappdClient() |
| 60 | + key_result = client.derive_key("/oracle", "") |
| 61 | + sk = SigningKey.from_pem(key_result.key) |
| 62 | + print(f"TEE: using derived key (curve: {sk.curve.name})", flush=True) |
| 63 | + except Exception as e: |
| 64 | + print(f"WARNING: Not in TEE ({e}), using random key", flush=True) |
| 65 | + sk = SigningKey.generate(curve=NIST256p) |
| 66 | + client = None |
| 67 | +
|
| 68 | + pk = sk.get_verifying_key() |
| 69 | +
|
| 70 | + def rpc(method, params=[]): |
| 71 | + r = requests.post(HELIOS, json={"jsonrpc":"2.0","method":method,"params":params,"id":1}) |
| 72 | + resp = r.json() |
| 73 | + if "error" in resp: |
| 74 | + raise Exception(resp["error"]) |
| 75 | + return resp.get("result") |
| 76 | +
|
| 77 | + def get_checkpoint(): |
| 78 | + r = requests.get(f"{CHECKPOINT_API}/checkpointz/v1/status", timeout=5) |
| 79 | + data = r.json()["data"]["finality"]["finalized"] |
| 80 | + return {"epoch": int(data["epoch"]), "root": data["root"]} |
| 81 | +
|
| 82 | + # Fetch verified data via Helios |
| 83 | + checkpoint = get_checkpoint() |
| 84 | + block_num = rpc("eth_blockNumber") |
| 85 | + block = rpc("eth_getBlockByNumber", [block_num, False]) |
| 86 | + call_result = rpc("eth_call", [{"to": DAI, "data": "0x18160ddd", "gas": "0x100000"}, block_num]) |
| 87 | +
|
| 88 | + claim = { |
| 89 | + "type": "lightclient_attestation", |
| 90 | + "network": "mainnet", |
| 91 | + "checkpoint_epoch": checkpoint["epoch"], |
| 92 | + "checkpoint_root": checkpoint["root"], |
| 93 | + "block_number": int(block_num, 16), |
| 94 | + "block_hash": block["hash"], |
| 95 | + "state_root": block["stateRoot"], |
| 96 | + "call": {"to": DAI, "data": "0x18160ddd", "result": call_result}, |
| 97 | + } |
| 98 | +
|
| 99 | + claim_bytes = json.dumps(claim, sort_keys=True).encode() |
| 100 | + claim_hash = hashlib.sha256(claim_bytes).digest() |
| 101 | + sig = sk.sign_deterministic(claim_hash, hashfunc=hashlib.sha256) |
| 102 | +
|
| 103 | + quote = client.tdx_quote(claim_hash.hex()).quote if client else None |
| 104 | +
|
| 105 | + proof = { |
| 106 | + "claim": claim, |
| 107 | + "claimHash": claim_hash.hex(), |
| 108 | + "signature": sig.hex(), |
| 109 | + "pubkey": pk.to_string().hex(), |
| 110 | + "quote": quote, |
| 111 | + } |
| 112 | +
|
| 113 | + print(json.dumps(proof, indent=2)) |
0 commit comments