Logo
新用户订阅 RPC,首月享 6.5 折优惠查看优惠
OnFinality Learn
基础设施与运维阅读约 11 分钟

非托管钱包加密货币:密钥管理、RPC 依赖与验证工作流

一份技术指南,说明非托管钱包如何持有密钥、签名交易并依赖 RPC 基础设施,并提供可复现的余额、nonce 和签名行为检查。

TL;DR

非托管钱包是一种在本地生成并存储私钥、在用户设备上签名交易,并通过 RPC 端点广播已签名载荷的软件或硬件。钱包从不将密钥托管委托给服务器,但仍依赖远程基础设施获取链数据、nonce 状态、费用估算和交易传播。本文解释密钥管理模型,展示如何验证钱包是否真正非托管,并提供可运行流程,用于针对您控制的 RPC 端点检查余额、nonce 和本地签名。

直接答案与范围

非托管钱包是一种加密货币钱包,其中私钥在用户控制的基础设施上生成和存储,通常是移动设备、浏览器扩展或硬件设备。钱包在本地签名交易,仅将已签名载荷提交到网络。没有公司持有密钥材料,因此没有公司能够代表用户移动、冻结或恢复资金。

本文涵盖在构建、集成或审计非托管钱包流程时重要的技术机制:密钥派生、本地签名、RPC 依赖和验证程序。它不对钱包品牌进行排名。如果您需要针对特定链的具体 RPC 端点推荐,请使用 RPC Assistant,而不是将本页视为提供商列表。

  • 范围内:密钥托管模型、签名流程、钱包发起的 RPC 调用、可复现检查。
  • 范围外:品牌比较、代币价格评论以及关于自托管的 legal 建议。
  • 假设:您拥有钱包地址、可访问 RPC 端点以及基本命令行工具。

托管与非托管托管模型

分界线在于谁控制私钥。在托管模型中,交易所或应用持有密钥并代表您签名;在您提取到链上之前,您的余额是该提供商账本中的一项记录。在非托管模型中,密钥仅存在于您的设备或硬件模块上,提供商永远看不到它。

这种差异具有运营后果。托管提供商可以重置您的密码、冻结提款或在平台故障中损失资金。非托管钱包无法做任何这些事情,但如果您丢失恢复短语,它也无法恢复访问。权衡是便利性和支持台与备份的sole责任。

  • 托管:提供商持有密钥、签名交易并控制提款时间。
  • 非托管:用户持有密钥、本地签名并控制备份和恢复。
  • 混合:MPC 或智能账户钱包分割签名权限,但密钥材料仍不完全由平台持有。

非托管钱包如何派生和存储密钥

大多数非托管钱包遵循确定性层级。恢复短语(通常为 12 或 24 个单词)编码一个种子。钱包从该种子派生主密钥,然后沿派生路径派生每个账户的密钥。对于 EVM 链,常见路径是 m/44'/60'/0'/0/0;比特币和 Solana 使用不同的币种类型和路径约定。

私钥永远不会离开签名环境。在软件钱包中,它在设备上静态加密,仅在签名时解密。在硬件钱包中,它留在安全元件内,主机在物理确认后发送未签名载荷供设备签名。恢复短语是种子的备份,不是密码,任何获得它的人都可以重建每个派生密钥。

  • 种子短语 → 主密钥 → 派生路径 → 账户私钥 → 公共地址。
  • 软件钱包在本地加密密钥;硬件钱包将密钥隔离在安全芯片中。
  • 恢复短语等同于所有派生私钥,绝不能输入网站。

钱包要求 RPC 端点做什么

非托管钱包不是节点。它通过 RPC 端点读取链状态并广播交易。端点看到您的公共地址和已签名交易,但永远看不到您的私钥。这种分离使得远程 RPC 与自托管兼容。

典型调用包括余额查询、nonce 查找、费用估算、链 ID 检查和交易提交。如果端点过时或受到速率限制,钱包可能显示错误余额、重用 nonce 或无法广播。因此,选择可靠端点是钱包可靠性的一部分,而不是事后考虑。有关通用模型,请参阅多链 RPC 端点指南;有关配置模式,请参阅 RPC 端点指南。

  • 读取调用:余额、nonce、链 ID、费用历史、合约状态。
  • 写入路径:通过 eth_sendRawTransaction 或等效链方法提交本地签名的原始交易。
  • 故障模式:过时 nonce、错误链 ID、速率限制和交易丢弃。

验证程序的先决条件

以下检查假设使用 EVM 兼容链和 JSON-RPC 端点。将 RPC_URL 替换为您控制的端点或您正在评估的提供商端点。切勿将真实私钥粘贴到共享 shell 历史中;使用环境变量和一次性测试密钥进行签名实验。

您需要 curl 进行读取调用,以及 Node.js 配合 ethers 或 Python 配合 web3.py 进行签名。这些程序在签名部分之前是只读的,签名部分使用测试密钥且不广播。

export RPC_URL="https://your-endpoint.example"
export WALLET_ADDRESS="0xYourPublicAddress"
export PRIVATE_KEY="0xYourThrowawayTestKey"

通过 RPC 检查链身份和余额

在信任任何余额显示之前,确认端点位于您期望的链上。指向错误链 ID 的钱包可能显示零余额或提交被其他网络拒绝的交易。以下两个调用返回链 ID 和账户余额(以 wei 为单位)。

将输出记录在结果表中,同时记录端点、时间戳和区块号。不要假设值;测量它们。一个简单的表格,包含端点、链 ID、区块号、余额(wei)和观察到的延迟等列,可以使端点比较可复现。

