EOS 账户体系简介

2019-02-27 16:54:50 浏览数 (1)

  1. eos 所有的代币都通过智能合约控制,包括 EOS。目前所有的代币的交易方法应该都是基于 eosio.token 智能合约,所以操作方法一致。
  2. eos 使用 action 来操作所有的链上数据,包括代币交易。action 需要签名,签名可以使用 ecc-secp256k1 或 ecc-secp256r1 曲线。 eos 通过 transaction(事务)来发送 action, action 可以有多个。
  3. action 的调用方法为:智能合约账户名 函数接口名 接口参数
  4. eos 使用 action 前需要先抵押一定的 eos 来换取 RAM,Network,CPU 资源。RAM 是持久资源,以当前市场价购买,卖出时也以当前市场价卖出;Network 和 CPU 资源限额24小时会重置,但只有新发起一笔操作后才会恢复。Network 和 CPU 资源赎回需要72小时后才能到手。发送 action 需要消耗Network 和 CPU。注册账户需要小量 RAM。抵押方法也是通过发送 transaction。cpu跟带宽的占用数据,只有在新发起一笔交易之后才会更新。
  5. eos 使用前需要先注册账户,方法是提交特定的 action,将指定公钥与账户名绑定。之后所有的操作都用账户名而不是公钥。账户名限制“.12345abcdefghijklmnopqrstuvwxyz”,12个字符以内,不可重复。目前只可注册 12个字符长的账号,其他账号以后可能以拍卖形式出售。目前不可注册带”.”的账号,只有系统账号可以带”.”
  6. eos 账户有权限等级体系,可以分配子权限给其他密钥。密钥派生一般使用 slip48 协议(对应 BTC 的 BIP44)。目前 eos 默认是 owner 和 active 两种权限,owner 可以更改 owner 和 active 对应的公钥,active 可以做除了更改公钥之外的所有操作。用户可自行增加下级权限。
  7. eos使用小端存储。
  8. eos transaction 格式: { expiration: '2018-10-07T16:29:39', ref_block_num: 55567, ref_block_prefix: 637338379, max_net_usage_words: 0, max_cpu_usage_ms: 0, delay_sec: 0, context_free_actions: [], actions: [ { account: 'eosio.token', name: 'transfer', authorization: [ { "actor": "inita", "permission": "active"} ], data: '202902f2520e91c3000000008093dd747011010000000000045359530000000000' } ], // 序列化后数据。原数据 { "from": "inita", "to": "initb", "quantity": "7.0000 SYS", "memo": ""} transaction_extensions: [] }, signatures: [ 'SIG_K1_KZQRFeGgN5EFctHBqhuV6u24Ewzme4TEnhnw8dEg5SVhkLes9kxcFWanYahdgt9N6LFJCKvREDabhGY5C1PGvhqj1uyJVD' ] } 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 { expiration: '2018-10-07T16:29:39', ref_block_num: 55567, ref_block_prefix: 637338379, max_net_usage_words: 0, max_cpu_usage_ms: 0, delay_sec: 0, context_free_actions: [], actions: [ { account: 'eosio.token', name: 'transfer', authorization: [ { "actor": "inita", "permission": "active"} ], data: '202902f2520e91c3000000008093dd747011010000000000045359530000000000' } ], // 序列化后数据。原数据 { "from": "inita", "to": "initb", "quantity": "7.0000 SYS", "memo": ""} transaction_extensions: [] }, signatures: [ 'SIG_K1_KZQRFeGgN5EFctHBqhuV6u24Ewzme4TEnhnw8dEg5SVhkLes9kxcFWanYahdgt9N6LFJCKvREDabhGY5C1PGvhqj1uyJVD' ] }
    • expiration:超时时间。如果 transaction 没有在该时间内被确认,则将直接无效。可以避免交易确认时间无法被确定。
    • ref_block_num:参考区块的高度。参考区块使得 transaction 只能在指定的链上被确认。则交易无法被分叉攻击。参考区块一般取签名前最后一个不可逆转的区块。ref_block_num = last_irreversible_block_num % 0xffff ref_block_prefix:参考区块的前缀。ref_block_prefix = last_irreversible_block_id[8, 12]
    • max_net_usage_words:限制该 transaction 最大 Network 使用
    • max_net_usage_words:限制该 transaction 最大 CPU 使用
    • delay_sec:被打包进区块后需要经过 delay_sec 秒后 transaction 才会被执行。期间用户可取消该 transaction
    • context_free_actions:类似 BTC 的隔离见证。暂时没用。https://github.com/EOSIO/eos/issues/1387。
    • actions:具体 action 列表,可以有多个。
    • action.account:智能合约账户名
    • action.name:action 名
    • action.authorization: 指定签名的账户,actor 账户名,permission 是权限。该字段决定签名的私钥。密钥选择方案:
      1. 若由上层解析,传入指定派生路径(根据 slip 48)给硬件。在上层被入侵的情况下,硬件可能会使用不匹配的密钥进行签名。如果在一开始权限授予的时候就被入侵,则子权限密钥可能不符合 slip48 规范,如子权限密钥和父密钥是同一个。此时权限等级机制将失效,安全性会降低。
      2. 硬件实现 slip48,自行解析 authorization 字段并选择恰当密钥。但这样一来扩展性会差一点。
      3. 硬件存储权限->密钥(或派生路径)键值对,这样麻烦一点,但扩展性好一点。
    • action.data:action 参数。已被序列化。
    • transaction_extensions:暂不支持的功能。
    • signatures:签名结果,base58编码,SIG_K1_ 前缀表示签名的曲线是 k1。
  9. eos transaction 序列化: eos 使用 eosjs-fcbuffer 进行序列化和反序列化,eosjs-fcbuffer 是 fcbuffer 的 fork 仓库,之前没太多人用。c 版本叫 fc。 序列化字段: { "expiration": 1538569524, // 需要转换为时间戳 "ref_block_num": 56170, "ref_block_prefix": 3374189397, "max_net_usage_words": 0, "max_cpu_usage_ms": 0, "delay_sec": 0, "context_free_actions": [], "actions": [ { "account": "eosio.token", "name": "transfer", "authorization": [ { "actor": "inita", "permission": "active" } ], "data": { // 被序列化前的数据 "from": "inita", "to": "initb", "quantity": "7.0000 SYS", "memo": "" } } ], "transaction_extensions": [] } 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 { "expiration": 1538569524, // 需要转换为时间戳 "ref_block_num": 56170, "ref_block_prefix": 3374189397, "max_net_usage_words": 0, "max_cpu_usage_ms": 0, "delay_sec": 0, "context_free_actions": [], "actions": [ { "account": "eosio.token", "name": "transfer", "authorization": [ { "actor": "inita", "permission": "active" } ], "data": { // 被序列化前的数据 "from": "inita", "to": "initb", "quantity": "7.0000 SYS", "memo": "" } } ], "transaction_extensions": [] } 这些字段对应的类型为: { "expiration": uint32, "ref_block_num": uint16, "ref_block_prefix": uint32, "max_net_usage_words": varuint32, "max_cpu_usage_ms": uint8, "delay_sec": varuint32, "context_free_actions": vector, "actions": [ // vector { "account": name, "name": name, "authorization": [ // vector { "actor": name, "permission": name } ], "data": { // data "from": name, "to": name, "quantity": asset, "memo": string } } ], "transaction_extensions": vector } 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 { "expiration": uint32, "ref_block_num": uint16, "ref_block_prefix": uint32, "max_net_usage_words": varuint32, "max_cpu_usage_ms": uint8, "delay_sec": varuint32, "context_free_actions": vector, "actions": [ // vector { "account": name, "name": name, "authorization": [ // vector { "actor": name, "permission": name } ], "data": { // data "from": name, "to": name, "quantity": asset, "memo": string } } ], "transaction_extensions": vector } 各字段的转换规则为:(小端存储)(根据 eosjs 和 eosjs-fcbuffer 源码得到)
    • uint8,uint16,uint32:正整数
    • varuint32:变长正整数,1-4个字节。每个 byte 的 [0, 6] 个 bit用于存储数据,最后一个bit用于是否是最后一个bit(0 是 1 不是)
    • vector:列表,size(varuint32) {data data …}(size 个)
    • name:base32 编码,定长8个字节。因为编码前 name 限制了长度为12,base32 占用5个bit,5 * 12 = 60 < 8 * 8
    • data:特殊类型,length(varuint32) {from, to, quantity, memo}(length 长度)
    • asset:特殊类型,分为三个部分:amount,precision,symbol。
    • amount 类型为 uint64,amount = value * 10 ^ precision,如7则为0700000000000000, 7.0000则为7011010000000000。
    • precision 类型为 uint8,应小于18(否则amount 可能溢出)。
    • symbol 长度为固定 7 字节,ASCII 编码
    • string:varuint32(length) UTF8encode(string)

    序列化结果: <br />// expiration ref_block_num ref_block_prefix 34b5b45b 6adb 550b1ec9 // max_net_usage_words max_cpu_usage_ms delay_sec context_free_actions 00 00 00 00 // actions [{ // account // name // authorization [{ // actor // permission // }] // }] 01 00a6823403ea3055 000000572d3ccdcd 01 000000000093dd74 00000000a8ed3232 // data: { // from // to // quantity{amount, symbol} // memo // } 21 000000000093dd74 000000008093dd74 7011010000000000 04 53595300000000 00 transaction_extensions 00 // result: 34b5b45b6adb550b1ec9000000000100a6823403ea3055000000572d3ccdcd01000000000093dd7400000000a8ed323221000000000093dd74000000008093dd74701101000000000004535953000000000000 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 <br />// expiration ref_block_num ref_block_prefix 34b5b45b 6adb 550b1ec9 // max_net_usage_words max_cpu_usage_ms delay_sec context_free_actions 00 00 00 00 // actions [{ //   account //   name //   authorization [{ //     actor //     permission //   }] // }] 01 00a6823403ea3055 000000572d3ccdcd 01 000000000093dd74 00000000a8ed3232 // data: { //   from //   to //   quantity{amount, symbol} //   memo // } 21 000000000093dd74 000000008093dd74 7011010000000000 04 53595300000000 00 transaction_extensions 00 // result: 34b5b45b6adb550b1ec9000000000100a6823403ea3055000000572d3ccdcd01000000000093dd7400000000a8ed323221000000000093dd74000000008093dd74701101000000000004535953000000000000

  10. eos 签名 mainChainId = aca376f206b8fc25a6ed44dbdc66547c36c6c33e3a119ffbeaef943642f0e906 // 主网 eos 链 chainId jungleChainId = 038f4b0fc8ff18a4f0842a8f0564611f6e96e8535901dd45e43ac8691a1c4dca // 测试网 jungle eos 链 chainId sysChainId = cf057bbfb72640471fd910bcb67639c22df9f92470936cddc1ade0e2f2e7dc4f // 本地 eos 链默认 chainId privateKey = 5KQwrPbwdL6PhXujxW37FSSQZ1JiwsST4cqQzDeyXtP79zkvFD3 // base 58 // mainnet header privateKey using compressed pubkey(01 if exist) checksum(sha256 ^ 2) // 80 D2653FF7CBB2D8FF129AC27EF5781CE68B2558C41A74AF1F2DDCA635CBEEF07D AA08644A chainIdBuf = mainChainId buf = 34b5b45b6adb550b1ec9000000000100a6823403ea3055000000572d3ccdcd01000000000093dd7400000000a8ed323221000000000093dd74000000008093dd74701101000000000004535953000000000000 // transaction 序列化结果 packedContextFreeData = 0000000000000000000000000000000000000000000000000000000000000000 // context_free_actions 的对应数据,eos 官方库是写死的,暂无作用 // 待签名 data signBuf = chainIdBuf buf packedContextFreeData // aca376f206b8fc25a6ed44dbdc66547c36c6c33e3a119ffbeaef943642f0e90692b4bc5bd2d8d970a04b000000000100a6823403ea3055000000572d3ccdcd01000000000093dd7400000000a8ed323227000000000093dd74000000008093dd747011010000000000045359530000000006e59388e59388000000000000000000000000000000000000000000000000000000000000000000 // 待签名 hash hash = sha256(signBuf) // f502c5b410ef5d08caf0dc9634c4cc83269487864c740be44fca6f50a0c58e94 // 签名 signature = ecc256k1(hash, privateKey) // SIG_K1_KcKPUw1sZ38YYBgYuTKMZa4xvfnZf7pNob7DZ7H6CXfbcfD2o2XsGD1vo9rcMjHjZivvCiNTradUStEcxvuypKxFcdGxBN // base 58 // i, r, s, checksum( ripemd(i, r, s, 'K1')[0, 4] ) // 20 39DD0B8AAB045745C28D6B977AC3F23D9805300879C842F186C6CDF3484560F9 28C501782449287FEBB594EB181B5FC58B5242C976F0E2BFD5FAB174099A68CC AC8C898D // lib/signature.js // i = eccrecovery() 4 27, 4 for compressed, 27 for compat // eosjs 是直接 4 27 的,网上资料不多,不太清楚4和27的含义。eccrecovery() 取值范围 [0, 3] // 另一个例子: // data: aca376f206b8fc25a6ed44dbdc66547c36c6c33e3a119ffbeaef943642f0e9063cb8bc5b22e05aae1c75000000000100a6823403ea3055000000572d3ccdcd01000000000093dd7400000000a8ed323221000000000093dd74000000008093dd747011010000000000045359530000000000000000000000000000000000000000000000000000000000000000000000000000 // hash: 3b0f1e23e39eff71ef6b2f2670086c3f0894ebf17820a0c3aac5f2467d1dbe2f // sig: SIG_K1_JyZ24w3Si9V8zt7axDVX3UNtStTVXWEd3diVwSyZMLMVHiRk3RyTi8LNv3qzWgKzz7LBb3uw7iLjMBhRHu7w4nXHWy1xVN 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 mainChainId = aca376f206b8fc25a6ed44dbdc66547c36c6c33e3a119ffbeaef943642f0e906 // 主网 eos 链 chainId jungleChainId = 038f4b0fc8ff18a4f0842a8f0564611f6e96e8535901dd45e43ac8691a1c4dca // 测试网 jungle eos 链 chainId sysChainId = cf057bbfb72640471fd910bcb67639c22df9f92470936cddc1ade0e2f2e7dc4f // 本地 eos 链默认 chainId privateKey = 5KQwrPbwdL6PhXujxW37FSSQZ1JiwsST4cqQzDeyXtP79zkvFD3 // base 58 // mainnet header privateKey                                                       using compressed pubkey(01 if exist)  checksum(sha256 ^ 2) // 80             D2653FF7CBB2D8FF129AC27EF5781CE68B2558C41A74AF1F2DDCA635CBEEF07D                                       AA08644A chainIdBuf = mainChainId buf = 34b5b45b6adb550b1ec9000000000100a6823403ea3055000000572d3ccdcd01000000000093dd7400000000a8ed323221000000000093dd74000000008093dd74701101000000000004535953000000000000 // transaction 序列化结果 packedContextFreeData = 0000000000000000000000000000000000000000000000000000000000000000 // context_free_actions 的对应数据,eos 官方库是写死的,暂无作用 // 待签名 data signBuf = chainIdBuf buf packedContextFreeData // aca376f206b8fc25a6ed44dbdc66547c36c6c33e3a119ffbeaef943642f0e90692b4bc5bd2d8d970a04b000000000100a6823403ea3055000000572d3ccdcd01000000000093dd7400000000a8ed323227000000000093dd74000000008093dd747011010000000000045359530000000006e59388e59388000000000000000000000000000000000000000000000000000000000000000000 // 待签名 hash hash = sha256(signBuf) // f502c5b410ef5d08caf0dc9634c4cc83269487864c740be44fca6f50a0c58e94 // 签名 signature = ecc256k1(hash, privateKey) // SIG_K1_KcKPUw1sZ38YYBgYuTKMZa4xvfnZf7pNob7DZ7H6CXfbcfD2o2XsGD1vo9rcMjHjZivvCiNTradUStEcxvuypKxFcdGxBN // base 58 // i, r, s, checksum( ripemd(i, r, s, 'K1')[0, 4] ) // 20 39DD0B8AAB045745C28D6B977AC3F23D9805300879C842F186C6CDF3484560F9 28C501782449287FEBB594EB181B5FC58B5242C976F0E2BFD5FAB174099A68CC AC8C898D // lib/signature.js // i = eccrecovery() 4 27, 4 for compressed, 27 for compat // eosjs 是直接 4 27 的,网上资料不多,不太清楚4和27的含义。eccrecovery() 取值范围 [0, 3] // 另一个例子: // data: aca376f206b8fc25a6ed44dbdc66547c36c6c33e3a119ffbeaef943642f0e9063cb8bc5b22e05aae1c75000000000100a6823403ea3055000000572d3ccdcd01000000000093dd7400000000a8ed323221000000000093dd74000000008093dd747011010000000000045359530000000000000000000000000000000000000000000000000000000000000000000000000000 // hash: 3b0f1e23e39eff71ef6b2f2670086c3f0894ebf17820a0c3aac5f2467d1dbe2f // sig: SIG_K1_JyZ24w3Si9V8zt7axDVX3UNtStTVXWEd3diVwSyZMLMVHiRk3RyTi8LNv3qzWgKzz7LBb3uw7iLjMBhRHu7w4nXHWy1xVN
  11. eos 公钥格式 pubKey = 026B996BC305719A8F563B9E85C9C96A54D40E15F9851FFED5F6A0710504FB5362 checksum = ripemd160(pubKey)[0, 4] = 1b0e677c eosPubKey = ‘EOS’ base58(pubKey checksum) = EOS5hsqHg5EftNtVjVaz39LPnYPEZboYRLbRKK6s4oQEpgsooJ5tP
  12. eos 私钥格式(WIF,虽然公钥默认使用压缩公钥,但不会在私钥末尾加01,而标准WIF规范若使用压缩公钥是需要加01的) priKey = D2653FF7CBB2D8FF129AC27EF5781CE68B2558C41A74AF1F2DDCA635CBEEF07D checksum = sha256(sha256(80 priKey)) = AA08644A eosPriKey = base58(priKey checksum) = 5KQwrPbwdL6PhXujxW37FSSQZ1JiwsST4cqQzDeyXtP79zkvFD3
  13. eos transactionId 对序列化交易报文进行sha256哈希,不需要添加chainid和packedContextFreeData
  14. eos rpc push_transaction 提交格式 { "compression": "none", // 暂不清楚用途 "packed_context_free_data": "", // hex data,目前为0 "packed_trx": "34b5b45b6adb550b1ec9000000000100a6823403ea3055000000572d3ccdcd01000000000093dd7400000000a8ed323221000000000093dd74000000008093dd74701101000000000004535953000000000000", // 交易序列化结果 "signatures":[ // 所有签名 "SIG_K1_KeH6wCsnUWRjrfGtqPpXFK4BJArfQ4FwuZARnpVyWkfgdrbrKMgH1msyvrvGyxABYj5UyNpMmipWhpyaruRaRFQbcuDBb4" ] } 1 2 3 4 5 6 7 8 9 { "compression": "none", // 暂不清楚用途 "packed_context_free_data": "", // hex data,目前为0 "packed_trx": "34b5b45b6adb550b1ec9000000000100a6823403ea3055000000572d3ccdcd01000000000093dd7400000000a8ed323221000000000093dd74000000008093dd74701101000000000004535953000000000000", // 交易序列化结果 "signatures":[ // 所有签名 "SIG_K1_KeH6wCsnUWRjrfGtqPpXFK4BJArfQ4FwuZARnpVyWkfgdrbrKMgH1msyvrvGyxABYj5UyNpMmipWhpyaruRaRFQbcuDBb4" ] }

0 人点赞