中移鏈(基於EOS)實戰:如何呼叫RPC介面組裝交易、簽名、上鍊以及查詢上鍊結果

BSN研習社發表於2022-05-06

id:BSN_2021

公眾號:BSN研習社

紅棗科技何來亮

背景:今年3月開放聯盟鏈“中移鏈”在區塊鏈服務網路( BSN [1])中完成適配並上線釋出,吸引了大批開發者,部分開發者提出了一些共性問題

目的:本篇文章是為了讓讀者瞭解如何在中移鏈(基於EOS)上呼叫RPC介面組裝交易、簽名、上鍊以及查詢上鍊結果

適用物件:適用於BSN開放聯盟鏈--中移鏈(基於EOS)開發者

1.準備

  • 需要現在 bsn [2] 建立專案和建立一個賬戶,可以參考:

  • 可以獲取到eos 端點:

  • 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   '{您的開放聯盟鏈專案ID/rpc/v1/chain/abi_json_to_bin' \
-d '{
    "code": "helailiang14",
    "action": "hi",
    "args": {
        "user": "helloworld"
    }
}'
------------------
return
 
{"binargs":"00408a97721aa36a"}

2.獲取當前最新的區塊編號

curl   GET '{您的開放聯盟鏈專案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 '{您的開放聯盟鏈專案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 '{您的開放聯盟鏈專案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 '{您的開放聯盟鏈專案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: 
[2] bsn:  p/home/Openalliance/projectManagement


來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/70012206/viewspace-2892513/,如需轉載,請註明出處,否則將追究法律責任。

相關文章