Diem 账户体系详解:地址推导、认证密钥、资源结构与账户角色 Diem 账户体系详解地址推导、认证密钥、资源结构与账户角色【免费下载链接】diemDiem’s mission is to build a trusted and innovative financial network that empowers people and businesses around the world.项目地址: https://gitcode.com/gh_mirrors/di/diem本篇技术指南以 Diem 开发者文档《Accounts》为核心系统讲解 Diem 区块链的账户模型从 16 字节账户地址与认证密钥的密码学推导到账户中 Move 模块/资源的存储结构再到 ParentVASP/ChildVASP 角色体系与账户创建流程。读完本文你将能够理解 Diem 账户的底层数据结构掌握单签与多签认证密钥的生成方法并能在 testnet 与主网/预主网环境中正确完成账户创建、币种添加与认证密钥轮换等实操任务。账户的本质代码与数据的容器在 Diem 区块链中账户Account是链上的一种资源resource其唯一职责是发送交易send transactions。每个账户由一个特定的16 字节账户地址标识同时是 Move 模块Move modules与 Move 资源Move resources的容器。账户状态由两部分组成types/src/account_address.rs、language/diem-framework/modules/DiemAccount.move代码CodeMove 模块包含类型声明与过程procedure声明但不含数据。模块中的过程编码了更新区块链全局状态的规则即“智能合约”逻辑。数据DataMove 资源只包含数据、不含代码。每个资源值都有一个类型该类型在发布到区块链分布式数据库中的某个模块里声明。一个账户可以持有任意数量的 Move 资源与 Move 模块。Diem 支付网络Diem Payment NetworkDPN支持为 Regulated VASP受监管虚拟资产服务商与 Designated Dealer指定经销商创建账户。从源码看一个“地址是 Diem 账户”的充要条件是该地址下已发布DiemAccount资源。这一定义直接体现在 DiemAccount.move 的注释中“Anaddressis a Diem Account iff it has a published DiemAccount resource.”账户地址16 字节的密码学派生值Diem 账户地址是一个16 字节128 位的值它不是随机生成的而是由其初始认证密钥authentication key派生而来。地址与认证密钥的关系每个账户在链上都存储一个认证密钥用于认证交易的签名者。认证密钥为 32 字节其中前 16 字节称为auth key prefix认证密钥前缀后 16 字节即账户地址。这一划分在 Rust 类型层有精确实现在 types/src/transaction/authenticator.rs 中AuthenticationKey::derived_address()保留 32 字节认证密钥的后 16 字节作为AccountAddress而prefix()返回前 16 字节。DPN 支持两种签名方案Ed25519用于单签交易scheme identifier 为0x00MultiEd25519用于多签交易scheme identifier 为0x01。签交易时必须持有账户对应的私钥。由于地址由初始认证密钥派生DPN 支持在不改变账户地址的前提下轮换认证密钥——账户的初始认证密钥被一个新生成的认证密钥替换地址保持不变详见下文“轮换认证密钥”小节。生成认证密钥与账户地址单签生成认证密钥与账户地址的完整流程生成密钥对生成一对全新的密钥对(pubkey_A, privkey_A)。DPN 使用 RFC 8032 定义的 Ed25519 曲线上的 PureEdDSA 方案。推导 32 字节认证密钥计算auth_key sha3-256(K_pub | 0x00)其中|表示字节拼接0x00是 1 字节的签名方案标识符0x00表示单签。auth_key的前 16 字节是auth key prefix后 16 字节是账户地址。创建账户任何创建账户的交易都需要同时提供账户地址与auth key prefix而任何与既有账户交互的交易只需提供地址即可。该流程与 Rust 实现一一对应在 types/src/transaction/authenticator.rs 中AuthenticationKeyPreimage::new()将公钥字节与 scheme 字节拼接成 preimagepublic_key | scheme_idAuthenticationKey::from_preimage()对其做 SHA3-256 哈希得到认证密钥types/src/account_address.rs 中的from_public_key()则通过AuthenticationKey::ed25519(public_key).derived_address()直接得到地址。这也解释了为什么地址无需公钥上链——验证者只需对签名者的公钥做同样的哈希运算即可比对。多签认证K-of-N Multisig账户的认证密钥既可以要求单签也可以要求多签。在K-of-N 多签方案中账户共有 N 个签名者交易必须获得其中至少 K 个签名才能通过认证。创建 K-of-N 多签认证密钥的步骤与单签类似生成密钥对生成 N 个 ed25519 公钥p_1, …, p_n。推导 32 字节认证密钥计算auth_key sha3-256(p_1 | … | p_n | K | 0x01)其中|表示拼接0x01是 1 字节签名方案标识符0x01表示多签K为阈值。随后按上文方式派生地址与 auth key prefix。多签公钥在链上通过SharedEd25519PublicKey资源发布在 SharedEd25519PublicKey.move 中该资源持有合并后的多签公钥publish用于首次发布、rotate_key用于轮换。Rust 侧的AuthenticationKey::multi_ed25519()authenticator.rs与AuthenticationKeyPreimage::multi_ed25519()authenticator.rs实现了对应的 preimage 构造。账户资源每个账户至少两种DPN 上的每个账户创建时至少携带两种资源RoleIdRoles.move为账户授予唯一且不可变的 角色role用于访问控制对应 DIP-2 规范。其结构仅含一个role_id: u64字段通过grant_role在创建时move_to到账户下且重复发布会以EROLE_ID错误中止Roles.move。DiemAccountDiemAccount.move持有账户的序列号sequence number、认证密钥authentication key与事件句柄event handles。完整的DiemAccount资源还包括withdraw_capability取款能力与key_rotation_capability密钥轮换能力两个可提取/恢复的能力字段以及收发支付事件句柄。从 DiemAccount.move 可以看到sequence_number每提交一笔交易递增 1用于防止重放攻击详见 术语表“Sequence Number”。货币CurrenciesDPN 支持账户以不同货币进行交易。从标准视角看DiemCoinType是 Diem 区块链上等同于 ERC20 的货币资源Diem.md 中 resource Diem。在 Move 层面它们是同一个Diem资源类型的不同泛型实例化例如DiemCoin1DiemXUS其中DiemXUS是启动时可供使用的货币类型。货币的类型参数在 Diem.move 中定义链上货币注册与授权由RegisteredCurrencies等模块管理。余额Balances每当一种DiemCoinType货币被授权给某个账户时会自动为账户添加一个零余额的DiemCoinType。每个非管理账户存储一个或多个BalanceCoinType资源DiemAccount.move 中 resource Balance。账户每持有一种货币如DiemCoin1或DiemXUS就对应一个独立的Balance资源如BalanceDiemCoin1、BalanceDiemXUS。Balance的唯一字段coin: DiemToken存储该币种的总价值。客户端向某账户发送CoinType资金时应检查账户地址是否存在确保该地址拥有CoinType的余额资源——即使余额为零。关键约束账户必须持有DiemCoinType余额才能收发该币种。向没有该币种余额资源的账户发送DiemCoinType会使交易中止abort。对应错误码在源码中定义EPAYEE_DOES_NOT_EXIST收款账户不存在与EPAYEE_CANT_ACCEPT_CURRENCY_TYPE收款账户不接受该币种见 DiemAccount.move。余额的添加有两种途径账户创建时一次性添加创建之后通过 add_currency 脚本添加。只有账户所有者能在账户创建后新增余额。一旦添加该余额不可移除——例如接受DiemXUS的账户将永远接受DiemXUS。账户角色ParentVASP 与 ChildVASP所有 Regulated VASP 可以拥有两种账户各自承担不同角色。角色以RoleId资源形式存储在链上并在函数入口通过Roles::assert_*断言校验Roles.move。ParentVASP 账户每个 Regulated VASP 有且仅有一个唯一的根账户称为ParentVASP。ParentVASP 携带三块关键数据其名称name用于 off-chain API 的端点 URLendpoint URL用于认证 off-chain 数据载荷签名的合规公钥compliance public key。从源码看ParentVASP 角色由Roles::new_parent_vasp_role授予且仅限 Treasury Compliance 账户调用Roles.move这正对应主网中“只有 TreasuryCompliance 能创建 ParentVASP”的访问控制模型。ChildVASP 账户ChildVASP是某个 ParentVASP 的子账户。一个 Regulated VASP 不一定要有子账户但子账户允许其在链上维持结构化的存在形态例如分离 cold/warm/hot 账户。ChildVASP 知道其 ParentVASP 的地址。当与 ChildVASP 交易需要 off-chain 通信时客户端应使用该地址查询 ParentVASP 信息。Roles::new_child_vasp_role要求调用者必须具有 ParentVASP 角色Roles.move即 ParentVASP 可以为自己创建子账户子账户不能再创建子账户。创建账户主网/预主网ParentVASP 与 ChildVASP当 Diem 主网mainnet启动后只有 TreasuryCompliance 账户能创建 ParentVASP 账户对应 DIP-2 中的 roles 访问控制。一旦 ParentVASP 创建成功该 Regulated VASP 即可创建 ChildVASP 账户。创建新账户时创建者必须指定新账户的地址address其认证密钥前缀auth key prefix账户初始接受的货币currencies。重要限制只能向已存在账户的地址发送资金。如果向空地址发送资金不会为该地址创建账户创建账户的交易会中止。这一约束由EPAYEE_DOES_NOT_EXIST错误码DiemAccount.move在执行期强制执行。更完整的创建流程见 创建账户与铸造作为已获 Diem Networks 批准的 Regulated VASP先完成申请由 Diem Networks 代你创建 ParentVASP 账户称为账户A。从账户A你的 ParentVASP 账户发送create_child_vasp_account交易脚本以创建 ChildVASP 账户对应脚本见 AccountCreationScripts.move。单个 ParentVASP 账户最多可创建 256 个 ChildVASP 账户。该脚本允许指定新账户应持有哪种货币或持有全部已知货币是否以指定数量的某币种初始化 ChildVASP 账户余额。Regulated VASP 可以从 Designated Dealer 处购买 Diem 币。配套的create_parent_vasp_account与create_designated_dealer交易脚本定义于 AccountCreationScripts.move 与 AccountCreationScripts.move分别被 TreasuryCompliance 用于创建 ParentVASP 账户和指定经销商账户。Testnet通过 Faucet 创建账户并铸造在testnet上可以使用Faucet服务执行某些只有 Diem 协会在主网上才能执行的操作。向 faucet 服务端点发送请求即可创建ParentVASP 账户铸造并向账户添加测试用假 Diem 币。向 faucet 服务器发送请求的 HTTP 格式http://faucet server address/?amountamountauth_keyauth_keycurrency_codecurrency_code参数说明参数含义auth_key账户的授权密钥amount账户可用的余额金额currency_code该金额对应的货币代码处理逻辑请求首先检查指定授权密钥下是否存在账户如果auth_key对应的账户不存在则创建一个带有amount余额以currency_code计的 ParentVASP 账户如果账户已存在则直接向该账户添加指定数量的currency_codeDiem 币。账户管理操作账户创建后可通过不同类型的交易完成以下管理任务详见 管理账户。创建恢复地址账户Recovery AddressRegulated VASP 可以将其某个账户指定为恢复地址账户。恢复地址账户应为冷账户即不计划从中发送任何交易仅用于为已注册到它的账户在其私钥丢失时轮换认证密钥。示例流程设恢复地址账户为R。从账户R发送create_recovery_address交易创建恢复地址对应链上RecoveryAddress模块见 RecoveryAddress.move。恢复地址R创建后属于该 VASP 的其他账户可通过发送add_recovery_rotation_capability交易并指定恢复地址为R将自己注册到 R。轮换认证密钥Rotate Authentication Key账户A希望更新访问其所需的认证密钥时根据 A 是否已注册恢复地址选择两种交易之一若A 未注册恢复地址发送rotate_authentication_key交易携带新的认证密钥。若A 属于某个恢复地址发送rotate_authentication_key_with_recovery_address交易携带新认证密钥并将自身作为to_recover地址。链上实现位于 DiemAccount.moverotate_authentication_key首先断言新认证密钥长度为 32否则以EMALFORMED_AUTHENTICATION_KEY中止然后将sender_account_resource.authentication_key覆盖为新值。该函数仅允许在key_rotation_capability未提取时调用且密钥轮换能力extract_key_rotation_capability/restore_key_rotation_capability见 DiemAccount.move可被提取后由持有者执行轮换——这正是恢复地址实现“丢失私钥后由恢复账户代轮换”的能力基础。向账户添加货币Add a Currency账户A想持有某种当前未持有的货币C的余额时可从A发送add_currency_to_account交易指定货币C。两个硬性约束不满足则交易执行失败C必须是链上已识别的货币A不能已经持有C的余额。重复添加已有币种会触发EADD_EXISTING_CURRENCY错误DiemAccount.move。小结Diem 账户体系围绕“地址—认证密钥—资源”三层核心设计地址与认证密钥均源自公钥的 SHA3-256 哈希并可按单签/多签K-of-N两种方案构造链上账户由RoleId与DiemAccount资源锚定余额以泛型BalanceCoinType按币种隔离存储ParentVASP/ChildVASP 两级角色体系配合 TreasuryCompliance 的访问控制决定了谁能在何时创建何种账户。理解这些机制是编写 Diem 客户端、设计钱包接入与进行链上账户管理的前提。想继续深入可阅读 Move 模块源码、交易脚本文档 以及 术语表。【免费下载链接】diemDiem’s mission is to build a trusted and innovative financial network that empowers people and businesses around the world.项目地址: https://gitcode.com/gh_mirrors/di/diem创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考