美文网首页
c++之通过JsonRpc与以太坊交互

c++之通过JsonRpc与以太坊交互

作者: 朵耳 | 来源:发表于2019-10-30 10:35 被阅读0次

    一:VS2019配置curl库

    1、下载curl安装包并解压

    进入https://curl.haxx.se/download.html下载curl库,解压得到文件夹【curl-7.65.3】

    image.png
    2、编译curl

    1)双击运行【curl-7.65.3】文件夹下的【buildconf.bat】
    2)打开VS2019自带的命令提示符

    image.png 3)进入【curl-7.65.3\winbuild】文件夹下
    4)输入命令编译
    nmake /f Makefile.vc mode=dll VC=16 MACHINE=x86 DEBUG=yes
    [图片上传中...(image.png-9a6b9e-1567388398889-0)]
    命令 释义
    mode static表示静态编译,dll表示动态编译(在我的使用中,静态编译后的项目执行报错,所以建议使用动态编译,下文也均是动态编译的属性配置)
    VC VC后面的数字表示编译的libcurl和VS相对应的版本号,VS2019的VC版本号是VC16
    MACHINE x64表示编译64位环境使用的libcurl,x86表示编译32位环境使用的libcurl。我的VS是x86版本。
    debug 如果需要debug版,将“DEBUG=no”改为“DEBUG=yes”,DEBUG=no”即release版本
    image.png 5)编译完成后,会在【curl-7.65.3\builds】文件夹下生成三个文件夹,使用【libcurl-vc16-x86-debug-dll-ipv6-sspi-winssl】文件夹就可以,另外两个文件夹的用途暂不知 image.png
    3、为你的项目配置curl
    1)选择对应的平台和版本 image.png

    2)选择【你的项目】->【属性】
    3)选择【配置属性】->【VC++目录】->【包含目录】->添加curl-7.65.3\builds\libcurl-vc16-x86-debug-dll-ipv6-sspi-winssl\include文件夹
    4)选择【配置属性】->【VC++目录】->【库目录】->添加curl-7.65.3\curl-7.65.3\builds\libcurl-vc16-x86-debug-dll-ipv6-sspi-winssl\lib文件夹
    5)选择【配置属性】->【c/c++】->【代码生成】->【运行库】,选择【MTd/MDd】
    6)选择【配置属性】->【链接器】->【常规】->【附加库目录】,添加curl-7.65.3\curl-7.65.3\builds\libcurl-vc16-x86-debug-dll-ipv6-sspi-winssl\lib文件夹
    7)选择【配置属性】->【链接器】->【输入】->【附加依赖项】,添加lib文件:libcurl_debug.lib(编译生成的.lib文件,在curl-7.65.3\curl-7.65.3\builds\libcurl-vc16-x86-debug-dll-ipv6-sspi-winssl\lib文件夹下)
    8)点击【应用】完成配置

    二:JsonRpc与以太坊交互

    Json解析可参考文章:

    //eth_connect.h文件
    #include<curl/curl.h>
    #include <string>
    #include <json/json.h>
    using namespace std;
    
    CURL* curl;
    CURLcode cres;
    
    size_t write_data_a(void* buffer, size_t size, size_t nmemb, void* userp) {
        char* d = (char*)buffer;
        char* u = (char*)userp;
    
        strcpy(u, d);
        return nmemb;
    }
    bool setCurl(char* jm, struct curl_slist* headers, char* r_header, char* r_result) {
        curl = curl_easy_init();
        headers = curl_slist_append(headers, "Content-Type: application/json");
        char* body_str_json = jm;//"{\"jsonrpc\":\"2.0\",\"method\":\"personal_newAccount\",\"params\":[\""+psw+"\"],\"id\":1}";
        //响应头
        string address = "http://127.0.0.1";
        int port = 8545;
        string post_url = address + ":" + to_string(port);
    
        if (curl) {
            //设置post请求的url地址
            curl_easy_setopt(curl, CURLOPT_URL, post_url.c_str());
            //设置HTTP头
            curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers);
            //设置发送超时时间
            curl_easy_setopt(curl, CURLOPT_TIMEOUT, 1);
            curl_easy_setopt(curl, CURLOPT_POSTFIELDSIZE, strlen(body_str_json));
            curl_easy_setopt(curl, CURLOPT_POSTFIELDS, body_str_json);
            //设置返回头
            curl_easy_setopt(curl, CURLOPT_HEADERFUNCTION, &write_data_a);
            curl_easy_setopt(curl, CURLOPT_HEADERDATA, r_header);
            //设置响应体
            curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, &write_data_a);
            curl_easy_setopt(curl, CURLOPT_WRITEDATA, r_result);
            return true;
        }
        return false;
    }
    
    char* getEthereumInformation(string request) {
        curl_global_init(CURL_GLOBAL_ALL);
        cres = CURLE_OK;
        char* r_header = new char[256], * r_result = new char[2048];
        struct curl_slist* headers = NULL;
    
        //string tmp = "{\"jsonrpc\":\"2.0\",\"method\":\"eth_blockNumber\",\"params\":[],\"id\":1}";
    
        char* body_str_json = new char[strlen(tmp.c_str()) + 1];
        strcpy(body_str_json, tmp.c_str());
    
        if (setCurl(body_str_json, headers, r_header, r_result)) {
            //执行单条请求
            //设置返回头
            curl_easy_setopt(curl, CURLOPT_HEADERFUNCTION, &write_data_a);
            curl_easy_setopt(curl, CURLOPT_HEADERDATA, r_header);
            //设置响应体
            curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, &write_data_a);
            curl_easy_setopt(curl, CURLOPT_WRITEDATA, r_result);
            cres = curl_easy_perform(curl);
            curl_slist_free_all(headers);
            //这个调用用来结束一个会话.与curl_easy_init配合着用
            curl_easy_cleanup(curl);
            //在结束libcurl使用的时候,用来对curl_global_init做的工作清理。类似于close的函数
            curl_global_cleanup();
            return r_result;
        }
        return 0;
    }
    
    //test.cpp(主函数)
    #include"eth_connect.h"
    using namespace std;
    int main() {
            //获取区块链当前区块高度
            string getBlockHeightJson = "{\"jsonrpc\":\"2.0\",\"method\":\"eth_blockNumber\",\"params\":[],\"id\":1}";
            char* getBlockHeight_ResultJson = getEthereumInformation(getBlockHeightJson);
            //返回的json数据格式:{"id":83,"jsonrpc" : "2.0","result" : "0x4b7" // 1207}
            //解析Json数据
            string HexBlockHeight = ReadJson(getBlockHeight_ResultJson, "result");
            //int height= HexStringToInt(HexBlockHeight);
            //HexBlockHeight = "0x" + dec2hex(round, 8);
    
            //根据blockNumber获取block信息(blockHash)
            //HexBlockHeight = "0x9" ;
            string getBlockByNumberJson = "{\"jsonrpc\":\"2.0\",\"method\":\"eth_getBlockByNumber\",\"params\":[\"" + HexBlockHeight + "\", true],\"id\":1}";
            char* getBlockByNumber_ResultJson = getEthereumInformation(getBlockByNumberJson);
            string BlockHash = readJson(getBlockByNumber_ResultJson);
            //string BlockHashShort = BlockHash.substr(0, 15);
            //strcpy(seed, BlockHashShort.c_str());
            curl_global_cleanup();
        return 0;
    }
    string ReadJson(string str, string keyOfstr)
    {
        //示例字符串
        /*string result = "{\"id\":83,\"jsonrpc\" : \"2.0\",\"result\" : \"0xc94\" }";*/
        Json::Reader reader;
        Json::Value root;
        //从字符串中读取数据
        if (reader.parse(str, root))
        {
            std::string result = root[keyOfstr].asString();
    
            return result;
        }
        return "";
    }
    //读取区块hash值,响应结果为:
    //{
    //"id":1,
    //"jsonrpc" : "2.0",
    //"result" : {
    //  "hash":"0xc6ef2fc5426d6ad6fd9e2a26abeab0aa2411b7ab17f30a99d3cb96aed1d1055b",
    //      "nonce" : "0x",
    //      "blockHash" : "0xbeab0aa2411b7ab17f30a99d3cb9c6ef2fc5426d6ad6fd9e2a26a6aed1d1055b",
    //      "blockNumber" : "0x15df", // 5599
    //      "transactionIndex" : "0x1", // 1
    //      "from" : "0x407d73d8a49eeb85d32cf465507dd71d507100c1",
    //      "to" : "0x85h43d8a49eeb85d32cf465507dd71d507100c1",
    //      "value" : "0x7f110", // 520464
    //      "gas" : "0x7f110", // 520464
    //      "gasPrice" : "0x09184e72a000",
    //      "input" : "0x603880600c6000396000f300603880600c6000396000f3603880600c6000396000f360",
    //}
    //}
    string readJson(string str) {
        int32_t index = str.find("{");
        if (-1 != index) {
            string resultJson = str.substr(index, str.size() - index);
            Json::Reader reader;
            Json::Value value;
            if (reader.parse(resultJson, value)) {
                if (!value["result"].isNull()) {
                    Json::Value result = value["result"];
                    if (!result["hash"].isNull()) {
                        const char* hash = result["hash"].asCString();
                        //memcpy(plat_user->nick_name_, name, strlen(name)); 
                        return hash;
                    }
                }
                return "";
            }
        }
    }
    

    相关文章

      网友评论

          本文标题:c++之通过JsonRpc与以太坊交互

          本文链接:https://www.haomeiwen.com/subject/bpifyctx.html