pack/unpack action_data/transaction を使う
今回使用する環境は EOS のメインネット。
code:get_info.sh
code:chain_info.json
{
"server_version": "2c9544bf",
"chain_id": "aca376f206b8fc25a6ed44dbdc66547c36c6c33e3a119ffbeaef943642f0e906",
"head_block_num": 51759009,
"last_irreversible_block_num": 51758682,
"last_irreversible_block_id": "0315c65a43dff99a653c7162432c90fc4649fc911de53d46ac0bf801d5624be2",
"head_block_id": "0315c7a13af46292c4e53568ef968d03cafeb739007f457bd6c0afcd3ad18a10",
"head_block_time": "2019-04-07T19:12:01.000",
"head_block_producer": "eosbeijingbp",
"virtual_block_cpu_limit": 200000000,
"virtual_block_net_limit": 1048576000,
"block_cpu_limit": 200000,
"block_net_limit": 1048576,
"server_version_string": "v1.6.1-26-g2c9544bf1"
}
適当な transaction の JSON を用意する。ただし、すでに存在するコントラクトアカウントとアクションを指定すること。
code:unpack_transaction.json
{
"expiration": "2019-04-07T14:02:41",
"ref_block_num": 13549,
"ref_block_prefix": 1770321463,
"max_net_usage_words": 0,
"max_cpu_usage_ms": 0,
"delay_sec": 0,
"context_free_actions": [],
"actions": [
{
"account": "pcscoreprtcl",
"name": "refreshkey2",
"authorization": [
{
"actor": "pcscoreagent",
"permission": "active"
}
],
"data": {
"sym": "PTSD",
"token_id": 6,
"new_subkey": "EOS6PLDjNz8MS8arFa7TDy6FRzhFfjrRSuUpYyKzaGFhv35mXQCTW",
"sig": "SIG_K1_K226ddTSqDnmtCVGzEXMKzYpapqr8dfLhMvwiEhgZ8rTPcMijS9teAJji9KEpZ31TM7xtezfyjTZ6zNH2fB4Fw5CgVzVWb"
}
}
],
"transaction_extensions": []
}
transaction.json のアクションデータに対して、cleos convert pack_action_data を行うと次を得る:
code:pack_action_data.sh
cleos -u https://api.eoslaomao.com:443 convert pack_action_data pcscoreprtcl refreshkey2 '{"sym": "PTSD", "token_id": 6, "new_subkey": "EOS6PLDjNz8MS8arFa7TDy6FRzhFfjrRSuUpYyKzaGFhv35mXQCTW", "sig": "SIG_K1_K226ddTSqDnmtCVGzEXMKzYpapqr8dfLhMvwiEhgZ8rTPcMijS9teAJji9KEpZ31TM7xtezfyjTZ6zNH2fB4Fw5CgVzVWb"}' code:packed_action_data.txt
505453440000000006000000000000000002c52fc40f28873fa2b5872c62a782f4ecc0e3a41ec1bbbf352f0d24a262bbcafa001f33b3d98ca27ed6590dd13fb46c11fe8244a921a3597f708c4557e45dcfa7407447f6b2003570fb0e718e1321d93e84008a5960a2b488d3f3c2b750f300938906
これは、
symbol_code sym = "PTSD": 5054534400000000
uint64_t tokne_id = 6: 0600000000000000
new_subkey = "EOS6PLDjNz8MS8arFa7TDy6FRzhFfjrRSuUpYyKzaGFhv35mXQCTW" :
unsigned_int type = 0 : 00
array<char,33> data : 02c52fc40f28873fa2b5872c62a782f4ecc0e3a41ec1bbbf352f0d24a262bbcafa
sig = "SIG_K1_K226dd...gVzVWb" :
unsigned_int type = 0 : 00
array<char,65> data : 1f33b3d98ca27ed6590dd13fb46c11fe8244a921a3597f708c4557e45dcfa7407447f6b2003570fb0e718e1321d93e84008a5960a2b488d3f3c2b750f300938906
と変換されている。
uint64_t 型は 1 バイトごとに区切ってリトルエンディアンで連結する。
symbol_code 型は raw にして uint64_t と同様に変換する。
unsigned_int 型はリトルエンディアンだが、uint64_t 型と異なり、7 ビットごとに区切って続きがあるかどうかが残りの 1 ビットに入る。つまり、0 は "0x00"、1 は "0x01"、127 は "0x7f" ("0b01111111")、 128 は繰り上がりが起きて "0x80" "0x01" ("0b10000000" "0b00000001") になるといった具合である。
prefix が "EOS" の public_key 型と prefix が "SIG_K1_" の signature 型は、どちらも type が unsigned_int 型の 0 で、本体を base58 デコードする。
もとに戻すこともできる:
code:unpack_action_data.sh
cleos -u https://api.eoslaomao.com:443 convert unpack_action_data pcscoreprtcl refreshkey2 505453440000000006000000000000000002c52fc40f28873fa2b5872c62a782f4ecc0e3a41ec1bbbf352f0d24a262bbcafa001f33b3d98ca27ed6590dd13fb46c11fe8244a921a3597f708c4557e45dcfa7407447f6b2003570fb0e718e1321d93e84008a5960a2b488d3f3c2b750f300938906 code:unpacked_action_data.json
{
"sym": "PTSD",
"token_id": 6,
"new_subkey": "EOS6PLDjNz8MS8arFa7TDy6FRzhFfjrRSuUpYyKzaGFhv35mXQCTW",
"sig": "SIG_K1_K226ddTSqDnmtCVGzEXMKzYpapqr8dfLhMvwiEhgZ8rTPcMijS9teAJji9KEpZ31TM7xtezfyjTZ6zNH2fB4Fw5CgVzVWb"
}
transaction.json に対して、cleos convert pack_transaction --pack-action-data を行うと次を得る:
code:pack_transaction.sh
code:packed_transaction.json
{
"signatures": [],
"compression": "none",
"packed_context_free_data": "",
"packed_trx": "0103aa5ced3437f6846900000000011051be555d8a30aa008457b0617597ba0190a762465d8a30aa00000000a8ed323274505453440000000006000000000000000002c52fc40f28873fa2b5872c62a782f4ecc0e3a41ec1bbbf352f0d24a262bbcafa001f33b3d98ca27ed6590dd13fb46c11fe8244a921a3597f708c4557e45dcfa7407447f6b2003570fb0e718e1321d93e84008a5960a2b488d3f3c2b750f30093890600"
}
これは、
time_point_sec expiration = "2019-04-07T14:02:41" :
uint32_t utc_seconds = 1554645761 : 0103aa5c
uint16_t ref_block_num = 13549 : ed34
uint32_t ref_block_prefix = 1770321463 : 37f68469
unsigned_int max_net_usage_words = 0 : 00
uint8_t max_cpu_usage_ms = 0 : 00
unsigned_int delay_sec = 0 : 00
vector<action> context_free_actions = [] : 00
vector<action> actions :
unsigned_int actions_vector_length = 1 : 01
name account = "pcscoreprtcl" : 1051be555d8a30aa
name name = "refreshkey2" : 008457b0617597ba
vector<permission_level> authorization :
unsigned_int authorization_vector_length = 1: 01
name actor = "pcscoreagent" : 90a762465d8a30aa
name permission = "active" : 00000000a8ed3232
vector<char> data :
unsigned_int data_vector_length = 116 : 74
char data[0] : 50
char data[1] : 54
char data[2] : 53
......
char data[115] : 06
vector<tuple<uint16_t, vector<char>>> transaction_extensions = [] : 00
と変換されている。time_point_sec 型は UNIX time を 1 秒で割り算して uint32_t と同様に変換する。name 型は value にして uint64_t と同様に変換する。vector<T> 型は最初に unsigned_int 型で長さが格納され、続けて 0 番目の要素から順に連結される。
cleos convert unpack_transaction も使ってみる。
code:unpack_transaction.sh
code:unpacked_transaction.json
{
"expiration": "1970-01-01T00:00:00",
"ref_block_num": 0,
"ref_block_prefix": 0,
"max_net_usage_words": 0,
"max_cpu_usage_ms": 0,
"delay_sec": 0,
"context_free_actions": [],
"actions": [],
"transaction_extensions": [],
"signatures": [],
"context_free_data": []
}
これは、transaction 構造体を初期値でインスタンス化したものである。あれぇ?
まとめ
pack/unpack の変換規則はわかったが、cleos convert unpack_transaction のやり方はわからない。
関連ワード