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

一: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 "";
        }
    }
}
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,937评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,503评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,712评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,668评论 1 276
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,677评论 5 366
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,601评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,975评论 3 396
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,637评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,881评论 1 298
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,621评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,710评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,387评论 4 319
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,971评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,947评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,189评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 44,805评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,449评论 2 342

推荐阅读更多精彩内容