為了滿足智能合約對隨機性的需求,去中心化偽隨機數生成器是一種常用的方法。

原文:A Guide to Using ANU's Quantum Random Number Generator in Your Smart Contracts

作者:Vansh Wassan

原用標題(譯後)指南:在智能合約中使用 ANU 的量子隨機數生成器

編譯: ChinaDeFi

隨機數生成器 (RNG) 一直是使用智能合約時最大的問題之一。確定性虛擬機無法產生 “真正的” 隨機性。

為了滿足智能合約對隨機性的需求,去中心化偽隨機數生成器是一種常用的方法。最常用的方法之一是 Chainlink 的 VRF 或可驗證隨機函數,它在鏈上提供密碼可證明的隨機數。它生成一個鏈下隨機數和用於驗證結果的加密證明。

然而,這種配置與其他第三方預言機網絡存在相同的問題。設置一個可以提供 PRNG 的預言機節點會暴露潛在的攻擊載體,比如女巫攻擊,也缺乏源透明性和去中心化。例如,需要信任治理實體來選擇網絡參與者,這意味著去中心化的 PRNG 只與治理實體一樣安全和去中心化。

量子隨機數生成

QRNG 通過量子現象產生隨機性。它使用一個 “真正的” 熵源,利用量子物理的獨特特性來產生真正的隨機性。

實現 QRNG 的方法各不相同,但共同點是得到的數字將是真正隨機的,因為量子事件的結果在理論上是不確定的。因此,QRNG 是隨機數生成的黃金標準。

澳大利亞國立大學的 QRNG Airnode

正如我們已經討論過的,通過第三方預言機網絡提供 RNG 會為攻擊載體打開大門。但是由 QRNG API 提供商直接運營的第一方預言機 (airnode) 會以最佳方式應對女巫攻擊風險。

API3 QRNG 是澳大利亞國立大學 (ANU) 提供的公共實用程序。它由 ANU 量子隨機數託管的 Airnode 提供動力,這也意味著它是第一方服務。澳大利亞國立大學的量子光學部是該領域世界領先的研究機構之一。該部門還運行一個 REST API,即量子隨機數 API,以服務於 Web2 中的 QRNG。

它作為一種公共產品,所以也是免費的 (除了 gas 成本),當需要鏈上 RNG 時,它通過一個易於使用的解決方案提供了 “真正的” 量子隨機性。

Airnode 和 API3 QRNG 是如何工作的?

https://docs.api3.org/qrng/introduction/how-works.html

首先,我們需要使用能夠匹配上的讚助者錢包進行部署並贊助 QrngRequester。QrngRequester 將是檢索隨機數的主合約。

QrngRequester 向 AirnodeRrpV0 提交一個隨機數請求。Airnode 從 AirnodeRrpV0 協議合約中收集請求,從鏈下檢索隨機數,並將其發送回 AirnodeRrpV0。一旦接收到,它將使用隨機數執行回調到請求程序。

編碼 QrngRequester.sol

開始

請確保已安裝以下軟件:

  • Node.js
  • yarn/NPM

另外,請確保已經克隆並安裝了 Airnode Monorepo。如果還沒有,用以下命令克隆 Airnode Monorepo:

$ git clone https://github.com/api3dao/airnode.git 

要安裝依賴項,請執行以下步驟:

$ yarn run bootstrap

要構建所有的包,使用這個命令:

$ yarn run build

編制合約

為了編譯 QrngRequester 合約,我們將使用 Remix IDE。它是一個在線 IDE,可以為與 EVM 兼容的區塊鏈開發、部署和管理智能合約。

