如何在Substrate基准测试中注册密钥库扩展或生成密钥对?
解决方案:在Pallet基准测试中生成密钥对
方法一:无需密钥库的确定性密钥对生成
如果不需要动态生成密钥对,使用固定种子创建密钥对是最简单的方案,无需依赖密钥库或std环境。
步骤
- 确保依赖特性开启:在
Cargo.toml中,为runtime-benchmarking特性添加sp-core/full-crypto支持:
[features] runtime-benchmarking = [ "frame-benchmarking/runtime-benchmarking", "sp-core/full-crypto", "sp-runtime/runtime-benchmarking", # 其他你的pallet所需的基准测试依赖 ]
- 在基准测试中生成密钥对:使用
Pair::from_seed方法从固定种子创建密钥对:
// 你的pallet基准测试代码中 use sp_core::sr25519::Pair; use sp_runtime::traits::IdentifyAccount; benchmark! { name: TransferWithPreGeneratedKey; setup: { // 使用固定32字节种子生成密钥对 let seed = [0x2a; 32]; let pair = Pair::from_seed(&seed); let sender = pair.public().into_account(); // 为测试账户充值(如果需要) frame_system::Pallet::<T>::set_balance(&sender, 1_000_000_000_000); let recipient = <T::AccountId as Default>::default(); }; execute: { // 在基准测试逻辑中使用生成的账户 Pallet::<T>::transfer(Origin::signed(sender), recipient, 1000)?; }; }
- 生成多组唯一密钥对:如果需要多个不同账户,可以通过递增种子值实现:
// 生成第n个唯一密钥对 let seed = [n as u8; 32]; let pair = Pair::from_seed(&seed);
方法二:在基准测试外部环境中注入测试密钥库
如果必须使用RuntimeAppPublic::generate_pair方法,可以通过自定义外部环境注册内存密钥库。
步骤
- 自定义基准测试外部环境:在runtime的
benchmarking.rs中创建包含密钥库的外部环境:
use sp_keystore::{Keystore, KeystorePtr, KeystoreExt}; use frame_benchmarking::BenchmarkingSetup; use sp_externalities::ExternalitiesExt; pub struct RuntimeBenchmarkSetup; impl BenchmarkingSetup<Runtime> for RuntimeBenchmarkSetup { fn setup() -> sp_externalities::TestExternalities { let mut ext = frame_system::GenesisConfig::default().build_storage::<Runtime>().unwrap(); // 创建内存密钥库 let keystore = Keystore::in_memory(); let keystore_ptr = KeystorePtr::new(keystore); // 注册密钥库扩展到外部环境 ext.register_extension(KeystoreExt(keystore_ptr)); sp_externalities::TestExternalities::new(ext) } }
- 在基准测试中使用密钥库生成密钥对:
// 你的pallet基准测试代码中 use sp_keystore::KeystoreExt; use sp_runtime::traits::RuntimeAppPublic; benchmark! { name: DynamicKeyPairGeneration; setup: { // 从外部环境中获取密钥库 let keystore = sp_externalities::with_context(|ext| { ext.get::<KeystoreExt>().unwrap().clone() }); // 使用密钥库生成新密钥对 let (public_key, _) = <T::AccountId as sp_runtime::traits::AccountId>::Public::generate_pair(Some(&*keystore)); let account_id = public_key.into_account(); }; execute: { // 使用生成的账户执行基准测试逻辑 Pallet::<T>::protected_call(Origin::signed(account_id), args)?; }; }
注意事项
- 确定性密钥对方案更适合基准测试,因为它能保证每次运行的输入一致,便于性能对比。
- 内存密钥库仅在基准测试过程中存在,不会持久化任何数据。
内容的提问来源于stack exchange,提问作者Ju Piece
相关产品推荐
相关产品推荐

