fuels-rs 如何锁定已解锁钱包的签名器并区分 Wallet<Locked> 可用的操作边界
fuels-rs 如何锁定已解锁钱包的签名器并区分 Wallet 可用的操作边界【免费下载链接】fuels-rsFuel Network Rust SDK项目地址: https://gitcode.com/GitHub_Trending/fu/fuels-rs在 fuels-rs 中一个持有签名器signer的Wallet实例既能查询链上状态也能签名消息和交易。当签名任务执行完毕你希望把私钥从内存中移出只保留“查余额、列币、看交易”这类只读能力。fuels-rs 用两个类型把这个边界固化在编译期WalletUnlockedS表示附带签名器的钱包WalletLocked表示只知道自己地址、无法签名的钱包。本文的目标是把一个已解锁的钱包通过lock方法转换或直接用地址构造为WalletLocked并弄清转换前后各自可用哪些操作。两种钱包状态及设计意图WalletUnlockedS与WalletLocked的区别见 access.mdWalletUnlockedS代表附带签名器的钱包。凡是涉及签名消息或交易的操作钱包必须是这个类型。WalletLocked代表没有签名器的钱包它只知道自己的公开地址public address。WalletLocked不能用于签名交易但仍可执行一系列有用的操作包括列出交易、列出资产、查询余额等。官方给出的设计准则是API 开发者应尽量减少使用WalletUnlockedS的范围确保签名器在内存中停留的时间不超过必要以缩小下游库和应用被攻击或出漏洞的面。也就是说lock不是“临时禁用”而是把签名能力从类型上拿掉。从源码 wallet.rs 可以看到实现逻辑Wallet内部由state泛型参数S与provider组成。lock的实现是pub fn lock(self) - WalletLocked { Wallet::new_locked(self.state.signer.address(), self.provider.clone()) }签名器本身没有参与转换——只取出了它的地址provider被克隆到新钱包。注意lock不会销毁原WalletUnlockedS原变量仍是解锁状态只有让原变量离开作用域或显式丢弃签名器才真正不再被持有。从解锁钱包转到 Wallet转换方法就是文档中给出的lock来源 access.md 的 Transitioning States 一节let wallet_locked wallet_unlocked.lock();约束是wallet_unlocked必须实现S: Signer即类型为WalletUnlockedS。转换后wallet_locked的静态类型是WalletLocked从这一刻起它不再有signer()访问器signer()只在 wallet.rs 的WalletUnlockedS实现中定义。如果场景是“我只有某个地址从未在本进程持有过签名器”可以跳过lock直接用地址构造WalletLocked。e2e 测试 test_wallet_get_coins 展示了这条路径let addr Address::zeroed(); let coins setup_single_asset_coins(addr, AssetId::zeroed(), NUM_COINS, AMOUNT); let provider setup_test_provider(coins, vec![], None, None).await?; let wallet Wallet::new_locked(addr, provider.clone());Wallet::new_locked(addr, provider)同样来自 wallet.rs。两条路径产出的对象类型一致操作边界完全相同。Wallet 可用的操作边界边界由 trait 实现决定。在 wallet.rs 中WalletLocked只实现了ViewOnlyAccount见 locked 模块提供address()、try_provider()以及经由get_spendable_resources组装输入的能力。ViewOnlyAccount是查询余额的通用接口见 accounts.md。WalletUnlockedS同时实现ViewOnlyAccount和Account额外提供add_witnesses这是交易构建时挂签名器的入口。转账类方法transfer、force_transfer_to_contract、withdraw_to_base_layer属于Accounttrait见 accounts.md 的 Transferring assets 一节。对照 index.md 的钱包分类说明可以归纳成下表操作WalletUnlockedWalletaddress()/try_provider()支持支持查询余额get_asset_balance、get_balances见 checking-balances-and-coins.md支持支持列出币get_coins支持支持transfer、force_transfer_to_contract、withdraw_to_base_layer支持不可用类型上不存在签名消息 / 为交易构建器添加签名器支持不可用类型上不存在对开发者来说这意味着边界不是靠运行时报错而是靠编译期拒绝在WalletLocked上调transfer或signer()会直接编译失败。这正是 access 文档中“minimise their usage ofWalletUnlockedS”建议能落地的原因。完整路径与验证方式下面是一段把三种状态串起来的代码骨架示例值取自 examples/wallets/src/lib.rs 中create_wallet_from_mnemonic与 e2e 测试test_wallet_get_coinsuse fuels::prelude::*; // 1. 构造解锁钱包含签名器 let provider setup_test_provider(vec![], vec![], None, None).await?; let phrase oblige salon price punch saddle immune slogan rare snap desert retire surprise; let key SecretKey::new_from_mnemonic_phrase_with_path( phrase, fuels::accounts::signers::derivation::DEFAULT_DERIVATION_PATH, )?; let wallet_unlocked Wallet::new(PrivateKeySigner::new(key), provider.clone()); // 2. 锁定签名器从状态中移除只保留地址与克隆的 provider let wallet_locked: WalletLocked wallet_unlocked.lock(); // 3. 只读操作在锁定钱包上可用 let asset_id AssetId::zeroed(); let balance: u128 wallet_locked.get_asset_balance(asset_id).await?; let coins wallet_locked.get_coins(asset_id).await?; // 4. 地址一致锁定的钱包与解锁钱包指向同一账户 assert_eq!(wallet_locked.address(), wallet_unlocked.address());setup_test_provider是 fuels-test-helpers 提供的测试 provider 构造器上面的代码放在#[tokio::test]中运行在连接真实节点的场景下用你自己的 provider 替换这一行即可。验证方式有三层编译期验证在wallet_locked上尝试调用transfer或signer()预期编译失败。能编译通过的代码才是合法的只读路径。地址一致性如上例lock只从签名器提取地址wallet_locked.address()应等于原解锁钱包的地址。只读查询可执行e2e 测试 test_wallet_get_coins 用Wallet::new_locked构造的钱包调用了get_coins并断言返回的 coin 数量与总额证明WalletLocked的查询路径可用。该测试中的具体数值NUM_COINS 3、AMOUNT 1000是测试自身的设定值作为文档示例理解即可不是通用预期值。边界与限制lock与new_locked都不涉及私钥的销毁或存储管理WalletLocked只持有地址。如果你还需要“把私钥加密存盘、之后凭主密码取回”那是另一条路径——Keystore::save_key/Keystore::load_key见 keystore.md 与 examples/wallets/src/lib.rs 的create_and_store_mnemonic_key与本文的运行时锁定相互独立。锁定后的钱包无法再恢复为解锁状态WalletLocked没有对应的unlock方法重建WalletUnlockedS需要重新提供签名器私钥、助记词或 KMS。签名器种类PrivateKeySigner、AWS/Google KMS、Fake Signer见 index.md只影响解锁钱包的构造方式lock之后两者行为一致因为签名器信息已不可达。【免费下载链接】fuels-rsFuel Network Rust SDK项目地址: https://gitcode.com/GitHub_Trending/fu/fuels-rs创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考