//SPDX-License-Identifier: MITpragma solidity 0.8.9;import "@api3/airnode-protocol/contracts/rrp/requesters/RrpRequesterV0.sol";
contract RemixQrngExample is RrpRequesterV0 { event RequestedUint256(bytes32 indexed requestId); event ReceivedUint256(bytes32 indexed requestId, uint256 response);
address public airnode; bytes32 public endpointIdUint256; address public sponsorWallet; mapping(bytes32 => bool) public waitingFulfillment;
// These are for Remix demonstration purposes, their use is not practical. struct LatestRequest { bytes32 requestId; uint256 randomNumber; } LatestRequest public latestRequest;
constructor(address _airnodeRrp) RrpRequesterV0(_airnodeRrp) {}
// Normally, this function should be protected, as in: // require(msg.sender == owner, "Sender not owner"); function setRequestParameters( address _airnode, bytes32 _endpointIdUint256, address _sponsorWallet) external { airnode = _airnode; endpointIdUint256 = _endpointIdUint256; sponsorWallet = _sponsorWallet; }
function makeRequestUint256() external { bytes32 requestId = airnodeRrp.makeFullRequest( airnode, endpointIdUint256, address(this), sponsorWallet, address(this), this.fulfillUint256.selector, "" ); waitingFulfillment[requestId] = true; latestRequest.requestId = requestId; latestRequest.randomNumber = 0; emit RequestedUint256(requestId); }
function fulfillUint256(bytes32 requestId, bytes calldata data) external onlyAirnodeRrp{ require( waitingFulfillment[requestId], "Request ID not known" ); waitingFulfillment[requestId] = false; uint256 qrngUint256 = abi.decode(data, (uint256)); // Do what you want with `qrngUint256` here... latestRequest.randomNumber = qrngUint256; emit ReceivedUint256(requestId, qrngUint256); }}

QrngRequester 有三個主要函數:setRequestParameters(), makeRequestUint256() 和 fulfillUint256()。

  • setRequestParameters() 函數接受 airnode、endpointIdUint256、sponsorWallet 並設置這些參數。
  • makeRequestUint256() 函數調用協議合約的 airnodeRrp.makeFullRequest() 函數,該函數將請求添加到其存儲中並返回一個 requestId。
  • 目標鏈下 ANU Airnode 收集請求並使用隨機數向請求者執行回調。

請求參數

makeRequestUint256() 函數需要以下參數發出有效請求。

  • airnode (地址) 和 endpointiduint256 指定端點。
  • sponsorWallet 指定將使用哪個錢包來完成請求。

響應參數

對 QrngRequester 的回調包含兩個參數:

  • requestId:在發出請求時會被首次獲取,並在這裡作為參考傳遞,以識別響應所針對的請求。
  • data:在成功響應的情況下,這是已被編碼的請求數據,除了其他響應數據外,還包含時間戳。使用 abi 對像中的 Decode() 函數對其進行解碼,以獲得隨機數。

轉到 Remix IDE,創建一個合約,並將其粘貼到 QrngRequester 代碼中。

現在,點擊儀表板右側的 compile 並編譯智能合約。

部署合約

我們將把我們的 QrngRequester 部署到 Goerli。確保錢包中有足夠的測試網 ETH 來部署合約,並在以後資助 sponsorWallet。

轉到部署,運行交易,並在環境下選擇 “Injected Provider — MetaMask” 選項。連接 MetaMask。確保是在 Goerli。

_rrpaddress 是主 airnodeRrpAddress。RRP 合約已經部署在鏈上。

填充_rrpAddress 之後,單擊 “Deploy”。確認 MetaMask 上的交易,並等待它部署 Requester 合約。

確保是在 Goerli。

調用合約

當 QrngRequester 部署完成後,轉到 Deploy,運行交易,然後單擊已部署合約下的請求者並下拉列表。

現在選擇 setRequestParameters 並下拉菜單來設置所有的參數。

將以下內容添加到函數的相應字段中。

  • _airnode:所需 QRNG 服務提供者的 airnode 地址。從 ANU Airnode 查看它的值。
  • _endpointIdUint256: Airnode 端點 ID 將返回一個隨機數。從 ANU Airnode 查看它的值。
  • _sponsorWallet:一個由請求者合約地址、Airnode 地址和 Airnode xpub 派生的錢包。這個錢包用來支付 gas 費用,以獲得一個隨機數。贊助者錢包必須使用命令 derived -sponsor-wallet-address 從 Admin CLI 中派生。使用命令輸出的讚助者錢包地址的值。

在設置好 Airnode CLI,安裝並構建所有依賴項和包之後,運行以下命令來派生自己的_sponsorWallet。

Linux

npx @api3/airnode-admin derive-sponsor-wallet-address \  --airnode-xpub xpub6CUGRUo... \  --airnode-address 0xe1...dF05s \
  --sponsor-address 0xF4...dDyu9

Windows

npx @api3/airnode-admin derive-sponsor-wallet-address ^  --airnode-xpub xpub6CUGRUo... ^  --airnode-address 0xe1...dF05s ^
--sponsor-address 0xF4...dDyu9

用一些測試網 ETH 資助 sponsorWallet。單擊交易按鈕並確認交易以設置參數。

發出請求,單擊 makeRequestUint256 按鈕調用函數,並發出完整的請求。

現在可以前往並檢查自己的新交易了。https://goerli.etherscan.io/sponsorWallet`

可能需要等待一段時間,因為 Airnode 調用 AirnodeRrpV0.sol 中的 fulfill() 函數,它將使用函數 fulfillment functionid 在 fulfillAddress 處回調請求者合約來傳遞數據 (隨機數)。

在這裡,我們可以看到最新的 fulfillment 交易。

現在回到 Remix 並點擊 latestRequest 按鈕檢查響應。

如果回調已經成功完成,randomNumber 將會出現。waitingFulfillment 的值將為假。

免責聲明:作為區塊鏈信息平台,本站所發布文章僅代表作者及嘉賓個人觀點,與 Web3Caff 立場無關。文章內的信息僅供參考,均不構成任何投資建議及要約,並請您遵守所在國家或地區的相關法律法規。