You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Substrate no_std环境下引入rand包WeightedIndex、StdRng报错如何解决?

问题原因
  • rand 包在关闭默认特性(default-features = false)的情况下,WeightedIndex 所属的加权分布功能需要额外启用weighted特性才能导入;同时WeightedIndex内部需要动态内存分配,依赖alloc特性,no_std环境下默认不开启该特性。
  • StdRng 是依赖系统熵源的随机数生成器,本身不支持no_std环境。Substrate Runtime是WASM的no_std环境,没有系统级熵源接口,因此无法导入和使用StdRng。
解决方案

第一步 调整Cargo.toml依赖配置

修改rand的依赖声明,补充需要的特性:

[dependencies]
rand = { version = "0.8.4", default-features = false, features = ["alloc", "weighted", "small_rng"] }

同时在pallet的std特性配置中,补充rand的std特性适配native编译:

[features]
default = ["std"]
std = [
    "rand/std",
    # 保留原有其他依赖的std配置
]

第二步 替换不兼容的随机数生成器

将StdRng替换为纯算法实现、no_std兼容的SmallRng,修改导入和实例化代码:

use rand::distributions::WeightedIndex;
use rand::prelude::*;
use rand::{rngs::SmallRng, SeedableRng};

fn draw_juror_for_citizen_profile_function(
    citizen_id: u128,
    length: usize,
) -> DispatchResult {
    let nonce = Self::get_and_increment_nonce();
    let random_seed = T::RandomnessSource::random(&nonce).encode();
    let random_number = u64::decode(&mut random_seed.as_ref())
        .expect("secure hashes should always be bigger than u32; qed");
    // 替换为SmallRng
    let mut rng: SmallRng = SeedableRng::seed_from_u64(random_number);
    
    // 后续即可正常使用WeightedIndex,示例:
    // let weights = vec![1, 2, 3];
    // let dist = WeightedIndex::new(&weights).unwrap();
    // let selected_index = dist.sample(&mut rng);

    Ok(())
}

fn get_and_increment_nonce() -> Vec<u8> {
    let nonce = <Nonce<T>>::get();
    <Nonce<T>>::put(nonce.wrapping_add(1));
    nonce.encode()
}

注意事项

  • Substrate Runtime默认启用alloc,因此rand开启alloc特性不会和no_std环境冲突。
  • 如果需要更高安全性的随机数生成器,可以选择引入rand_chacha依赖,使用ChaCha20Rng替代SmallRng,该实现同样支持no_std环境。

内容的提问来源于stack exchange,提问作者Amiya Behera

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.26 19:45:04