[{"data":1,"prerenderedAt":315},["ShallowReactive",2],{"i-lucide:sun-moon":3,"i-simple-icons:github":8,"i-simple-icons:linkedin":10,"i-lucide:mail":13,"i-lucide:arrow-up-right":15,"post-\u002Fwriting\u002Fhydra-fly-build-log":17,"i-lucide:shield-alert":307,"i-lucide:arrow-left":309,"i-lucide:lightbulb":311,"i-lucide:info":313},{"left":4,"top":4,"width":5,"height":5,"rotate":4,"vFlip":6,"hFlip":6,"body":7},0,24,false,"\u003Cpath fill=\"none\" stroke=\"currentColor\" stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\" d=\"M12 2v2m2.837 12.385a6 6 0 1 1-7.223-7.222c.624-.147.97.66.715 1.248a4 4 0 0 0 5.26 5.259c.589-.255 1.396.09 1.248.715M16 12a4 4 0 0 0-4-4m7-3l-1.256 1.256M20 12h2\"\u002F>",{"left":4,"top":4,"width":5,"height":5,"rotate":4,"vFlip":6,"hFlip":6,"body":9},"\u003Cpath fill=\"currentColor\" d=\"M12 .297c-6.63 0-12 5.373-12 12c0 5.303 3.438 9.8 8.205 11.385c.6.113.82-.258.82-.577c0-.285-.01-1.04-.015-2.04c-3.338.724-4.042-1.61-4.042-1.61C4.422 18.07 3.633 17.7 3.633 17.7c-1.087-.744.084-.729.084-.729c1.205.084 1.838 1.236 1.838 1.236c1.07 1.835 2.809 1.305 3.495.998c.108-.776.417-1.305.76-1.605c-2.665-.3-5.466-1.332-5.466-5.93c0-1.31.465-2.38 1.235-3.22c-.135-.303-.54-1.523.105-3.176c0 0 1.005-.322 3.3 1.23c.96-.267 1.98-.399 3-.405c1.02.006 2.04.138 3 .405c2.28-1.552 3.285-1.23 3.285-1.23c.645 1.653.24 2.873.12 3.176c.765.84 1.23 1.91 1.23 3.22c0 4.61-2.805 5.625-5.475 5.92c.42.36.81 1.096.81 2.22c0 1.606-.015 2.896-.015 3.286c0 .315.21.69.825.57C20.565 22.092 24 17.592 24 12.297c0-6.627-5.373-12-12-12\"\u002F>",{"left":4,"top":4,"width":5,"height":5,"rotate":4,"vFlip":6,"hFlip":6,"body":11,"hidden":12},"\u003Cpath fill=\"currentColor\" d=\"M20.447 20.452h-3.554v-5.569c0-1.328-.027-3.037-1.852-3.037c-1.853 0-2.136 1.445-2.136 2.939v5.667H9.351V9h3.414v1.561h.046c.477-.9 1.637-1.85 3.37-1.85c3.601 0 4.267 2.37 4.267 5.455v6.286zM5.337 7.433a2.06 2.06 0 0 1-2.063-2.065a2.064 2.064 0 1 1 2.063 2.065m1.782 13.019H3.555V9h3.564zM22.225 0H1.771C.792 0 0 .774 0 1.729v20.542C0 23.227.792 24 1.771 24h20.451C23.2 24 24 23.227 24 22.271V1.729C24 .774 23.2 0 22.222 0z\"\u002F>",true,{"left":4,"top":4,"width":5,"height":5,"rotate":4,"vFlip":6,"hFlip":6,"body":14},"\u003Cg fill=\"none\" stroke=\"currentColor\" stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\">\u003Cpath d=\"m22 7l-8.991 5.727a2 2 0 0 1-2.009 0L2 7\"\u002F>\u003Crect width=\"20\" height=\"16\" x=\"2\" y=\"4\" rx=\"2\"\u002F>\u003C\u002Fg>",{"left":4,"top":4,"width":5,"height":5,"rotate":4,"vFlip":6,"hFlip":6,"body":16},"\u003Cpath fill=\"none\" stroke=\"currentColor\" stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\" d=\"M7 7h10v10M7 17L17 7\"\u002F>",{"id":18,"title":19,"body":20,"canonical":289,"date":290,"description":26,"draft":6,"extension":291,"featured":6,"kind":292,"lang":293,"meta":294,"navigation":12,"path":295,"readingTime":296,"seo":297,"stem":298,"summary":299,"tags":300,"__hash__":306},"writing\u002Fwriting\u002Fhydra-fly-build-log.md","Từ 20.724 xuống 724 ADA: nhật ký dựng một game realtime on-chain trên Hydra",{"type":21,"value":22,"toc":280},"minimark",[23,27,40,43,48,56,63,70,77,94,98,101,111,118,125,187,190,194,205,211,215,222,228,239,246,252,264,268,274,277],[24,25,26],"p",{},"Một game \"Flappy Bird gắn blockchain\" nghe đơn giản đến mức dễ xem thường. Thực tế, dựng nó là chuỗi những lần vỡ trận: mỗi lần một giả định tưởng đúng gãy ra, và mỗi lần gãy lại lộ một giới hạn của mô hình eUTXO. Đây là nhật ký bốn lần vỡ trận đó - kể theo đúng thứ tự diễn ra.",[28,29,32],"callout",{"title":30,"type":31},"Luận điểm trung tâm","insight",[24,33,34,35,39],{},"Bài toán của một game có cược on-chain không phải \"kết nối ví và gửi ADA\", mà là ba ràng buộc đồng thời: xác nhận đủ nhanh để không phá trải nghiệm, phí đủ thấp để stake nhỏ vẫn có lãi, và ",[36,37,38],"em",{},"provably fair"," - người chơi tự xác minh được kết quả, không phải tin vào server.",[24,41,42],{},"Cardano Layer 1 có thời gian xác nhận khoảng 20 giây và phí cố định cho mỗi giao dịch. Không hợp cho microtransaction trong game. Hydra Head giải cả ba ràng buộc cùng lúc: xác nhận dưới 1 giây, phí bằng 0 bên trong Head, và trạng thái vẫn kết toán về L1 bất kỳ lúc nào. Phần còn lại của bài viết là chuyện điều đó gãy ở đâu.",[44,45,47],"h2",{"id":46},"vỡ-trận-1-kẻ-gian-không-cần-hack","Vỡ trận 1: kẻ gian không cần hack",[24,49,50,51,55],{},"Trong lần kiểm thử nội bộ, một lỗ hổng lộ ra mà không đụng tới một dòng anti-cheat nào. Kẻ tấn công không inject điểm, không giả chữ ký. Họ chỉ đọc ",[52,53,54],"code",{},"mapSeed"," từ API, tái tạo bản đồ cục bộ, chạy mô phỏng vật lý để tìm chuỗi tap tối ưu, rồi gửi đúng chuỗi tap đó qua socket như người chơi thật.",[24,57,58,59,62],{},"Mọi lớp anti-cheat đều xanh, vì từng cú tap đều hợp lệ và trông tự nhiên. Cái sai không nằm ở giao dịch - nó nằm ở chỗ ",[36,60,61],{},"server tin rằng người ở đầu bên kia đang thật sự chơi",".",[28,64,67],{"title":65,"type":66},"Physics Simulation Attack","danger",[24,68,69],{},"Không có chữ ký nào bị giả. Bot thắng bằng chính luật chơi thật, chỉ là nó \"chơi\" bằng một trình giải thay vì ngón tay. Đây là lớp gian lận khó nhất: hợp lệ ở mọi tầng kiểm tra kỹ thuật.",[24,71,72,73,76],{},"Hai hướng phòng thủ được xếp ưu tiên cao nhất, và cả hai đều tấn công vào gốc - ",[36,74,75],{},"lấy đi khả năng biết trước bản đồ",":",[78,79,80,88],"ul",{},[81,82,83,87],"li",{},[84,85,86],"strong",{},"Seeded PRNG cho vị trí chướng ngại."," Nếu server giữ toàn bộ layout sinh ra từ seed bí mật, bot không thể pre-compute mà không chạy game thật.",[81,89,90,93],{},[84,91,92],{},"Phát hiện bất thường trong phân phối điểm."," Bot luôn chạm gần điểm tối đa; người thật có phương sai cao hơn nhiều. Theo dõi phân phối điểm theo ví qua thời gian là một tín hiệu khó ngụy trang.",[44,95,97],{"id":96},"vỡ-trận-2-thiết-kế-khoá-20000-ada-để-không-làm-gì","Vỡ trận 2: thiết kế khoá 20.000 ADA để không làm gì",[24,99,100],{},"Bảng xếp hạng on-chain ban đầu có ba lớp, trong đó lớp dưới cùng cấp cho mỗi người chơi một UTXO riêng. Nghe hợp lý, cho tới khi tính chi phí vận hành thật:",[102,103,108],"pre",{"className":104,"code":106,"language":107},[105],"language-text","1.000 người chơi   → 2.000 ADA bị khoá vô thời hạn trong Hydra Head\n10.000 người chơi  → 20.000 ADA bị khoá\n","text",[52,109,106],{"__ignoreMap":110},"",[24,112,113,114,117],{},"Toàn bộ số ADA đó phải được admin commit vào Head ",[36,115,116],{},"trước khi mở",", và không rút được cho đến khi Head đóng. Với bất kỳ operator nào, đây là con số không thực tế - vốn chết nằm im chỉ để giữ chỗ.",[24,119,120,121,124],{},"Lời giải là bỏ hẳn lớp per-player. Admin ký thẳng vào 20 shard UTXO - gọi là ",[84,122,123],{},"Direct Shard Submit",". Kết quả trên mốc 10.000 người chơi:",[126,127,128,144],"table",{},[129,130,131],"thead",{},[132,133,134,138,141],"tr",{},[135,136,137],"th",{},"Chỉ số",[135,139,140],{},"Trước",[135,142,143],{},"Sau",[145,146,147,161,174],"tbody",{},[132,148,149,153,156],{},[150,151,152],"td",{},"ADA khoá trong Head",[150,154,155],{},"~20.724",[150,157,158],{},[84,159,160],{},"724",[132,162,163,166,169],{},[150,164,165],{},"Số UTXO trong Head",[150,167,168],{},"21 + N (tăng mãi)",[150,170,171],{},[84,172,173],{},"21 cố định",[132,175,176,179,182],{},[150,177,178],{},"Thay đổi",[150,180,181],{},"-",[150,183,184],{},[84,185,186],{},"-96,5%",[24,188,189],{},"Ít UTXO hơn không chỉ tiết kiệm ADA. Cách này còn giảm độ trễ xác nhận snapshot và giảm bộ nhớ của mọi Hydra node. Một quyết định, ba tầng lợi ích - dấu hiệu gỡ đúng nút thắt.",[44,191,193],{"id":192},"vỡ-trận-3-20-shard-một-địa-chỉ-một-lỗ-hổng","Vỡ trận 3: 20 shard, một địa chỉ, một lỗ hổng",[24,195,196,197,200,201,204],{},"Sau khi gộp lớp, 20 shard vẫn nằm chung ",[36,198,199],{},"một"," địa chỉ validator. Đó là cửa cho tấn công đầu độc: bất kỳ ai cũng gửi được ADA tới địa chỉ đó, tạo một UTXO giả mang ",[52,202,203],{},"shard_id"," trùng shard thật. Nếu admin lỡ tiêu nhầm UTXO giả, dữ liệu shard đó biến mất, thay bằng dữ liệu của kẻ tấn công.",[24,206,207,208,210],{},"Cách chặn là đưa ",[52,209,203],{}," vào tham số compile-time của validator. Mỗi shard giờ có một địa chỉ Cardano riêng - 20 shard, 20 địa chỉ. Không ai tạo được UTXO hợp lệ cho shard 5 tại địa chỉ shard 7, và không có \"ô nhiễm chéo\" giữa các shard. Một off-chain registry giữ vai trò nguồn sự thật duy nhất: chỉ UTXO do admin tạo và ghi vào registry mới được công nhận, khoá luôn hướng tấn công tạo UTXO giả trước khi khởi tạo.",[44,212,214],{"id":213},"vỡ-trận-4-hai-người-ghi-điểm-cùng-lúc","Vỡ trận 4: hai người ghi điểm cùng lúc",[24,216,217,218,221],{},"Đây là chỗ mô hình eUTXO đòi nợ. Mỗi UTXO chỉ cho phép đúng một giao dịch tiêu tại một thời điểm. Hai giao dịch cùng tham chiếu một shard UTXO thì chỉ một thành công, cái kia bị từ chối. Với 20 shard và phân phối ví bằng ",[52,219,220],{},"keccak256(wallet) % 20",", xác suất va chạm leo rất nhanh:",[102,223,226],{"className":224,"code":225,"language":107},[105],"5 ván\u002Fgiây   → ~2,5% va chạm\n20 ván\u002Fgiây  → ~47,5%\n50 ván\u002Fgiây  → hơn 1 va chạm mỗi giây (không trụ nổi)\n",[52,227,225],{"__ignoreMap":110},[24,229,230,231,234,235,238],{},"Đây chính là ",[36,232,233],{},"shard contention"," - kẻ thù số một của thông lượng trong eUTXO. Lời giải là một hàng đợi riêng cho mỗi shard, ",[52,236,237],{},"concurrency = 1",": không bao giờ có hai giao dịch tranh cùng một shard UTXO.",[24,240,241,242,245],{},"Điểm mấu chốt là ",[36,243,244],{},"vì sao cách này chạy được ở đây mà không chạy trên L1",". Hàng đợi tuần tự chỉ khả thi khi mỗi bước xác nhận cực nhanh. Trên L1, 20 giây một xác nhận biến hàng đợi thành nghẽn cứng. Trên Hydra, dưới 1 giây biến đúng kiến trúc đó thành hệ thống thông lượng cao:",[102,247,250],{"className":248,"code":249,"language":107},[105],"Phase 1: 20 shard × 1 điểm\u002Fgiây        → ~20 điểm\u002Fgiây\nPhase 2: gộp 10 điểm mỗi giao dịch      → ~222 điểm\u002Fgiây (đủ cho hơn 4.400 người chơi đồng thời)\n",[52,251,249],{"__ignoreMap":110},[28,253,256],{"title":254,"type":255},"Chi tiết cơ chế sharding","note",[24,257,258,259,62],{},"Vì sao chọn 21 phân mảnh, chiến lược gộp khi đọc bảng tổng, và các đánh đổi về tính nhất quán được mổ xẻ riêng trong ",[260,261,263],"a",{"href":262},"\u002Fwriting\u002Fhydra-leaderboard-sharding","21 UTXO cho vạn người chơi",[44,265,267],{"id":266},"kiến-trúc-sau-bốn-lần-vỡ-trận","Kiến trúc sau bốn lần vỡ trận",[102,269,272],{"className":270,"code":271,"language":107},[105],"Trạng thái Hydra Head (cố định, không phụ thuộc số người chơi):\n  20 Shard UTXO         - mỗi shard giữ ~200 ví và điểm cao nhất\n  1  GlobalSnapshot     - top-N gộp từ mọi shard\n  ─────────────────────────────────────────────────────────\n  Tổng: 21 UTXO, 724 ADA khoá, ~4 ADA phí L1 một lần\n",[52,273,271],{"__ignoreMap":110},[24,275,276],{},"Mỗi khi một người chơi lập personal best: backend xác minh qua anti-cheat và replay hash, admin ký giao dịch vào đúng shard, Hydra xác nhận dưới 1 giây, điểm số cùng replay hash được ghi vĩnh viễn. Người chơi vào Trust Center tự verify được mọi kết quả - không cần tin server, không cần tin đội ngũ.",[24,278,279],{},"Không có mẹo thần kỳ nào ở đây. Mỗi lần vỡ trận đều bắt đầu từ một giả định trông hiển nhiên - \"cho mỗi người một UTXO\", \"một validator là đủ\", \"cứ ghi song song\" - và chỉ gãy khi chạm số thật. Giá trị không nằm ở kiến trúc cuối cùng gọn gàng, mà ở chuỗi câu hỏi buộc phải trả lời để tới được đó.",{"title":110,"searchDepth":281,"depth":281,"links":282},3,[283,285,286,287,288],{"id":46,"depth":284,"text":47},2,{"id":96,"depth":284,"text":97},{"id":192,"depth":284,"text":193},{"id":213,"depth":284,"text":214},{"id":266,"depth":284,"text":267},"https:\u002F\u002Fwiki.ada-defi.io.vn\u002Fdoc\u002Fcau-chuyen-xay-dung-hydra-fly-tu-y-tuong-den-mainnet-ready-xeWv01p2VY","2026-04-01","md","engineering","vi",{},"\u002Fwriting\u002Fhydra-fly-build-log",11,{"title":19,"description":26},"writing\u002Fhydra-fly-build-log","Hydra Fly là một game kỹ năng thời gian thực chạy trên Cardano Hydra. Kể lại hành trình dựng game qua bốn lần \"vỡ trận\": một cuộc tấn công mô phỏng vật lý không cần hack, thiết kế khoá hơn 20.000 ADA để không làm gì, và bài toán tranh chấp UTXO suýt bóp nghẹt thông lượng.",[301,302,303,304,305],"cardano","hydra","eutxo","scaling","anti-cheat","faQuGzf12sS4ZRH_irKDQ1depiV7WtlDX5MqQaNzhFo",{"left":4,"top":4,"width":5,"height":5,"rotate":4,"vFlip":6,"hFlip":6,"body":308},"\u003Cpath fill=\"none\" stroke=\"currentColor\" stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\" d=\"M20 13c0 5-3.5 7.5-7.66 8.95a1 1 0 0 1-.67-.01C7.5 20.5 4 18 4 13V6a1 1 0 0 1 1-1c2 0 4.5-1.2 6.24-2.72a1.17 1.17 0 0 1 1.52 0C14.51 3.81 17 5 19 5a1 1 0 0 1 1 1zm-8-5v4m0 4h.01\"\u002F>",{"left":4,"top":4,"width":5,"height":5,"rotate":4,"vFlip":6,"hFlip":6,"body":310},"\u003Cpath fill=\"none\" stroke=\"currentColor\" stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\" d=\"m12 19l-7-7l7-7m7 7H5\"\u002F>",{"left":4,"top":4,"width":5,"height":5,"rotate":4,"vFlip":6,"hFlip":6,"body":312},"\u003Cpath fill=\"none\" stroke=\"currentColor\" stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\" d=\"M15 14c.2-1 .7-1.7 1.5-2.5c1-.9 1.5-2.2 1.5-3.5A6 6 0 0 0 6 8c0 1 .2 2.2 1.5 3.5c.7.7 1.3 1.5 1.5 2.5m0 4h6m-5 4h4\"\u002F>",{"left":4,"top":4,"width":5,"height":5,"rotate":4,"vFlip":6,"hFlip":6,"body":314},"\u003Cg fill=\"none\" stroke=\"currentColor\" stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\">\u003Ccircle cx=\"12\" cy=\"12\" r=\"10\"\u002F>\u003Cpath d=\"M12 16v-4m0-4h.01\"\u002F>\u003C\u002Fg>",1790138980678]