如何在Solana链上程序中获取随机数?

Dav*_*saw 5 random contract blockchain smartcontracts solana

我刚刚加入 Solana 链上计划。我要做一个判断正面或背面的硬币游戏。我尝试使用 std:: rand 和 get_random 板条箱,但它们不起作用。如果您有这方面的经验,请告诉我。

我使用 Solana 链上程序的锚点。

Set*_*max 12

不幸的是,随机生成器无法在链上运行。如果你想要一些随机数,你应该从链外获取。

为什么?

假设您使用块哈希或类似的东西进行随机,因此用户可以通过插入指令或值来检查有利的结果,甚至更糟糕的是,如果不令人满意,则强制回滚。

那么我们应该做什么呢?

  1. 尝试使用像Chainlink VRF(可验证随机函数)这样的预言机

  2. 模拟oracle vrf服务:

使交易在您的服务器监听的链上进行。如果发生此交易,请在链外生成随机数并从您的服务器回调它。

锚点像这样使用随机数

use rand::rngs::OsRng;
.
.
.
let dummy_a = Keypair::generate(&mut OsRng);
Run Code Online (Sandbox Code Playgroud)

因此,如果您需要类似 UUID 的行为的随机性,您可以使用锚代码存储库中的上述机制,但如果您的情况是像掷骰子这样的游戏逻辑,则需要预言机或模拟它。

更新 11/10/2022

众所周知,Metaplex 糖果机床使用随机数来选择下一个要铸造的物品。

看这个代码片段:

// (2) selecting an item to mint

let recent_slothashes = &ctx.accounts.recent_slothashes;
let data = recent_slothashes.data.borrow();
let most_recent = array_ref![data, 12, 8];

let clock = Clock::get()?;
// seed for the random number is a combination of the slot_hash - timestamp
let seed = u64::from_le_bytes(*most_recent).saturating_sub(clock.unix_timestamp as u64);

let remainder: usize = seed
    .checked_rem(candy_machine.data.items_available - candy_machine.items_redeemed)
    .ok_or(CandyError::NumericalOverflowError)? as usize;

let config_line = get_config_line(candy_machine, remainder, candy_machine.items_redeemed)?;

candy_machine.items_redeemed = candy_machine
    .items_redeemed
    .checked_add(1)
    .ok_or(CandyError::NumericalOverflowError)?;
Run Code Online (Sandbox Code Playgroud)

这个想法是您可以从 Solana 网络获取区块哈希和时钟作为随机输入种子来创建下一个随机数。

另一个代码片段将是开始创建随机数的好点:

//convert blockhash to random seed string
let recent_blockhash_data = recent_blockhashes.data.borrow();
let most_recent = array_ref![recent_blockhash_data, 0, 16];
let some_numbers = u128::from_le_bytes(*most_recent);
let blockhash_random_seed: String = (some_numbers).to_string();
Run Code Online (Sandbox Code Playgroud)

在上面的代码中,我们使用最近的块哈希并将其转换为十六进制(作为字符串)。您可以选择该十六进制哈希字符串的每个部分并将其用作随机值。

最后,重要的是要知道 blockhash 现在已被弃用,Metaplex 使用 slothash,但如果你仔细观察,你会发现他们仍然使用 blockhash,只是使用变量的名称作为 slothash。

干杯