中移链(基于EOS)实战:如何调用RPC接口组装交易、签名、上链以及查询上链结果

id:BSN_2021
公众号:BSN研习社
红枣科技何来亮

背景:今年3月开放联盟链“中移链”在区块链服务网络(BSN[1])中完成适配并上线发布,吸引了大批开发者,部分开发者提出了一些共性问题

目的:本篇文章是为了让读者了解如何在中移链(基于EOS)上调用RPC接口组装交易、签名、上链以及查询上链结果

适用对象:适用于BSN开放联盟链--中移链(基于EOS)开发者

1. 准备

•需要现在bsn[2]创建项目和创建一个账户,可以参考:https://bsnbase.com/static/tmpFile/bzsc/openper/7-3-6.html

•可以获取到eos 端点:https://opbningxia.bsngate.com:18602/api/aecb28acfd154cfeb90d0b6a8ecab1e7/rpc     

•eos账户/合约地址:helailiang14

•为账户购买足够的资源(cpu、net、ram)

•安装EOSIO开发环境:需要安装cleos和keosd, 可以参考:https://developers.eos.io/welcome/latest/getting-started-guide/local-development-environment/installing-eosio-binaries •部署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"}

  2. 获取当前最新的区块编号


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 

 3. 根据区块编号获取区块详情


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

     4. 签署交易

使用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

 5. 打包交易

使用 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 格式

      6. 提交交易


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步的报文转换结果

      7. 查询表数据


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/Openalliance/projectManagement

本图文内容来源于网友网络收集整理提供,作为学习参考使用,版权属于原作者。
THE END
分享
二维码

)">
< <上一篇
下一篇>>