- eos 所有的代币都通过智能合约控制,包括 EOS。目前所有的代币的交易方法应该都是基于 eosio.token 智能合约,所以操作方法一致。
- eos 使用 action 来操作所有的链上数据,包括代币交易。action 需要签名,签名可以使用 ecc-secp256k1 或 ecc-secp256r1 曲线。 eos 通过 transaction(事务)来发送 action, action 可以有多个。
- action 的调用方法为:智能合约账户名 函数接口名 接口参数
- eos 使用 action 前需要先抵押一定的 eos 来换取 RAM,Network,CPU 资源。RAM 是持久资源,以当前市场价购买,卖出时也以当前市场价卖出;Network 和 CPU 资源限额24小时会重置,但只有新发起一笔操作后才会恢复。Network 和 CPU 资源赎回需要72小时后才能到手。发送 action 需要消耗Network 和 CPU。注册账户需要小量 RAM。抵押方法也是通过发送 transaction。cpu跟带宽的占用数据,只有在新发起一笔交易之后才会更新。
- eos 使用前需要先注册账户,方法是提交特定的 action,将指定公钥与账户名绑定。之后所有的操作都用账户名而不是公钥。账户名限制“.12345abcdefghijklmnopqrstuvwxyz”,12个字符以内,不可重复。目前只可注册 12个字符长的账号,其他账号以后可能以拍卖形式出售。目前不可注册带”.”的账号,只有系统账号可以带”.”
- eos 账户有权限等级体系,可以分配子权限给其他密钥。密钥派生一般使用 slip48 协议(对应 BTC 的 BIP44)。目前 eos 默认是 owner 和 active 两种权限,owner 可以更改 owner 和 active 对应的公钥,active 可以做除了更改公钥之外的所有操作。用户可自行增加下级权限。
- eos使用小端存储。
- 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 是权限。该字段决定签名的私钥。密钥选择方案:
- 若由上层解析,传入指定派生路径(根据 slip 48)给硬件。在上层被入侵的情况下,硬件可能会使用不匹配的密钥进行签名。如果在一开始权限授予的时候就被入侵,则子权限密钥可能不符合 slip48 规范,如子权限密钥和父密钥是同一个。此时权限等级机制将失效,安全性会降低。
- 硬件实现 slip48,自行解析 authorization 字段并选择恰当密钥。但这样一来扩展性会差一点。
- 硬件存储权限->密钥(或派生路径)键值对,这样麻烦一点,但扩展性好一点。
- action.data:action 参数。已被序列化。
- transaction_extensions:暂不支持的功能。
- signatures:签名结果,base58编码,SIG_K1_ 前缀表示签名的曲线是 k1。
- 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
- 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
- eos 公钥格式 pubKey = 026B996BC305719A8F563B9E85C9C96A54D40E15F9851FFED5F6A0710504FB5362 checksum = ripemd160(pubKey)[0, 4] = 1b0e677c eosPubKey = ‘EOS’ base58(pubKey checksum) = EOS5hsqHg5EftNtVjVaz39LPnYPEZboYRLbRKK6s4oQEpgsooJ5tP
- eos 私钥格式(WIF,虽然公钥默认使用压缩公钥,但不会在私钥末尾加01,而标准WIF规范若使用压缩公钥是需要加01的) priKey = D2653FF7CBB2D8FF129AC27EF5781CE68B2558C41A74AF1F2DDCA635CBEEF07D checksum = sha256(sha256(80 priKey)) = AA08644A eosPriKey = base58(priKey checksum) = 5KQwrPbwdL6PhXujxW37FSSQZ1JiwsST4cqQzDeyXtP79zkvFD3
- eos transactionId 对序列化交易报文进行sha256哈希,不需要添加chainid和packedContextFreeData
- 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" ] }
EOS 账户体系简介
2019-02-27 16:54:50
浏览数 (1)