Chainlink VRF 深度解析與實戰

背景

在區塊鏈的去中心化應用中,隨機性是一個常見但難以實現的需求。例如,區塊鏈游戲需要隨機決定戰斗結果,NFT 項目需要隨機分配稀有屬性,去中心化抽獎需要公平選擇獲獎者。然而,傳統的鏈上隨機數生成方法(如使用 block.timestamp 或 blockhash)存在嚴重缺陷:這些值可被礦工或惡意節點預測和操縱,導致隨機性不可靠,容易引發不公平或安全問題。此外,鏈上生成隨機數的計算成本高,且無法提供可驗證的公平性。

為解決這些問題,Chainlink 推出了 VRF(Verifiable Random Function,可驗證隨機函數)。Chainlink VRF 通過鏈下生成隨機數并結合密碼學證明,確保隨機性既安全又可公開驗證,同時避免了鏈上隨機性生成的高成本和潛在攻擊風險。這使得 VRF 成為區塊鏈應用中實現公平、透明隨機性的標準解決方案。

什么是 Chainlink VRF?

Chainlink VRF(Verifiable Random Function,可驗證隨機函數)是一種為區塊鏈應用設計的可證明公平且防篡改的隨機數生成器。它通過密碼學手段確保隨機數的生成過程安全、可驗證且不可預測。Chainlink VRF 是區塊鏈游戲、NFT 鑄造、抽獎系統以及其他需要隨機邏輯的去中心化應用的理想選擇。

與傳統的偽隨機數生成器不同,這些方法容易受到礦工操縱,Chainlink VRF 提供了更安全、透明的隨機數解決方案,廣泛應用于區塊鏈網絡。

Chainlink VRF 的工作原理

Chainlink VRF 的核心是一個兩步流程:

  1. 請求隨機數:智能合約(稱為消費者合約)向 Chainlink VRF 協調器(Coordinator)發送請求,指定所需的隨機數數量和其他參數

  2. 履行隨機數請求:Chainlink 預言機在鏈下生成隨機數,并使用私鑰對其進行簽名。然后,預言機將隨機數和密碼學證明一起發送到消費者合約。合約使用預言機的公鑰驗證證明,確保隨機數未被篡改

核心組件

  • VRF 協調器:一個管理隨機數請求和響應的智能合約,充當消費者合約和 Chainlink 預言機之間的橋梁

  • 訂閱模型:在 VRF v2.5 中,用戶通過 LINK 代幣為訂閱賬戶充值,用于支付隨機數請求費用。每個訂閱都有一個唯一 ID

  • 證明驗證:Chainlink 預言機使用橢圓曲線密碼學生成證明,消費者合約在接受隨機數前會驗證此證明,確保隨機性來源可信

Chainlink VRF 的優勢

  1. 可驗證性:隨機數附帶密碼學證明,任何人都可以驗證其真實性

  2. 防篡改:鏈下生成隨機數避免了鏈上攻擊(如礦工操縱)

  3. 靈活性:支持多種區塊鏈網絡,并且可以請求多個隨機數

  4. 易于集成:Chainlink 提供了詳細的文檔和庫,開發者可以快速集成 VRF

典型用例

Chainlink VRF 的應用場景非常廣泛,以下是一些典型案例:

  • 區塊鏈游戲:為游戲中的隨機事件(如抽卡、戰斗結果)生成公平的隨機數

  • NFT 鑄造:隨機分配稀有屬性或決定 NFT 的生成順序

  • 去中心化抽獎:確保獲獎者選擇過程公平透明

  • 隨機分配:在去中心化金融(DeFi)或治理協議中隨機選擇參與者

集成 Chainlink VRF 的步驟

以下是如何在 Arbitrum Sepolia(或其他 EVM 兼容鏈)上集成 Chainlink VRF v2.5 的詳細步驟:

