共计 9249 个字符,预计需要花费 24 分钟才能阅读完成。
id:BSN_2021
公众号:BSN 研习社
红枣科技何来亮
背景:往年 3 月凋谢联盟链“中移链”在区块链服务网络(BSN[1])中实现适配并上线公布, 吸引了少量开发者,局部开发者提出了一些共性问题
目标:本篇文章是为了让读者理解如何在中移链 (基于 EOS) 上调用 RPC 接口组装交易、签名、上链以及查问上链后果
实用对象:实用于 BSN 凋谢联盟链 – 中移链 (基于 EOS) 开发者
1. 筹备
•须要当初 bsn[2]创立我的项目和创立一个账户,能够参考:https://bsnbase.com/static/tm…
•能够获取到 eos 端点:https://opbningxia.bsngate.com:18602/api/aecb28acfd154cfeb90d0b6a8ecab1e7/rpc
•eos 账户 / 合约地址:helailiang14
•为账户购买足够的资源(cpu、net、ram)
•装置 EOSIO 开发环境:须要装置 cleos 和 keosd, 能够参考:https://developers.eos.io/wel… •部署 eos 合约: hello.cpp
#include <eosio/eosio.hpp>
#include <eosio/transaction.hpp>
using namespace eosio;
// 通过 [[eosio::contract]] 标注这个类是一个合约
class [[eosio::contract]] hello : public contract
{
public:
using contract::contract;
// 在构造函数进行表对象的实例化, 规范合约构造函数,receiver 也就是咱们的合约账号(个别状况下),code 就是咱们的 action 名称,ds 就是数据流
// get_self() 合约所在的账号 get_code() 以后交易申请的 action 办法名 get_datastream() 以后数据流
hello(name receiver, name code, datastream<const char *> ds) : contract(receiver, code, ds), friend_table(get_self(), get_self().value)
{ }
// 用 [[eosio::action]] 标注这个办法是一个合约 action 就行
// 留神:action 的名称要求合乎 name 类型的规定
[[eosio::action]] void hi(name user)
{print("Hello,", user);
print("get_self,", get_self().value);
// print("get_code,", get_code().value);
uint32_t now = current_time_point().sec_since_epoch();
auto friend_itr = friend_table.find(user.value);
// 数据不存在
if (friend_itr == friend_table.end())
{
// 第一个参数就是内存应用的对象,第二个参数就是增加表对象时的委托办法。friend_table.emplace(get_self(), [&](auto &f) {
f.friend_name = user;
f.visit_time = now;
});
}
else
{
// 第一个参数是传递须要批改的数据指针,第二个参数是内存应用的对象,第二个参数就是表对象批改时的委托办法
friend_table.modify(friend_itr, get_self(), [&](auto &f) {f.visit_time = now;});
}
}
[[eosio::action]] void nevermeet(name user)
{print("Never see you again,", user);
auto friend_itr = friend_table.find(user.value);
check(friend_itr != friend_table.end(), "I don't know who you are.");
// 只有一个参数,就是要删除的对象指针
friend_table.erase(friend_itr);
}
[[eosio::action]] void meetagain()
{uint32_t now = current_time_point().sec_since_epoch();
auto time_idx = friend_table.get_index<"time"_n>();
auto last_meet_itr = time_idx.begin();
check(last_meet_itr != time_idx.end(), "I don't have a friend.");
time_idx.modify(last_meet_itr, get_self(), [&](auto &f) {f.visit_time = now;});
}
private:
// 定义一个构造体,而后用 [[eosio::table]] 标注这个构造体是一个合约表。在构造体里定义一个函数名 primary_key,返回 uint64_t 类型,作为主键的定义
struct [[eosio::table]] my_friend
{
name friend_name;
uint64_t visit_time;
uint64_t primary_key() const { return friend_name.value;}
double by_secondary() const { return -visit_time;}
};
// 定义表名和查问索引 "friends"_n 就是定义表名,所以应用了 name 类型,之后 my_friend 是表的构造类
typedef eosio::multi_index<"friends"_n, my_friend> friends;
friends friend_table;
};
2. rpc 调用流程
1. 将交易信息由 JSON 格局序列化为 BIN 格局字符串
curl -X POST 'https://opbningxia.bsngate.com:18602/api/{您的凋谢联盟链我的项目 ID/rpc/v1/chain/abi_json_to_bin' \
-d '{"code":"helailiang14","action":"hi","args": {"user":"helloworld"}
}'
------------------
return
{"binargs":"00408a97721aa36a"}
- 获取以后最新的区块编号
curl GET 'https://opbningxia.bsngate.com:18602/api/{您的凋谢联盟链我的项目 ID/rpc/v1/chain/get_info'
------------------
return
{
"server_version":"11d35f0f",
"chain_id":"9b4c6015f8b73b2d7ee3ebd92d249a1aba06a614e9990dcf54f7cf2e3d5172e1",
"head_block_num":15134328,
"last_irreversible_block_num":15134262,
"last_irreversible_block_id":"00e6ee360b5e7680a526ddea45db1be15c4be2cd2389020688218fe765be6db7",
"head_block_id":"00e6ee7889523875a28284effecdd1199cc960adb14c14c36cd1bd52afed6824",
"head_block_time":"2022-04-27T09:08:08.500",
"head_block_producer":"prod.b",
"virtual_block_cpu_limit":200000000,
"virtual_block_net_limit":1048576000,
"block_cpu_limit":199900,
"block_net_limit":1048576,
"server_version_string":"v3af0a20",
"fork_db_head_block_num":15134328,
"fork_db_head_block_id":"00e6ee7889523875a28284effecdd1199cc960adb14c14c36cd1bd52afed6824",
"server_full_version_string":"v3af0a20",
"last_irreversible_block_time":"2022-04-27T09:07:35.500"
}
获取到 head_block_num : 15134328
援用
获取 head_block_id:00e6ee7889523875a28284effecdd1199cc960adb14c14c36cd1bd52afed6824
援用
获取 chain_id: 9b4c6015f8b73b2d7ee3ebd92d249a1aba06a614e9990dcf54f7cf2e3d5172e1
- 依据区块编号获取区块详情
curl -X POST 'https://opbningxia.bsngate.com:18602/api/{您的凋谢联盟链我的项目 ID/rpc/v1/chain/get_block' \
-d '{"block_num_or_id":"15130610"}'
------------------
return
{
"timestamp": "2022-04-27T09:08:08.500",
"producer": "prod.b",
"confirmed": 0,
"previous": "00e6ee77f2655528739622d2c9235026d4f10138b9821e46ea35165cb086d12d",
"transaction_mroot": "0000000000000000000000000000000000000000000000000000000000000000",
"action_mroot": "665584b582b234bf58d3708b31da20e14d266713e3bc6ce79ea3187cc2ffa5a4",
"schedule_version": 2,
"new_producers": null,
"producer_signature": "SIG_K1_KiYCDLMgE6gE1nNqQQL2jEEF3VVd6iaspAePvvJMjKwgg2Yf6GiTYcznrkymAdtZUAUFh28N8r9RzX936cASKDB6JW6ga3",
"transactions": [],
"id": "00e6ee7889523875a28284effecdd1199cc960adb14c14c36cd1bd52afed6824",
"block_num": 15134328,
"ref_block_prefix": 4018438818
}
获取到 timestamp : 2022-04-27T09:08:08
- 签订交易
应用 EOSIO 提供的签名工具实现签名:启动 keosd 后,才会提供签名服务
curl -X POST POST 'http://192.168.1.46:8800/v1/wallet/sign_transaction' \
-d '[
{
"expiration": "2022-04-27T10:08:08",
"ref_block_num": 61048,
"ref_block_prefix": 4018438818,
"max_net_usage_words": 0,
"max_cpu_usage_ms": 0,
"delay_sec": 0,
"context_free_actions": [],
"actions": [
{
"account": "helailiang14",
"name": "hi",
"authorization": [
{
"actor": "helailiang14",
"permission": "active"
}
],
"data": "00408a97721aa36a"
}
],
"transaction_extensions": [],
"signatures": [],
"context_free_data": []},
["EOS6F6PRkSaPyijTDBYskFbsxpGz53JMTFbEhua94fQEyf7pAMc7Y"],
"9b4c6015f8b73b2d7ee3ebd92d249a1aba06a614e9990dcf54f7cf2e3d5172e1"
]'
------------------
return :
{
"expiration":"2022-04-27T10:08:08",
"ref_block_num":61048,
"ref_block_prefix":4018438818,
"max_net_usage_words":0,
"max_cpu_usage_ms":0,
"delay_sec":0,
"context_free_actions":[ ],
"actions":[
{
"account":"helailiang14",
"name":"hi",
"authorization":[
{
"actor":"helailiang14",
"permission":"active"
}
],
"data":"00408a97721aa36a"
}
],
"transaction_extensions":[ ],
"signatures":["SIG_K1_K2AzV2Pk4SP3PQhcdQ1bYgGZgr7PUUcJkAGowvncFV1ngrZufeCQpveAUBRYvNA5uyxFk2hKiot3Mu7FCW5rqqeoU5SVTo"],
"context_free_data":[]}
•expiration 过期工夫。这里将 timestamp 加上了 60 分钟.
•ref_block_num: 由第二步返回的 head_block_id 16 进制的 而后字段截取前八位低 4 位 转 10 进制,ee78 ==> 61048
•ref_block_prefix:由第二步返回的 head_block_id 16 进制的 而后字段截取 16 到 24 而后两个字节反转(a28284ef 反转为 ef8482a2)转 10 进制, ef8482a2 ==> 4018438818
•account 合约名称, 即部署合约的账户
•name 调用的合约办法。
•actor 调用者。签名者
•data:第一步生成的 bin 字符串
•permission 应用的权限类型
•EOS6F6PRkSaPyijTDBYskFbsxpGz53JMTFbEhua94fQEyf7pAMc7Y:签订此交易的公钥。实际上是由钱包中对应的私钥来签
•9b4c6015f8b73b2d7ee3ebd92d249a1aba06a614e9990dcf54f7cf2e3d5172e1: 是第二步获取的 chain_id
•
•signatures: 签名后果 SIG_K1_K2AzV2Pk4SP3PQhcdQ1bYgGZgr7PUUcJkAGowvncFV1ngrZufeCQpveAUBRYvNA5uyxFk2hKiot3Mu7FCW5rqqeoU5SVTo
- 打包交易
应用 cleos convert pack_transaction 将交易报文转换成 packed 格局
cleos convert pack_transaction '{"expiration":"2022-04-27T10:08:08","ref_block_num":61048,"ref_block_prefix":4018438818,"max_net_usage_words": 0,"max_cpu_usage_ms": 0,"delay_sec": 0,"context_free_actions": [],"actions": [
{
"account": "helailiang14",
"name": "hi",
"authorization": [
{
"actor": "helailiang14",
"permission": "active"
}
],
"data": "00408a97721aa36a"
}
],
"transaction_extensions": []}'
------------------
return:{"signatures": [],
"compression": "none",
"packed_context_free_data": "","packed_trx":"0816696278eea28284ef000000000140029bc64567a26a000000000000806b0140029bc64567a26a00000000a8ed32320800408a97721aa36a00"
}
packed_trx: 为交易报文的 packed 格局
- 提交交易
curl -X POST 'https://opbningxia.bsngate.com:18602/api/{您的凋谢联盟链我的项目 ID/rpc/v1/chain/push_transaction' \
-d '{"signatures": ["SIG_K1_K2AzV2Pk4SP3PQhcdQ1bYgGZgr7PUUcJkAGowvncFV1ngrZufeCQpveAUBRYvNA5uyxFk2hKiot3Mu7FCW5rqqeoU5SVTo"],"compression":"none","packed_context_free_data":"",
"packed_trx": "0816696278eea28284ef000000000140029bc64567a26a000000000000806b0140029bc64567a26a00000000a8ed32320800408a97721aa36a00"
}'
------------------
return:
{
"transaction_id":"a69d03f6b1bab4bd8908124eef5e59d3e47df4063e697a07487308cde63a9f79",
"processed":{
"id":"a69d03f6b1bab4bd8908124eef5e59d3e47df4063e697a07487308cde63a9f79",
"block_num":15136664,
"block_time":"2022-04-27T09:27:36.500",
"producer_block_id":null,
"receipt":{
"status":"executed",
"cpu_usage_us":272,
"net_usage_words":13
},
"elapsed":272,
"net_usage":104,
"scheduled":false,
"action_traces":[
{
"action_ordinal":1,
"creator_action_ordinal":0,
"closest_unnotified_ancestor_action_ordinal":0,
"receipt":{
"receiver":"helailiang14",
"act_digest":"31ff1ecb2b0b0c89911b74c7930f08ecfefbd24ba59ef30a905d44068d2d8910",
"global_sequence":15199315,
"recv_sequence":2,
"auth_sequence":[
[
"helailiang14",
4
]
],
"code_sequence":1,
"abi_sequence":1
},
"receiver":"helailiang14",
"act":{
"account":"helailiang14",
"name":"hi",
"authorization":[
{
"actor":"helailiang14",
"permission":"active"
}
],
"data":{"user":"helloworld"},
"hex_data":"00408a97721aa36a"
},
"context_free":false,
"elapsed":63,
"console":"Hello, helloworldget_self,7683817463629939264",
"trx_id":"a69d03f6b1bab4bd8908124eef5e59d3e47df4063e697a07487308cde63a9f79",
"block_num":15136664,
"block_time":"2022-04-27T09:27:36.500",
"producer_block_id":null,
"account_ram_deltas":[ ],
"account_disk_deltas":[ ],
"except":null,
"error_code":null,
"return_value_hex_data":"","inline_traces":[]}
],
"account_ram_delta":null,
"except":null,
"error_code":null
}
}
signatures: 为第 4 步签名的后果
packed_trx: 为第 5 步的报文转换后果
- 查问表数据
curl -X POST 'https://opbningxia.bsngate.com:18602/api/{您的凋谢联盟链我的项目 ID/rpc/v1/chain/get_table_rows' \
-d'{"code":"helailiang14","table":"friends","scope":"helailiang14","json": true}'
------------------
return:
{
"rows":[
{
"friend_name":"helloworld",
"visit_time":1651051656
}
],
"more":false,
"next_key":"","next_key_bytes":""
}
数据 [helloworld] 曾经写到 table 中
References
[1] BSN: https://bsnbase.com/
[2] bsn: https://bsnbase.com/p/home/Op…