Substrate中chain_specs.rs的Alice开发密钥如何添加到本地密钥库?
Substrate开发模式下密钥自动注入本地密钥库的实现逻辑
1. 创世配置阶段的密钥生成逻辑
你在chain_spec.rs中看到的authority_keys_from_seed("Alice")函数,作用是根据传入的种子派生当前Runtime中Session pallet注册的所有类型会话密钥的公钥,包括Aura、Grandpa、ImOnline等所有已声明的应用密钥类型,这些公钥最终会被写入创世存储的Session模块Keys项中,属于链上全局共识的初始权威配置,这一步并不会操作本地密钥库。
pub fn development_config() -> Result<ChainSpec, String> { let wasm_binary = WASM_BINARY.ok_or_else(|| "Development wasm binary not available".to_string())?; Ok(ChainSpec::from_genesis( // Name "Development", // ID "dev", ChainType::Development, move || { testnet_genesis( wasm_binary, // Initial PoA authorities vec![authority_keys_from_seed("Alice")], // Sudo account get_account_id_from_seed::<sr25519::Public>("Alice"), // Pre-funded accounts vec![ get_account_id_from_seed::<sr25519::Public>("Alice"), get_account_id_from_seed::<sr25519::Public>("Bob"), get_account_id_from_seed::<sr25519::Public>("Alice//stash"), get_account_id_from_seed::<sr25519::Public>("Bob//stash"), ], true, ) }, // Bootnodes vec![], // Telemetry None, // Protocol ID None, // Properties None, // Extensions None, )) }
2. 开发模式自动注入本地密钥的核心逻辑
本地密钥库的密钥注入是节点启动阶段的行为,当你使用--dev参数启动节点时,Substrate的CLI框架会识别到当前链规范的类型为ChainType::Development,会自动触发内置的测试密钥预注入逻辑:
- 自动将Alice、Bob等通用测试账号的种子,派生所有应用类型的密钥对,插入到本地密钥库(内存密钥库或dev模式专属的文件密钥库)
- 这个逻辑是Substrate CLI为了简化开发测试内置的,不需要额外编码配置,只要是开发链类型就会默认执行
3. Pallet中读取本地密钥的逻辑
你在im-online pallet中看到的T::AuthorityId::all()方法,是Substrate应用密钥trait AppCrypto的标准实现,它会直接从当前节点的密钥存储中,读取对应应用类型(此处为ImOnline的专属密钥类型ID)的所有公钥,因为开发模式启动时已经把Alice的ImOnline密钥对注入到本地密钥库,所以查询时可以直接获取到对应记录。
fn local_authority_keys() -> impl Iterator<Item=(u32, T::AuthorityId)> { // on-chain storage // // At index `idx`: // 1. A (ImOnline) public key to be used by a validator at index `idx` to send im-online // heartbeats. let authorities = Keys::<T>::get(); // local keystore // // All `ImOnline` public (+private) keys currently in the local keystore. let mut local_keys = T::AuthorityId::all(); local_keys.sort(); authorities.into_iter() .enumerate() .filter_map(move |(index, authority)| { local_keys.binary_search(&authority) .ok() .map(|location| (index as u32, local_keys[location].clone())) }) }
4. 自定义自动注入密钥的实现方法
如果你要为自定义的密钥类型实现类似的自动注入能力,可以直接修改节点启动的初始化逻辑:
在CLI的节点启动分支中,判断当前为开发/测试模式时,主动调用密钥库的插入接口写入预设测试密钥,示例代码如下:
// 示例:插入自定义应用类型的测试密钥到本地密钥库 // 自定义密钥类型的ID,需和Runtime中声明的应用ID一致 const MY_KEY_TYPE: sp_application_crypto::KeyTypeId = sp_application_crypto::KeyTypeId(*b"mykt"); // 节点初始化阶段执行 let keystore = node.keystore(); // 传入密钥类型ID、测试种子、对应公钥即可完成插入 keystore.insert( MY_KEY_TYPE, "Alice", // 测试种子 &my_custom_key::Public::from_seed(&[0;32]).as_ref() ).expect("Insert test key failed");
内容的提问来源于stack exchange,提问作者Jdawg287
相关产品推荐
相关产品推荐

