オンチェーンライドライフサイクルのためのカスタムRustブロックチェーンの構築方法
原題: How I Built a Custom Rust Blockchain for On-Chain Ride Lifecycle
分析結果
- カテゴリ
- AI
- 重要度
- 65
- トレンドスコア
- 27
- 要約
- この記事では、オンチェーンでのライドライフサイクル管理のためにカスタムRustブロックチェーンを構築する過程を紹介します。Rustの特性を活かし、効率的で安全なブロックチェーンを設計し、ライドの開始から終了までのトラッキングを実現しました。具体的な実装手法や直面した課題、解決策についても詳しく解説しています。
- キーワード
I wanted ride-sharing operations — request, offer, accept, pay, cancel — to be first-class on-chain transactions , not generic smart-contract calls wrapped in app logic. So I built Clutch Protocol : a custom non-EVM blockchain in Rust, a GraphQL bridge for apps, a JavaScript SDK for client-side signing, and a public stage testnet you can try without installing anything. This post is the technical story: what I built, why I didn't use Ethereum, how a ride actually flows through the stack, and what's still alpha. The problem I was solving Traditional ride apps centralize trust: the platform owns matching, payments, and dispute resolution. Putting the ride state machine on-chain changes the contract between riders, drivers, and app builders: Every step is a signed, auditable transaction Private keys stay on the client (Bitcoin-style) App developers can earn on-chain referrer fees when users complete rides Drivers receive CLT directly via RidePay , not through a platform ledger The tradeoff is real: you lose EVM composability and must ship custom SDKs. For a domain-specific protocol, that tradeoff felt acceptable. Architecture at a glance Demo App / Your dApp │ ▼ clutch-hub-sdk-js (client-side signing, RLP, secp256k1) │ ▼ clutch-hub-api (GraphQL + WebSocket + faucet) │ ▼ clutch-node (Aura consensus, WebSocket JSON-RPC) │ ▼ clutch-explorer (indexer → Postgres → REST UI) Component Role Stack clutch-node Blockchain core Rust, Aura, libp2p clutch-hub-api App bridge Rust, async-graphql clutch-hub-sdk-js Client SDK TypeScript, npm clutch-hub-demo-app Reference UI React, Vite, Leaflet clutch-deploy Full stack Docker Compose Docs: https://docs.clutchprotocol.io Why a custom chain (and not Ethereum) Clutch is non-EVM . Ride operations are native transaction types with RLP encoding: Tag Type Purpose 1 RideRequest Passenger requests a ride 2 RideOffer Driver offers to fulfill 3 RideAcceptance Passenger accepts; fare debited 4 RidePay Payment installment to driver + referrers 5 RideCancel Cancel trip; refund unpaid fare 8 RideRequestCancel Cancel pending request Apps don't deploy contracts. They call the Hub API for unsigned payloads, sign locally, and submit signed RLP hex. The node validates signatures, nonces, and applies the ride state machine. What you gain: simpler app surface, predictable tx format, ride logic enforced in the node. What you lose: DeFi composability, existing wallet/tooling, large validator ecosystem. How a ride works (end to end) RideRequest → RideOffer(s) → RideAcceptance → RidePay → completed ↓ ↓ RideRequestCancel RideCancel 1. Build unsigned transaction (server) The Hub API constructs the payload and injects referrer addresses from config: mutation { createUnsignedRideRequest ( pickupLatitude : 35.7 , pickupLongitude : 51.4 , dropoffLatitude : 35.8 , dropoffLongitude : 51.5 , fare : 1000 ) } Returns JSON like: { "from" : "0x..." , "nonce" : 3 , "data" : { "function_call_type" : "RideRequest" , "arguments" : { } } } 2. Sign client-side (never send private keys) The SDK hashes and signs with secp256k1. Keys never touch the API: import { ClutchHubSdk } from ' clutch-hub-sdk-js ' ; const sdk = new ClutchHubSdk ( ' https://api-stage.clutchprotocol.io ' , publicKey ); await sdk . ensureAuth (); const unsigned = await sdk . createUnsignedRideRequest ({ pickup : { latitude : 35.7 , longitude : 51.4 }, dropoff : { latitude : 35.8 , longitude : 51.5 }, fare : 1000 , }); const signed = await sdk . signTransaction ( unsigned , privateKey ); 3. Submit signed transaction await sdk . submitTransaction ( signed . rawTransaction ); The Hub forwards to the node over WebSocket JSON-RPC ( send_raw_transaction ). Validators include the tx in a block; state updates atomically. 4. Read state (GraphQL or subscriptions) const requests = await sdk . listRideRequests (); await sdk . subscribeRideRequests (( updated ) => { console . log ( ' Open requests: ' , updated . length ); }); Subscriptions multiplex over a shared WebSocket to /graphql/ws . Under the hood the API polls the node (~0.5–1s) and pushes snapshots — honest alpha limitation. CLT economics (driver-first) Ride payments and validator rewards are separate : Layer Mechanism Default RidePay Referrer fees + driver remainder 2% request + 2% offer Blocks Fixed reward to block author 50 CLT per block Example: 10 CLT fare, one full RidePay , both referrers set: Request referrer: 1 CLT Offer referrer: 1 CLT Driver: 8 CLT App builders: run your own Hub API, set your wallet as default_ride_request_referrer / default_ride_offer_referrer , and earn CLT when users complete rides on your deployment. No separate grants program — rewards come from real ride activity. Details: https://docs.clutchprotocol.io/getting-started/app-developer-incentives Security model Client-side signing only — API receives signed RLP hex, not private keys Wallet JWT — identity is a public key ( generateToken ), no passwords Nonce anti-replay — per-account nonce enforced on-chain Faucet — only server-side signer, testnet Transfer only; disable in production Try it in 3 minutes (no install) Open https://app-stage.clutchprotocol.io Choose Passenger or Driver → generate wallet → Request CLT (faucet) Passenger: request a ride on the map · Driver: submit an offer Full tutorial: https://docs.clutchprotocol.io/getting-started/ride-lifecycle Run the full stack locally git clone https://github.com/clutchprotocol/clutch-deploy.git cd clutch-deploy cp .env.example .env docker compose up -d Service URL Demo app http://localhost:5173 Hub API http://localhost:3000/health Explorer http://localhost:5174 npm install clutch-hub-sdk-js What's alpha (honest limitations) Testnet only — no mainnet, small validator set on stage DAO governance — roadmap, not shipped ConfirmArrival / ComplainArrival — stubs in the node, not in Hub/SDK yet Hub subscriptions poll the node; not push-from-chain yet APIs may change without notice Open source Eight public repos under https://github.com/clutchprotocol Star the org if this is interesting Discussions: https://github.com/orgs/clutchprotocol/discussions Issues and PRs welcome — conventional commits appreciated Questions I'd love feedback on Domain-specific chain vs. smart contracts — worth it for ride-sharing, or would you always pick an L2? Referrer-fee model for app builders — sensible incentive or weird? What would you build on this stack? Links Website: https://clutchprotocol.io Docs: https://docs.clutchprotocol.io Stage demo: https://app-stage.clutchprotocol.io npm SDK: https://www.npmjs.com/package/clutch-hub-sdk-js GitHub: https://github.com/clutchprotocol Built by Mehran Mazhar ( GitHub ). Alpha software — use at your own risk. I wanted ride-sharing operations — request, offer, accept, pay, cancel — to be first-class on-chain transactions , not generic smart-contract calls wrapped in app logic. So I built Clutch Protocol : a custom non-EVM blockchain in Rust, a GraphQL bridge for apps, a JavaScript SDK for client-side signing, and a public stage testnet you can try without installing anything. This post is the technical story: what I built, why I didn't use Ethereum, how a ride actually flows through the stack, and what's still alpha. The problem I was solving Traditional ride apps centralize trust: the platform owns matching, payments, and dispute resolution. Putting the ride state machine on-chain changes the contract between riders, drivers, and app builders: Every step is a signed, auditable transaction Private keys stay on the client (Bitcoin-style) App developers can earn on-chain referrer fees when users complete rides Drivers receive CLT directly via RidePay , not through a platform ledger The tradeoff is real: you lose EVM composability and must ship custom SDKs. For a domain-specific protocol, that tradeoff felt acceptable. Architecture at a glance Demo App / Your dApp │ ▼ clutch-hub-sdk-js (client-side signing, RLP, secp256k1) │ ▼ clutch-hub-api (GraphQL + WebSocket + faucet) │ ▼ clutch-node (Aura consensus, WebSocket JSON-RPC) │ ▼ clutch-explorer (indexer → Postgres → REST UI) Component Role Stack clutch-node Blockchain core Rust, Aura, libp2p clutch-hub-api App bridge Rust, async-graphql clutch-hub-sdk-js Client SDK TypeScript, npm clutch-hub-demo-app Reference UI React, Vite, Leaflet clutch-deploy Full stack Docker Compose Docs: https://docs.clutchprotocol.io Why a custom chain (and not Ethereum) Clutch is non-EVM . Ride operations are native transaction types with RLP encoding: Tag Type Purpose 1 RideRequest Passenger requests a ride 2 RideOffer Driver offers to fulfill 3 RideAcceptance Passenger accepts; fare debited 4 RidePay Payment installment to driver + referrers 5 RideCancel Cancel trip; refund unpaid fare 8 RideRequestCancel Cancel pending request Apps don't deploy contracts. They call the Hub API for unsigned payloads, sign locally, and submit signed RLP hex. The node validates signatures, nonces, and applies the ride state machine. What you gain: simpler app surface, predictable tx format, ride logic enforced in the node. What you lose: DeFi composability, existing wallet/tooling, large validator ecosystem. How a ride works (end to end) RideRequest → RideOffer(s) → RideAcceptance → RidePay → completed ↓ ↓ RideRequestCancel RideCancel 1. Build unsigned transaction (server) The Hub API constructs the payload and injects referrer addresses from config: mutation { createUnsignedRideRequest ( pickupLatitude : 35.7 , pickupLongitude : 51.4 , dropoffLatitude : 35.8 , dropoffLongitude : 51.5 , fare : 1000 ) } Returns JSON like: { "from" : "0x..." , "nonce" : 3 , "data" : { "function_call_type" : "RideRequest" , "arguments" : { } } } 2. Sign client-side (never send private keys) The SDK hashes and signs with secp256k1. Keys never touch the API: import { ClutchHubSdk } from ' clutch-hub-sdk-js ' ; const sdk = new ClutchHubSdk ( ' https://api-stage.clutchprotocol.io ' , publicKey ); await sdk . ensureAuth (); const unsigned = await sdk . createUnsignedRideRequest ({