1. 前置條件

  • 安裝環境

    • 安裝 Hardhat 或 Foundry 用于開發和部署智能合約

    • 安裝 Chainlink 合約庫(通過 npm 或直接導入)

    • 或者前面的兩條都不用準備,直接使用 Remix

  • 準備 LINK 代幣:用于支付 VRF 請求費用

  • 創建訂閱(部署的時候我會給出詳細步驟圖解?

    1. 訪問 Chainlink VRF 訂閱頁面? ?https://vrf.chain.link/

    2. 創建一個訂閱賬戶并充值 LINK 代幣

    3. 記錄訂閱 ID

2. 編寫智能合約

以下官方展示如何使用 Chainlink VRF v2.5 生成隨機數,獲取家族名稱的案例:

// SPDX-License-Identifier: MIT
pragma solidity 0.8.19;import {VRFConsumerBaseV2Plus} from "@chainlink/contracts@1.4.0/src/v0.8/vrf/dev/VRFConsumerBaseV2Plus.sol";
import {VRFV2PlusClient} from "@chainlink/contracts@1.4.0/src/v0.8/vrf/dev/libraries/VRFV2PlusClient.sol";// 使用隨機數模擬擲20面骰子的Chainlink VRF消費者合約
contract VRFD20 is VRFConsumerBaseV2Plus {// 表示骰子正在擲的狀態uint256 private constant ROLL_IN_PROGRESS = 42;// 你的訂閱IDuint256 public s_subscriptionId;//  arbitrum-sepolia 網絡的VRF協調者地址address public vrfCoordinator = 0x5CE8D5A2BC84beb22a398CCA51996F7930313D61;// 使用的gas通道,指定最大gas價格bytes32 public s_keyHash =0x1770bdc7eec7771f7ba4ffd640f34260d7f095b79c92d34a5b2551d6f6cfd2be;// 回調函數的gas限制,存儲每個隨機數約需20000 gasuint32 public callbackGasLimit = 40000;// 請求確認數,默認為3uint16 public requestConfirmations = 3;// 請求的隨機數數量,最大不超過 VRFCoordinatorV2_5.MAX_NUM_WORDSuint32 public numWords = 1;// 映射:請求ID到擲骰者地址mapping(uint256 => address) private s_rollers;// 映射:擲骰者地址到VRF結果mapping(address => uint256) private s_results;// 事件:骰子已擲出event DiceRolled(uint256 indexed requestId, address indexed roller);// 事件:骰子結果已返回event DiceLanded(uint256 indexed requestId, uint256 indexed result);// 構造函數,繼承VRFConsumerBaseV2Plusconstructor(uint256 subscriptionId) VRFConsumerBaseV2Plus(vrfCoordinator) {s_subscriptionId = subscriptionId;}// 請求隨機數,模擬擲骰子function rollDice(address roller) public onlyOwner returns (uint256 requestId) {// 確保未擲過骰子require(s_results[roller] == 0, "Already rolled");// 請求隨機數requestId = s_vrfCoordinator.requestRandomWords(VRFV2PlusClient.RandomWordsRequest({keyHash: s_keyHash,subId: s_subscriptionId,requestConfirmations: requestConfirmations,callbackGasLimit: callbackGasLimit,numWords: numWords,extraArgs: VRFV2PlusClient._argsToBytes(VRFV2PlusClient.ExtraArgsV1({nativePayment: false}))}));s_rollers[requestId] = roller;s_results[roller] = ROLL_IN_PROGRESS;emit DiceRolled(requestId, roller);}// VRF協調者回調函數,返回隨機數function fulfillRandomWords(uint256 requestId,uint256[] calldata randomWords) internal override {// 計算20面骰子結果uint256 d20Value = (randomWords[0] % 20) + 1;s_results[s_rollers[requestId]] = d20Value;emit DiceLanded(requestId, d20Value);}// 獲取玩家的家族名稱function house(address player) public view returns (string memory) {// 確保已擲骰子require(s_results[player] != 0, "Dice not rolled");// 確保擲骰完成require(s_results[player] != ROLL_IN_PROGRESS, "Roll in progress");return _getHouseName(s_results[player]);}// 根據ID獲取家族名稱function _getHouseName(uint256 id) private pure returns (string memory) {string[20] memory houseNames = ["Targaryen","Lannister","Stark","Tyrell","Baratheon","Martell","Tully","Bolton","Greyjoy","Arryn","Frey","Mormont","Tarley","Dayne","Umber","Valeryon","Manderly","Clegane","Glover","Karstark"];return houseNames[id - 1];}
}
訪問 Chainlink VRF 訂閱頁面:

創建一個訂閱賬戶的第一步(點擊Create Subscription):交易請求

創建一個訂閱賬戶的最后一步(自動彈出):請求簽名

訂閱賬戶創建成功可以看到:

點擊進入你的訂閱賬戶:復制 Subscription ID,部署合約要用到

部署合約:填入?? Subscription ID

?

部署成功之后, 在你的訂閱賬戶添加一個消費者:復制你的合約地址,然后點擊?Add consumer ,確認交易請求

成功之后,添加 Link 代幣做為費用支出,(因為每次請求隨機數都要消耗 Link 代幣)? 點擊 Fund subscription 后確認交易:

做完之后,你會看到消費者界面:

我們來擲色子,請求一下隨機數:

?

OK,我們來驗證結果,可以看到已經獲取到了家族名稱,證明隨機數請求成功!

?

代碼說明

  • 合約繼承:合約繼承 VRFConsumerBaseV2Plus,這是 Chainlink 提供的基合約,用于處理 VRF 請求和回調

  • 構造函數:初始化 VRF 協調器地址和訂閱 ID

  • 請求隨機數:requestRandomNumber 函數向 VRF 協調器發送請求,指定 keyHash、訂閱 ID、gas 限制等參數

  • 接收隨機數:fulfillRandomWords 是回調函數,由 VRF 協調器調用,將生成的隨機數存儲在 randomWords 變量中

  • 參數說明

    • vrfCoordinator:VRF 協調器地址,需根據網絡選擇

    • keyHash:標識預言機的公鑰哈希,決定 gas 價格

    • callbackGasLimit:回調函數的最大 gas 消耗

    • requestConfirmations:等待的區塊確認數,確保隨機數的安全性

    • numWords:請求的隨機數數量

注意事項

  • 網絡選擇:確保 VRF 協調器地址和 keyHash 與目標網絡匹配

  • LINK 余額:訂閱賬戶需有足夠的 LINK 代幣支付費用

  • Gas 優化:根據回調邏輯的復雜性調整 callbackGasLimit,避免請求失敗

  • 安全考慮:限制 requestRandomNumber 的調用權限,防止未經授權的請求

?

實際案例:NFT 隨機屬性

以下是一個簡單的 NFT 合約,展示如何使用 Chainlink VRF 為 NFT 分配隨機屬性:

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;import {VRFConsumerBaseV2Plus} from "@chainlink/contracts@1.4.0/src/v0.8/vrf/dev/VRFConsumerBaseV2Plus.sol";
import {VRFV2PlusClient} from "@chainlink/contracts@1.4.0/src/v0.8/vrf/dev/libraries/VRFV2PlusClient.sol";
import {ERC721} from "@openzeppelin/contracts/token/ERC721/ERC721.sol";contract RandomNFT is ERC721, VRFConsumerBaseV2Plus {address vrfCoordinator = 0x5CE8D5A2BC84beb22a398CCA51996F7930313D61;uint256 s_subscriptionId;uint32 callbackGasLimit = 200000;uint16 requestConfirmations = 3;uint32 numWords = 1;bytes32 keyHash =0x1770bdc7eec7771f7ba4ffd640f34260d7f095b79c92d34a5b2551d6f6cfd2be;uint256 public tokenId;mapping(uint256 => uint256) public tokenToAttribute;constructor(uint256 subscriptionId) ERC721("RandomNFT", "RNFT") VRFConsumerBaseV2Plus(vrfCoordinator) {s_subscriptionId = subscriptionId;}function mintNFT() external {s_vrfCoordinator.requestRandomWords(VRFV2PlusClient.RandomWordsRequest({keyHash: keyHash,subId: s_subscriptionId,requestConfirmations: requestConfirmations,callbackGasLimit: callbackGasLimit,numWords: numWords,extraArgs: VRFV2PlusClient._argsToBytes(VRFV2PlusClient.ExtraArgsV1({nativePayment: false}))}));_safeMint(msg.sender, tokenId);tokenId++;}function fulfillRandomWords(uint256 /* requestId */,uint256[] calldata randomWords) internal override {uint256 attribute = randomWords[0] % 100; // 生成 0-99 的隨機屬性tokenToAttribute[tokenId - 1] = attribute;}
}

代碼說明

  • NFT 鑄造:用戶調用 mintNFT 函數鑄造 NFT 并觸發 VRF 請求

  • 隨機屬性:隨機數生成后,fulfillRandomWords 將其轉換為 0-99 的屬性值并存儲

  • 擴展性:可以根據需求調整隨機數的范圍或添加更多屬性

這里的合約我就不帶著大家去操作了, 我已經私下操作成功,留給大家自由發揮,步驟跟前面是一樣的,這里展示的是簡單版本的NFT,如果你的NFT是有元數據的,那就隨機元數據,利用好 requestId,使用基本是一樣的,請大家靈活使用

總結

Chainlink VRF 提供了一種安全、透明、可驗證的隨機數生成方案,為區塊鏈應用的公平性和可信度提供了強有力的支持。通過其訂閱模型和密碼學證明,開發者可以輕松集成隨機性,滿足游戲、NFT、抽獎等多種場景的需求。

截至 2025 年,Chainlink VRF 已在區塊鏈生態中取得了顯著成就。根據 Chainlink 官方數據,VRF 已處理超過 數百萬次隨機數請求,支持了數百個去中心化應用,涵蓋 NFT 項目、區塊鏈游戲和 DeFi 協議。這些應用利用 VRF 的公平性吸引了大量用戶,推動了區塊鏈生態的增長。例如,NFT 項目通過 VRF 實現的隨機屬性分配顯著提升了用戶信任和參與度。此外,Chainlink VRF 的多鏈支持使其成為跨鏈應用的首選隨機性解決方案,覆蓋以太坊、Arbitrum、Polygon、BNB Chain 等主流網絡。

Chainlink VRF 的影響不僅體現在技術層面,還推動了區塊鏈行業的標準化。它的可驗證性和防篡改特性為去中心化應用的公平性樹立了標桿,特別是在高價值的 NFT 和游戲領域。未來,隨著區塊鏈技術的進一步普及,Chainlink VRF 有望在更多領域(如元宇宙、去中心化治理、預測市場)發揮作用。Chainlink 團隊也在不斷優化 VRF 的性能,例如降低 gas 成本、支持更多鏈上場景,將進一步擴大其應用范圍和影響力。

官方文檔:???https://docs.chain.link/vrf/v2-5/getting-started

訂閱VRF:???https://vrf.chain.link/

水龍頭:???? ??https://faucets.chain.link/

代碼倉庫:???https://github.com/BraisedSix/chainlink-learn

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/web/83610.shtml
繁體地址,請注明出處:http://hk.pswp.cn/web/83610.shtml
英文地址,請注明出處:http://en.pswp.cn/web/83610.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

7. TypeScript接口

TypeScript 中的接口(Interfaces)用于定義對象的結構。它們允許開發者指定一個對象應具有哪些屬性以及這些屬性的類型。接口有助于確保對象遵循特定的結構,從而在整個應用中提供一致性,并提升代碼的可維護性。 一、認識接口 Typ…

UE 新版渲染器輸出視頻

安裝包解壓到C盤 打開UE插件 Movie Render Queue 進入UE引擎在項目設置找到 libx264 aac mp4 影片渲染隊列調用出 命令行編碼器安裝包路徑,序列輸出路徑,定序器不能有中文

基于用戶的協同過濾推薦算法實現(Java電商平臺)

在電商平臺中,基于用戶的協同過濾推薦算法是一種常見的推薦系統方法。它通過分析用戶之間的相似性來推薦商品。以下是一個簡單的實現思路和示例代碼,使用Java語言。 實現思路 數據準備:收集用戶的評分數據,通常以用戶-商品評分矩…

LeetCode - 904. 水果成籃

題目 904. 水果成籃 - 力扣(LeetCode) 思路 題目本質 你有一個整數數組,每個元素代表一種水果。你只能用兩個籃子,每個籃子只能裝一種水果。你要在數組中找一個最長的連續子數組,這個子數組里最多只包含兩種不同的…

發現 Kotlin MultiPlatform 的一點小變化

最近發現 Kotlin 官方已經開始首推 Idea 的社區版的 KMP 插件了. 以前有網頁創建 KMP 的項目的文檔也消失了. 雖然有 Android Studio 的選項. 但是卻不是在默認的位置上了. 足以說明官方是有意想讓大家直接使用 Idea 社區版或者專業版 所以我直接在社區版上安裝 KMP 插件. 嘗試…

【Photoshop】金屬字體制作

新建一個空白項目,選擇橫排文字工具,輸入想要的文件建立文字圖層 選擇橫排文字工具選擇出文字內容,在通知欄出點擊’拾色器‘,設置好需要的文字顏色 圖層面板右下角點擊‘添加圖層樣式’,選擇斜面和浮雕 樣式設置為內斜…

centos 7.9 升級ssh版本 7.4p1 升級到 8.2p1

centos 7.9 升級ssh版本 7.4p1 升級到 8.2p1 1、安裝包下載2、安裝telnet3、安裝openssl-OpenSSL_1_1_1f.tar.gz4、安裝openssh-8.2p1.tar.gz5、修改ssh服務的相關配置文件6、確定可以ssh連接服務器后,卸載telnet,因為telnet不安全 本文是離線環境下升級…

stm32---dma串口發送+fifo隊列框架

之前分享了一個關于gd32的fifo框架,這次就用stm32仿照寫一個,其實幾乎一樣,這次說的更詳細點,我全文都寫上了注釋,大家直接cv模仿我的調用方式即可 uasrt.c #include "stm32f10x.h" // D…

【生產就曲篇】讓應用可觀測:Actuator監控端點與日志最佳實踐

摘要 本文是《Spring Boot 實戰派》系列的終章,我們將探討如何讓應用真正達到**“生產就緒” (Production-Ready)** 的標準。文章的核心是可觀測性 (Observability),即從外部了解一個系統內部運行狀態的能力。 我們將深度挖掘 Spring Boot Actuator 的…

操作系統知識(1)

操作系統的分類總結 1、批處理操作系統:單道批處理和多道批處理(主機與外設可并行) 2、分時操作系統:一個計算機系統與多個終端設備連接。將CPU的工作時間劃分為許多很短的時間片,輪流為各個終端的用戶服務。 3、實時操作系統:實時是指計算機對于外來信息能夠以足…

一.Sharding分庫分表-基因法+自定義多key分片實現多字段查詢

前言 當下遇到這樣一個場景,由于訂單數據量達到千萬級別,采用分庫分表進行優化,根據訂單的熱查條件:order_no訂單編號進行分表,但是這樣帶來一個問題,用戶查詢自己的訂單怎么查?由于分片鍵使用…

【leetcode】543. 二叉樹的直徑

二叉樹的直徑 題目題解解釋 題目 543. 二叉樹的直徑 給你一棵二叉樹的根節點,返回該樹的 直徑 。 二叉樹的 直徑 是指樹中任意兩個節點之間最長路徑的 長度 。這條路徑可能經過也可能不經過根節點 root 。 兩節點之間路徑的 長度 由它們之間邊數表示。 題解 …

AI基礎知識(07):基于 PyTorch 的手寫體識別案例手冊

目錄 實驗介紹 實驗對象 實驗時間 實驗流程 實驗介紹 隨著人工智能技術的飛速發展,圖像識別技術在眾多領域得到了廣泛應用。手寫體識別作為圖像 識別的一個重要分支,其在教育、金融、醫療等領域具有廣泛的應用前景。本實驗旨在利用深度 學習框架 PyTorc…

wordpress后臺更新后 前端沒變化的解決方法

使用siteground主機的wordpress網站,會出現更新了網站內容和修改了php模板文件、js文件、css文件、圖片文件后,網站沒有變化的情況。 不熟悉siteground主機的新手,遇到這個問題,就很抓狂,明明是哪都沒操作錯誤&#x…

信號(瞬時)頻率求解與仿真實踐(2)

引言 本文是信號(瞬時)頻率求解與仿真實踐專題的第二篇文章,在上一篇博文 [1]信號(瞬時)頻率求解與仿真實踐(1)-CSDN博客中,我構建了信號瞬時頻率求解的基本框架,并且比較詳細地討論了瞬時頻率法。這篇博文探討適用于信號瞬時頻率求解的另一種…

Linux運行發布jar文件攜帶哪些參數

在 CentOS 8 上運行發布的 JAR 文件時,可以根據不同需求攜帶以下參數: 1. 基本運行方式 bash 復制 下載 java -jar your-application.jar 2. 常用 JVM 參數 參數說明-Xms256m初始堆內存大小(如 256MB)-Xmx1024m最大堆內存大小(如 1GB)-XX:MaxMetaspaceSize=256m元空間…

在GIS 工作流中實現數據處理(4)

結果輸出與可視化 最后,我們將統計結果輸出為一個 Excel 文件,并在 ArcMap 中對城市中心區域的土地利用情況進行可視化展示。 import pandas as pd# 將統計表格轉換為 pandas DataFrame df pd.read_csv(statistics_table, sep"\t")# 輸出為…

【術語解釋】網絡安全((SAST, DAST, SCA, IAST),Hadoop, Spark, Hive 的關系

## OWASP Top 10等 OWASP Top 10:OWASP (Open Worldwide Application Security Project,開放全球應用程序安全項目) Top 10 是一份由全球安全專家定期更新的報告,列出了當前 Web 應用程序面臨的十大最關鍵安全風險。 它是一個廣受認可的意識文…

NY197NY205美光閃存固態NY218NY226

NY197NY205美光閃存固態NY218NY226 美光科技作為全球領先的半導體存儲解決方案供應商,其閃存固態硬盤(SSD)產品線一直備受業界關注。NY197、NY205、NY218和NY226是美光近期推出的幾款重要固態硬盤型號,它們在性能、容量和適用場景…

MinHook 對.NET底層的 SendMessage 攔截真實案例反思

一:背景 1. 講故事 上一篇我們說到了 minhook 的一個簡單使用,這一篇給大家分享一個 minhook 在 dump 分析中的實戰,先看下面的線程棧。 0:044> ~~[138c]s win32u!NtUserMessageCall0x14: 00007ffc5c891184 c3 ret 0:061&g…