curl -s -X POST "$RPC_URL" \
  -H "Content-Type: application/json" \
  -d '{"jsonrpc":"2.0","id":1,"method":"eth_chainId","params":[]}'

curl -s -X POST "$RPC_URL" \
  -H "Content-Type: application/json" \
  -d "{\"jsonrpc\":\"2.0\",\"id\":2,\"method\":\"eth_getBalance\",\"params\":[\"$WALLET_ADDRESS\",\"latest\"]}"

签名前验证 nonce 状态

账户 nonce 是从地址发送的交易计数。使用过时 nonce 签名的钱包将产生一笔交易,直到较早的 nonce 被挖出才能被包含。查询最新和待处理 nonce,以查看端点是否可见排队交易。

如果 pending 等于 latest,则在端点的内存池视图中没有来自该地址的排队交易。如果 pending 更高,则先前的交易仍在待处理。当用户重试卡住的交易时,这种区别很重要;替换它需要相同的 nonce 和更高的费用,而不是新的 nonce。

curl -s -X POST "$RPC_URL" \
  -H "Content-Type: application/json" \
  -d "{\"jsonrpc\":\"2.0\",\"id\":3,\"method\":\"eth_getTransactionCount\",\"params\":[\"$WALLET_ADDRESS\",\"latest\"]}"

curl -s -X POST "$RPC_URL" \
  -H "Content-Type: application/json" \
  -d "{\"jsonrpc\":\"2.0\",\"id\":4,\"method\":\"eth_getTransactionCount\",\"params\":[\"$WALLET_ADDRESS\",\"pending\"]}"

演示不广播的本地签名

非托管钱包的核心属性是签名发生在本地。您可以通过在自己的进程中构造和签名交易,然后检查原始签名载荷来证明这一点。没有密钥材料发送到 RPC 端点;只有结果十六进制字符串会被广播。

下面的 Node.js 示例使用 ethers 离线签名交易。使用一次性密钥和与端点匹配的链 ID 运行它。输出是已签名的原始交易,您可以解码或丢弃。Python 示例使用 web3.py 执行相同操作。

// npm install ethers
const { Wallet } = require("ethers");

async function main() {
  const wallet = new Wallet(process.env.PRIVATE_KEY);
  const tx = {
    to: process.env.WALLET_ADDRESS,
    value: 0n,
    nonce: 0,
    gasLimit: 21000n,
    maxFeePerGas: 1000000000n,
    maxPriorityFeePerGas: 1000000000n,
    chainId: 1,
    type: 2
  };
  const signed = await wallet.signTransaction(tx);
  console.log("from:", wallet.address);
  console.log("signed raw tx:", signed);
}

main().catch(console.error);

预期验证结果

正确配置的非托管设置应在各项检查中产生一致的结果。使用下表作为模板,并用您自己的测量值填充,而不是假设值。

检查预期观察不匹配意味着什么
eth_chainId与钱包 UI 显示的网络匹配端点位于不同链或代理路由错误
eth_getBalance对于有资金的地址非零,在两个端点上一致端点过时、地址错误或链错误
eth_getTransactionCount latest 与 pendingPending 大于或等于 latestPending 大于 latest 表示有排队交易
本地签名无需任何网络调用即可生成签名载荷如果签名需要远程调用,则密钥托管不是本地的
广播返回交易哈希并在区块浏览器上可见拒绝通常表示 nonce、费用或链 ID 错误

如果签名载荷在本地生成,且端点仅接收原始交易,则钱包流程在密钥材料方面是非托管的。如果任何步骤需要将私钥或种子发送到服务器,则无论营销语言如何,该流程都是托管的。

排查常见的非托管钱包故障

大多数钱包故障是基础设施或状态问题,而不是密钥问题。余额无法刷新通常意味着端点受到速率限制或落后于链头。交易永不确认通常意味着 nonce 过时或费用低于当前基础费用。显示错误网络的钱包通常意味着应用配置与端点之间的链 ID 不匹配。

对于卡住的交易,查询待处理 nonce 并使用相同 nonce 和更高优先费用重新提交。对于余额差异,在相同区块高度比较两个独立端点。对于签名错误,确认派生路径以及密钥与您期望的地址对应。如果您运行自己的节点,区块链节点托管指南涵盖影响钱包可靠性的同步和健康检查。

  • 余额过时:在固定区块号比较端点。
  • 交易卡住:重用 nonce 并提高费用。
  • 网络错误:验证钱包配置和端点响应中的链 ID。
  • 签名失败:检查派生路径和密钥-地址对应关系。

限制、权衡与后续步骤

非托管钱包消除了交易对手风险,但将操作风险集中在用户身上。丢失恢复短语不可恢复,钓鱼网站针对种子输入,恶意代币授权即使在密钥保持本地的情况下也可能耗尽资金。硬件钱包和交易模拟降低但不能消除这些风险。

RPC 依赖是另一个权衡。自托管钱包仍然信任端点获取链数据和传播。对于生产集成,在承诺之前评估端点可靠性、速率限制和链覆盖范围。您可以在 RPC 定价页面比较计划、查看支持的网络,或探索需要一致吞吐量的工作负载的专用节点选项。如需按链选择具体端点,请咨询 RPC Assistant。

  • 离线备份恢复短语,并在注资前验证备份。
  • 在签名不熟悉的合约之前模拟或解码交易。
  • 测试端点故障转移,以便单个提供商中断不会阻止签名和广播。
  • 在生产部署前查看 /en/learn 了解相关钱包和 RPC 基础知识。

永远不用担心基础设施

OnFinality 消除了 DevOps 的繁重工作,让您能够更聪明、更快地构建。

开始