Các ứng dụng onchain ngày càng phụ thuộc vào randomness: xổ số, game, NFT minting, phân phối phần thưởng, đấu giá treasury và các thí nghiệm governance. Tuy nhiên, randomness trên blockchain lại khó hơn vẻ ngoài nhiều. Khác với phần mềm truyền thống, smart contract không thể đơn giản gọi một thư viện chuẩn như Math.random() rồi tin vào kết quả. Mỗi node trong mạng phải có thể tái tạo cùng một execution, điều này khiến randomness thật sự trở nên hiếm và dễ vỡ.
Bài viết này sẽ trình bày các thách thức cốt lõi trong việc tạo randomness onchain, các phương pháp mà các đội nhóm đang dùng hiện nay, và một ví dụ Solidity ngắn gọn làm nổi bật các phần quan trọng của một triển khai thực tế.
1. Vì sao Randomness onchain lại khó đến vậy
Vấn đề đầu tiên là về kiến trúc: blockchain được thiết kế theo kiểu deterministic. Nếu một contract yêu cầu một giá trị ngẫu nhiên, mọi validator hoặc node cuối cùng phải đồng ý về cùng một kết quả. Điều này có nghĩa là giá trị ngẫu nhiên không thể được sinh ra từ một nguồn riêng tư duy nhất, vì sẽ không thể chứng minh hoặc tái tạo một cách phi tập trung mà không làm lộ nguồn đó.
Điều này tạo ra ba thách thức lớn:
- Không có randomness riêng tư native
- Một blockchain không thể dựa vào một nguồn entropy từ CPU cục bộ mà không phá vỡ consensus.
- Bất kỳ giá trị nào được sinh ra bên trong contract đều có thể bị dự đoán bởi mạng nếu các input đã được biết.
- Rủi ro MEV và thao túng
- Miners, validators hoặc block builders có thể ảnh hưởng đến thứ tự giao dịch.
- Trong một số trường hợp, họ có thể thiên vị kết quả bằng cách chọn thời điểm công bố giao dịch hoặc quan sát trạng thái đang chờ xử lý.
- Giả định niềm tin và liveness
- Một số hệ thống phụ thuộc vào một bên thứ ba đáng tin cậy để cung cấp randomness.
- Những hệ thống khác phụ thuộc vào một mạng phi tập trung, nhưng phải chấp nhận các tradeoff về độ trễ, chi phí hoặc độ phức tạp.
Đây chính là lý do vì sao “randomness” thường là phần bị xem nhẹ nhất trong một thiết kế onchain.
2. Các cách tiếp cận chính mà các đội nhóm đang dùng hiện nay
A. Commit-Reveal Schemes
Một trong những mẫu cũ nhất là commit-reveal. Người tham gia trước tiên cam kết một số bí mật, sau đó mới công bố nó. Contract kiểm tra xem việc reveal có khớp với commitment hay không, và randomness cuối cùng được suy ra từ tất cả các giá trị đã nộp.
Vì sao nó được dùng:
- Dễ hiểu.
- Hoạt động tốt cho game và các protocol đa bên.
- Không cần oracle bên ngoài.
Vì sao nó thất bại trong thực tế:
- Người dùng có thể bỏ cuộc sau khi thấy người khác reveal.
- Lợi thế của người reveal cuối có thể làm méo mó tính công bằng.
- Nó dễ bị griefing và các vấn đề phối hợp.
Cách tiếp cận này hữu ích cho một số ứng dụng, nhưng chưa đủ cho randomness có giá trị cao hoặc production-grade.
B. Verifiable Random Functions (VRFs)
Một cách mạnh mẽ hơn là sử dụng Verifiable Random Function. VRF tạo ra một đầu ra giả ngẫu nhiên và một bằng chứng mật mã mà bất kỳ ai cũng có thể kiểm tra được. Đầu ra không thể bị dự đoán cho đến khi provider reveal nó, nhưng bằng chứng lại chứng minh rằng kết quả đã được tạo đúng.
Đây là cách tiếp cận được nhiều hệ thống oracle hiện đại dùng, bao gồm Chainlink VRF và các hệ tương tự.
Vì sao các đội nhóm thích nó:
- Có thể kiểm chứng bằng mật mã mạnh.
- Kháng thao túng tốt hơn so với việc tạo randomness trực tiếp trên chuỗi.
- Dễ tích hợp vào smart contract.
Tradeoffs:
- Vẫn phụ thuộc vào một provider hoặc committee bên ngoài.
- Tạo thêm chi phí và độ trễ.
- Người dùng phải tin vào cấu hình và mô hình kinh tế của provider.
C. Distributed Randomness Beacons
Một cách tiếp cận khác là randomness beacon phân tán, trong đó một nhóm người tham gia độc lập cùng nhau tạo ra một giá trị ngẫu nhiên. Các hệ như drand dùng threshold cryptography để tạo ra một dòng random public liên tục.
Vì sao nó hấp dẫn:
- Không có một bên nào kiểm soát đầu ra.
- Có đặc tính phi tập trung mạnh.
- Câu chuyện về công bằng tốt hơn so với randomness dựa trên oracle một lần.
Tradeoffs:
- Độ phức tạp hạ tầng cao hơn.
- Không phải lúc nào cũng phù hợp với các trường hợp dùng riêng lẻ.
- Cần xử lý cẩn thận vấn đề liveness và sự tham gia của committee.
D. Threshold Signatures và MPC-Based Randomness
Trong một số protocol, randomness được tạo ra bằng threshold signature hoặc MPC. Nhiều bên cùng đóng góp một phần randomness, và đầu ra cuối cùng chỉ có thể tái tạo khi đủ số bên tham gia.
Đây thường được thấy trong các hệ thống tổ chức hoặc permissioned, nơi mô hình bảo mật được kiểm soát chặt chẽ hơn và các bên tham gia đều đã biết trước.
3. “Randomness tốt” thường có nghĩa gì
Đối với hầu hết các đội, mục tiêu không phải là randomness hoàn hảo theo nghĩa toán học. Nó là một sự kết hợp thực tế giữa:
- Khả năng không thể dự đoán trước khi reveal.
- Khả năng chống thiên vị sau khi tạo.
- Khả năng kiểm chứng cho các bên dùng tiếp.
- Liveness để hệ thống vẫn hoạt động dù một số bên ngoại tuyến.
- Hiệu quả chi phí đủ bền vững trên chuỗi.
Trong thực tế, các hệ tốt nhất là những hệ cân bằng được các thuộc tính này mà không giả vờ mình là phép thuật.
4. Một ví dụ Solidity ngắn: Randomness dựa trên VRF
Dưới đây là một ví dụ tối giản minh họa các phần chính của một contract consumer VRF. Mẫu này giống nhau trên nhiều provider oracle:
- Yêu cầu randomness.
- Nhận callback với các random words.
- Dùng kết quả trong logic ứng dụng.
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;
import "@chainlink/contracts/src/v0.8/interfaces/VRFCoordinatorV2Interface.sol";
import "@chainlink/contracts/src/v0.8/VRFConsumerBaseV2.sol";
contract FairDraw is VRFConsumerBaseV2 {
VRFCoordinatorV2Interface private immutable COORDINATOR;
uint64 private immutable subscriptionId;
bytes32 private immutable keyHash;
uint256 public requestId;
uint256 public randomValue;
event RandomRequested(uint256 indexed requestId, address requester);
event RandomFulfilled(uint256 indexed requestId, uint256 value);
constructor(address coordinator, uint64 _subscriptionId, bytes32 _keyHash)
VRFConsumerBaseV2(coordinator)
{
COORDINATOR = VRFCoordinatorV2Interface(coordinator);
subscriptionId = _subscriptionId;
keyHash = _keyHash;
}
function requestRandomness() external returns (uint256) {
requestId = COORDINATOR.requestRandomWords(
keyHash,
subscriptionId,
3, // request confirmations
100000, // callback gas limit
1 // number of random words
);
emit RandomRequested(requestId, msg.sender);
return requestId;
}
function fulfillRandomWords(uint256 _requestId, uint256[] memory _randomWords)
internal
override
{
randomValue = _randomWords[0];
emit RandomFulfilled(_requestId, randomValue);
}
}
Những phần quan trọng là:
- Bước request: contract hỏi randomness từ một coordinator.
- Bước callback: oracle trả các random words về contract.
- Logic ứng dụng: contract sử dụng kết quả như một input đáng tin cậy cho trạng thái tiếp theo.
5. Hướng dẫn thực tế cho người xây dựng
Nếu bạn đang xây dựng một sản phẩm thật, lựa chọn phù hợp phụ thuộc vào use case:
- Game và các ứng dụng ít rủi ro: commit-reveal có thể đủ, dù yếu hơn các giải pháp hiện đại.
- Hệ thống có giá trị cao hoặc tương tác trực tiếp với người dùng: các giải pháp theo phong cách VRF thường là lựa chọn an toàn nhất.
- Hệ thống tổ chức hoặc permissioned: threshold signatures hoặc MPC có thể mang lại sự cân bằng đúng giữa niềm tin và kiểm soát.
- Infrastructure công khai: distributed randomness beacons hấp dẫn khi phi tập trung quan trọng hơn sự tiện lợi.
Bài học cốt lõi là không có nguồn randomness nào là “đúng” cho mọi trường hợp. Thiết kế tốt nhất phụ thuộc vào threat model, người dùng và mức độ tin cậy mà bạn sẵn sàng đặt vào lớp hạ tầng.
Kết luận
Randomness onchain vẫn là một trong những vấn đề khó nhất trong kỹ thuật blockchain vì nó nằm ở giao điểm của consensus, mật mã, kinh tế học và trải nghiệm người dùng. Các giải pháp được áp dụng rộng rãi nhất hiện nay không phải là những nguồn “ma thuật” tạo randomness; chúng là những hệ thống được thiết kế cẩn thận để biến tính không thể đoán trước, khả năng kiểm chứng và khả năng chống thiên vị thành những thứ có thể đo lường được.
Đối với hầu hết các đội, hướng đi tiếp theo không phải là invent một primitive randomness mới từ đầu, mà là chọn một cơ chế đã được chứng minh phù hợp với mô hình bảo mật và giới hạn vận hành của sản phẩm.